Skip to content

Commit db11d4d

Browse files
committed
Release v1.25.0 — sanitized source snapshot (2026-07-24)
1 parent b303ddf commit db11d4d

220 files changed

Lines changed: 2435 additions & 535 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22

33
All notable changes to SuperBased Observer are documented here.
44

5+
## [1.25.0] — 2026-07-24
6+
7+
### Added
8+
9+
- **feat(terminal): dashboard-launched terminals joinable by default.**
10+
`/api/attach/sessions` widened to every live daemon-owned run kind
11+
(fresh/handoff/attach/resume) — a terminal launched from the dashboard is
12+
now itself a Jump-in candidate, not just an `--attach` session. A handoff
13+
terminal's row keys by the FORKED session (not the source it continued
14+
from), so it's joined from the fork's session detail once correlation links
15+
it. `JumpInButton`'s copy and newest-row selection (picking the most
16+
recently created live row when more than one matches a session) were
17+
updated to match the wider row set.
18+
- **feat(attach): attach-by-default for all 19 CLI launchers.** Every
19+
`observer <verb>` launcher (claude, codex, opencode, cursor, copilot-cli,
20+
kilo, cline-cli, hermes, gemini, openclaw, pi, antigravity-cli, qwen, kiro,
21+
grok, kimi, devin, qoder, goose) now attaches by default the same way
22+
claude/codex have — a shared launcher gate plus 19 new integration-registry
23+
Attach rows (tool key → launcher verb). Auto-resume-on-daemon-restart stays
24+
gated to the two tools with a verified native resume (claude, codex) — every
25+
other launcher gets an honest degraded-mortality notice instead (a daemon
26+
restart ends the session outright; `observer <verb> --continue-from
27+
<session-id>` is the manual fork fallback). Proxy env forwarding and
28+
`[terminal.attach].route_proxy` / `--no-proxy` remain claude/codex-scoped —
29+
every other tool's daemon-spawned inner launcher handles its own
30+
base-URL routing itself. Note the attached child inherits the DAEMON's
31+
environment, not the launching shell's — a credential exported only in the
32+
launching shell won't reach it (config-file/OAuth auth unaffected; export
33+
it where `observer start` runs, or use `--no-attach`). `JumpInButton`'s verb map extended to cover
34+
all 19 tools.
35+
536
## [1.24.1] — 2026-07-24
637

738
### Added

browser-extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "SuperBased Observer — Browser Capture",
4-
"version": "1.24.1",
4+
"version": "1.25.0",
55
"description": "Opt-in, passive observability of your own AI chatbot web usage (ChatGPT, Claude, Perplexity, Gemini, Copilot). Captures per-turn metadata + estimated tokens locally; nothing leaves your machine except to your local observer daemon.",
66
"minimum_chrome_version": "111",
77
"permissions": [

cmd/observer/antigravity.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ func newAntigravityCmd() *cobra.Command {
3030
carry string
3131
fromMessage int
3232
fromTime string
33+
attach *bool
34+
noAttach *bool
3335
)
3436
cmd := &cobra.Command{
3537
Use: "antigravity-cli [-- agy-args...]",
@@ -46,6 +48,27 @@ func newAntigravityCmd() *cobra.Command {
4648
"to separate observer flags from agy flags. NEVER touches API keys.",
4749
SilenceErrors: true,
4850
RunE: func(cmd *cobra.Command, args []string) error {
51+
// Attach gate (attach-all-launchers): default-on attach hands the PTY
52+
// to the daemon. Seed-only spec (agy is native-exempt — no proxy env,
53+
// no escape-hatch flag). No -p/--prompt headless predicate: this
54+
// launcher only grounds -i/--prompt-interactive + a bare positional
55+
// seed, so a headless one-shot flag is NOT grounded here — the
56+
// handoff-fork family is the only incompatible mode (both-TTY guard
57+
// covers scripted runs).
58+
outcome, aErr := launcherAttach(cmd.Context(), launcherAttachSpec{
59+
tool: "antigravity-cli",
60+
configPath: configPath,
61+
flagAttach: *attach,
62+
flagNoAttach: *noAttach,
63+
incompatible: continueFamilyEngaged(continueFrom, carry, fromMessage, fromTime),
64+
passthrough: antigravityAttachPassthrough(binPath),
65+
toolArgs: args,
66+
stderr: cmd.ErrOrStderr(),
67+
})
68+
if outcome.handled {
69+
return aErr
70+
}
71+
4972
bin, err := resolveToolBin("antigravity-cli", binPath, "--agy-path", configPath, cmd.ErrOrStderr())
5073
if err != nil {
5174
return err
@@ -92,6 +115,17 @@ func newAntigravityCmd() *cobra.Command {
92115
cmd.Flags().StringVar(&carry, "carry", "", "Carry mode for --continue-from: metadata|distilled|distilled_tail|full|full_cache (default from [handoff] config)")
93116
cmd.Flags().IntVar(&fromMessage, "from-message", 0, "With --continue-from: fork after this 1-based transcript message (default: last message)")
94117
cmd.Flags().StringVar(&fromTime, "from-time", "", "With --continue-from: fork after the last message at or before this RFC3339 time")
118+
attach, noAttach = registerAttachFlags(cmd, "antigravity-cli")
95119
cmd.Flags().SetInterspersed(false)
96120
return cmd
97121
}
122+
123+
// antigravityAttachPassthrough forwards the --agy-path wrapper flag to the
124+
// daemon-spawned inner `observer antigravity-cli` launcher when set (nil
125+
// otherwise).
126+
func antigravityAttachPassthrough(agyPath string) []string {
127+
if agyPath != "" {
128+
return []string{"--agy-path", agyPath}
129+
}
130+
return nil
131+
}

cmd/observer/attach_client.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,24 @@ type attachLaunch struct {
7777

7878
// nativeResumeHint composes the daemon-exit resume guidance from the tool's
7979
// grounded ResumeSpec (session-attach design §2.4). When native resume is not
80-
// yet grounded it degrades to a generic, honest phrase rather than asserting a
81-
// resume command the tool may not support. Dispatch is on the ResumeSpec shape,
82-
// never a tool-name branch (CLAUDE.md #3).
80+
// yet grounded — the ResumeNone case that now covers 17 of the 19 attachable
81+
// launchers (attach-all-launchers) — it degrades HONESTLY: for a launchable
82+
// tool it points at the manual `observer <verb> --continue-from <id>` handover
83+
// fork (the real mortality backstop for a daemon-restart-ends-the-session
84+
// tool), and only falls back to the fully-generic phrase when even the launch
85+
// verb is unknown. Dispatch is on the capability SHAPE (ResumeSpec kind +
86+
// Handoff.Launch presence), never a tool-name branch (CLAUDE.md #3). This is
87+
// the ONE seam where the "daemon restart = session over" reality lands for a
88+
// ResumeNone tool — reportAttachResult's daemon-exit / conn-lost / input-stall
89+
// branches interpolate it.
8390
func nativeResumeHint(capab integration.Capability) string {
8491
if capab.Resume.Kind != integration.ResumeNative || capab.Resume.Subcommand == "" {
92+
if capab.Handoff.Launch != nil && capab.Handoff.Launch.Subcommand != "" {
93+
return fmt.Sprintf(
94+
"start a new session (`observer %s --continue-from <session-id>` carries a distilled handover)",
95+
capab.Handoff.Launch.Subcommand,
96+
)
97+
}
8598
return "resume it natively to continue"
8699
}
87100
switch capab.Resume.IDMechanism {
@@ -103,20 +116,25 @@ func nativeResumeHint(capab integration.Capability) string {
103116
//
104117
// - --no-proxy-route when the escape hatch is engaged (the inner launcher
105118
// then skips base-URL / `-c openai_base_url` injection);
106-
// - --proxy <url> when the operator overrode the proxy URL;
119+
// - <proxyFlag> <url> when the operator overrode the proxy URL — the flag
120+
// NAME is the inner launcher's own proxy-override spelling (`--proxy` for
121+
// most, `--proxy-url` for hermes/pi), passed in so shared code never
122+
// branches on tool identity (CLAUDE.md #3); emitted only when BOTH
123+
// proxyFlag and proxyOverride are non-empty (a seed-only launcher with no
124+
// proxy flag passes proxyFlag="" and the override is dropped);
107125
// - --config <path> when the outer invocation used a non-default config;
108126
// - passthrough... launcher-specific wrapper flags the inner launcher
109127
// should honor (e.g. --claude-path/--codex-path, --no-app-server-check),
110128
// enumerated explicitly by each launcher (B2-6);
111129
// - -- <toolArgs...> the operator's trailing tool args (`observer codex
112130
// --attach -- --model X`), so launcher state is not dropped.
113-
func attachExtraArgs(noProxyRoute bool, proxyOverride, configPath string, passthrough, toolArgs []string) []string {
131+
func attachExtraArgs(noProxyRoute bool, proxyOverride, proxyFlag, configPath string, passthrough, toolArgs []string) []string {
114132
var args []string
115133
if noProxyRoute {
116134
args = append(args, "--no-proxy-route")
117135
}
118-
if proxyOverride != "" {
119-
args = append(args, "--proxy", proxyOverride)
136+
if proxyOverride != "" && proxyFlag != "" {
137+
args = append(args, proxyFlag, proxyOverride)
120138
}
121139
if configPath != "" {
122140
args = append(args, "--config", configPath)

cmd/observer/attach_client_unix.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ func runAttachSession(ctx context.Context, in attachLaunch) error {
7777
}
7878
subcommand := capab.Attach.Subcommand
7979

80+
// canAutoResume gates the daemon-death AUTO-resume loop on the tool's native
81+
// resume capability (attach-all-launchers §3). Only a ResumeNative tool has
82+
// an inner launcher that registers `--resume` and can reattach its REAL
83+
// transcript, so injectResumeArg's `--resume <id>` argv is only parseable
84+
// there. For the 17 ResumeNone launchers a daemon restart ENDS the session
85+
// (honest mortality) — offerAutoResume/resumeSpawn stay unreachable and the
86+
// ResumeNone hint (nativeResumeHint → `--continue-from`) lands instead.
87+
// Dispatch on the capability SHAPE, never a tool-name branch (CLAUDE.md #3).
88+
canAutoResume := capab.Resume.Kind == integration.ResumeNative
89+
8090
// Attach drives a live TUI: require a real terminal on both ends.
8191
stdinFd := int(os.Stdin.Fd())
8292
stdoutFd := int(os.Stdout.Fd())
@@ -141,9 +151,12 @@ func runAttachSession(ctx context.Context, in attachLaunch) error {
141151
}
142152

143153
// Daemon-death. Auto-resume only with a REAL correlated id (the abstain
144-
// rule — no fabricated target) and within the retry cap; otherwise the
145-
// honest resume hint.
146-
if currentID == "" || autoResumes >= maxAutoResumes {
154+
// rule — no fabricated target), a tool that can natively resume
155+
// (canAutoResume — a ResumeNone tool's inner launcher can't parse the
156+
// injected `--resume`), and within the retry cap; otherwise the honest
157+
// resume hint (nativeResumeHint degrades to `--continue-from` for a
158+
// ResumeNone launcher).
159+
if currentID == "" || !canAutoResume || autoResumes >= maxAutoResumes {
147160
return reportAttachResult(in.stderr, subcommand, capab, res.status, res.attachErr)
148161
}
149162
if !offerAutoResume(ctx, in.stderr, sockPath, subcommand, currentID, attachsock.Dial) {

cmd/observer/attach_host.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,17 @@ func validateAttachCapability(req attachsock.SpawnRequest) error {
248248
return fmt.Errorf("attach: subcommand %q does not match tool %q's grounded attach subcommand %q",
249249
req.Subcommand, req.Tool, capab.Attach.Subcommand)
250250
}
251+
// Resume defense in depth (attach-all-launchers §3): a socket client is
252+
// untrusted, so refuse a resume spawn (manual --resume OR an AutoResume) for
253+
// a tool with no grounded native resume. The 17 ResumeNone launchers now
254+
// attachable have no `--resume` argv, so composing one for their inner
255+
// launcher would fail with a cobra unknown-flag error inside the PTY. Branch
256+
// on the capability SHAPE, never the tool name (CLAUDE.md #3). The client
257+
// gate + resumableSessionSet already prevent this; this is the daemon-side
258+
// backstop against a spoofed request.
259+
if req.ResumeSession != "" && capab.Resume.Kind != integration.ResumeNative {
260+
return fmt.Errorf("attach: tool %q has no native resume capability", req.Tool)
261+
}
251262
return nil
252263
}
253264

0 commit comments

Comments
 (0)