* fix(browser): tab creation steals window focus during agent automation
Agent-created tabs inherited CDP's foreground default: direct CDP
Target.createTarget omitted the background flag, and the extension
relay's createTab defaulted to active:true, so every agent tab open
activated the new tab (and, on the extension driver, focused the
window), interrupting whatever the human was doing in that browser.
Direct CDP tab creation now requests background:true (agent tab
ownership/selection is target-id based and never depended on
activation), and the extension relay defaults an omitted background
to true while preserving an explicit background:false, matching the
Codex/Claude-in-Chrome model the extension driver mirrors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(browser): keep focus fix LOC-neutral
Preserve background tab creation while keeping the oversized CDP and relay modules within the current LOC ratchet.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914
* fix(browser): honor explicit CDP focus requests
Keep background-by-default automation while treating Target.createTarget focus=true as an explicit foreground request in the extension relay.
Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914
* fix(browser): preserve explicit CDP focus semantics
Apply the background-by-default automation policy only when focus is omitted, preserving focus=false foreground-tab requests as well as focus=true.
Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914
* fix(browser): preserve create target window focus
Carry the resolved CDP focus intent through the extension relay and explicitly focus the containing Chrome window when requested.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914
* style(browser): refresh relay import order
* test(secrets): use secure node exec fixtures
* test(doctor): secure exec secret fixture
* test(doctor): retain narrowed temp path
* test(secrets): secure remaining exec fixtures
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The secret target registry filtered plugin-derived entries to bundled-origin
records only, so when the Exa web providers moved into an installed plugin
package their config targets vanished: the gateway's isKnownSecretTargetId
rejected the CLI-discovered target and infer web search failed with an
unresolved SecretRef before provider I/O (regression of #82621/#82798).
Web-provider and config-contract entries now come from every active plugin
manifest record, matching what channel entries already did; entries stay
manifest-scoped (web-provider contract + sensitive hint, or declared
secretInput paths), so non-bundled origins cannot widen target paths beyond
their own declared contracts.
Fixes#104320
* fix(secrets): use resolveStateDir for .env path to cover legacy .clawdbot dir
* fix(secrets): replace override-based legacy .env test with true automatic fallback, add apply-path coverage
* fix(config-cli): emit JSON error on config get --json for missing paths
When is used with a nonexistent
path, the command emits no JSON on stdout, only a text error on stderr.
This breaks automated consumers that expect machine-readable errors.
Fix: output JSON to stdout before exit(1) when
opts.json is set. This matches the existing JSON error output pattern
already used by runConfigValidate and handleConfigMutationError.
Also re-throw synthetic exit errors in the catch block so the
--json branch's writeRuntimeJson+exit is not caught and re-emitted
as a text error.
* fix(config-cli): use typed ExitError signal instead of __exit__ string sentinel
* fix(secrets): reuse resolved stateDir for .env path in audit
* fix(secrets): pass resolved stateDir into apply .env scrubbing, add root-switch regression
* test(config-cli): migrate remaining __exit__ sentinel to ExitError
* fix(secrets): cover config and state dotenv roots
* style(secrets): format dotenv path helper
* test(secrets): track temporary directories
* test(config): expect typed exit for missing patch files
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* refactor(plugin-sdk): narrow wildcard barrels to explicit used exports
* refactor(tools): delete dead tool-planning module exposed by barrel narrowing
* fix(plugin-sdk): restore deprecation tag on OpenClawSchemaType alias
* test(agents): drop test for deleted runtime proxy module
* refactor(tools): trim descriptor types to cache consumers
* refactor(deadcode): harvest exports orphaned by barrel narrowing
* refactor(deadcode): harvest exports orphaned by barrel narrowing (rest)
* fix(agents): restore sdk imports and test markers via public predicate
* fix(plugin-sdk): named type re-exports in plugin-entry; trim types barrel precisely
* chore(plugin-sdk): account unmasked deprecated provider types in budgets
* fix(plugins): name star-only type rows for dts bundling
* fix(plugins): restore host-hook surface; unexport internal api compositions
* fix(plugins): named type imports for api composition; restore needed source exports
* fix(plugins): knip-visible type imports for registry surfaces
* test: adapt tests to privatized media and command internals
* fix(qa-lab): re-export snapshot conversation type
* style: format sessions sdk imports
* fix(plugins): restore smoke entry export; pin budgets to exact actuals
* fix(plugins): canonical smoke-entry import; drop orphaned root shims
* fix(plugins): allowlist manifest probe, repoint qa web import, drop dead browser barrels
* fix(plugin-sdk): pin codex auth marker and scaffold provider type
* fix(qa-lab): keep web-facing model-selection shim within boundary rules
* fix(plugin-sdk): preserve merged contracts through narrowed barrels
* chore(plugin-sdk): pin post-rebase surface budgets
* refactor(deadcode): trim auto-reply and CLI exports
* refactor(deadcode): trim cron and task exports
* refactor(deadcode): trim fleet and process exports
* test(deadcode): exercise live task and process seams
* test(fleet): cover stream redaction through owner module
* refactor(security): trim dead internal exports
* refactor(secrets): trim dead internal exports
* refactor(deadcode): trim remaining src exports
* refactor(deadcode): remove test-only runtime exports
* refactor(deadcode): trim pairing test exports
* refactor(deadcode): reconcile refreshed baseline
* test(auto-reply): deduplicate queue state imports
* fix(gateway): make hot reload transactional
Replace partial reload side effects with a deferred transaction that publishes config, secrets, auth, and subsystem state together, and drains in-flight reload work before shutdown.
Co-authored-by: LZY3538 <293718838+LZY3538@users.noreply.github.com>
* fix(auth): preserve state-only credential ownership
Keep derived runtime snapshots in place for main-store state mutations so order refreshes do not look like credential replacement.
* fix(gateway): close reload transaction gaps
* fix(gateway): close merged reload gaps
* chore: move reload note to PR context
* fix(gateway): exclude restart emission root
---------
Co-authored-by: LZY3538 <293718838+LZY3538@users.noreply.github.com>
* fix(core): make indexed access explicit in auto-reply, infra, and config
Part 1/3 of the src NUIA phase-3b burn-down (#104600): iteration and
destructuring over index reads, boundary guards on parsed input, and
named invariants. Config path walkers bind the path head once; SQLite
migration key handling is hoisted without query-shape changes.
* fix(core): make indexed access explicit in cli, gateway, commands, security, shared
Part 2/3: argv/token selection restructured, gateway event/attachment
invariants named, security parsers stay fail-closed (invariant
violations throw), edit-distance matrices access checked entries.
* fix(core): make indexed access explicit across remaining src surfaces
Part 3/3: channels, plugins, process, cron, plugin-sdk, media, logging,
tui, hooks, daemon, and small directories. Latent bug fixed: a tailnet
resolver could leak undefined through a string|null contract and now
fails with a descriptive local error.
* fix(core): keep optional boundaries optional after per-commit review
Review findings: expectDefined misused where absence is a legitimate
state. CLI --profile/route-args missing next tokens take their existing
miss paths; help normalization compares --help against the last
positional again; first-time plugin install spreads absent cfg.plugins;
denylist scan iterates manifest dependency entries instead of throwing
on omitted sections; tailnet resolver returns a guaranteed string at
the source instead of a caller-side undefined throw.
* refactor(core): closed-key provider labels and honest optional passthroughs
PROVIDER_LABELS becomes a satisfies-typed closed record (static reads
provably defined; dynamic lookups go through providerUsageLabel with
honest string|undefined). Status-scan overview passes its optional
params through unchanged instead of asserting them.
* fix(channels): make getChatChannelMeta honestly optional
The original signature claimed ChatChannelMeta while leaking undefined
on bundled channel id metadata drift; three of four callers already
handled absence. The return type now says so, and the one assuming
caller falls back to the raw channel label.
* fix(core): index-safety for post-rebase main drift
Covers the sqlite-sessions flip and auth-source-plan code that landed
mid-phase, plus the channel-validation test consuming the now honestly
optional getChatChannelMeta.
* refactor(channels): split chat-meta accessors along the SDK contract
getChatChannelMeta keeps its shipped plugin-SDK signature (defined for
bundled ids, fail-loud on impossible misses); new findChatChannelMeta
carries the drift-tolerant optional contract for core auto-enable and
formatting paths.
* fix(qa-channel): own channel metadata instead of a guaranteed-undefined catalog lookup
qa-channel spread getChatChannelMeta over an id that is never in the
bundled catalog, shipping an empty setup meta by accident; the fail-loud
SDK accessor exposed it. The channel now declares its metadata once.
* fix(gateway): heartbeat projection lookahead is optional at the transcript tail
expectDefined wrapped messages[i + 1] whose absence on the final message
is the normal case; the adjacent ternary already handled it. Restores
the plain optional read with an explicit guard in the pair condition.
* fix(plugin-sdk): channel plugin factory tolerates non-bundled channel ids again
createChannelPluginBase spreads bundled catalog meta for ANY channel id,
where absence is the normal case for external plugins; the resolver is
honestly optional again while the exported bundled-id accessor keeps the
fail-loud contract.
* fix(core): spreads of optional config sections stay optional
Fresh-setup and first-install paths (crestodian setup inference, hook
installs, agent config base, target agent models) legitimately lack the
section being rebuilt; spreading undefined is the shipped {} semantics.
Removes the remaining gratuitous assertion wraps found by tree audit.
* chore(lint): enforce no-floating-promises repo-wide
* feat(tooling): split DOM globals out of the Node-side typecheck program
tsconfig.core.json now compiles src/ + packages/ with lib ES2023; new
tsconfig.ui.json owns ui/ with DOM. Web-global names used by Node code
alias to canonical undici/stream-web types; highlight.js loads through a
validated narrow API because its d.ts force-includes lib.dom. Boundary,
sparse-guard, changed-lane routing, and profile lanes cover the new ui
graph.
* chore(deps): declare undici-types and teach knip about the highlight.js runtime require
* ci: retrigger dropped pull_request synchronize event
* refactor(types): derive web-global aliases from @types/node fetch globals, drop undici-types dep
* ci: retrigger after dependency guard cleared
* fix(scripts): add ui lane to changed-lanes declaration union