Commit Graph

119 Commits

Author SHA1 Message Date
Vincent Koc
b786f4a804 fix(talk): expose one transcript queue policy 2026-08-01 13:27:38 +08:00
Vincent Koc
137b65b4a9 fix(talk): stop overflow control spin 2026-08-01 13:20:42 +08:00
Vincent Koc
5188a23eb5 fix(talk): keep transcript overflow terminal 2026-08-01 13:15:56 +08:00
Vincent Koc
82c40747bd fix(talk): bound durable transcript operations 2026-08-01 13:08:02 +08:00
Vincent Koc
9cfe4ebf08 fix(talk): preserve consult errors during cleanup 2026-07-30 23:17:38 +08:00
Vincent Koc
8668ac4e6a test(talk): cover talkback queue saturation 2026-07-30 23:17:38 +08:00
Vincent Koc
46d51bb3a4 fix(talk): bound pending talkback work 2026-07-30 23:17:38 +08:00
Omar Shahine
364d8be010 feat(agents): rename scheduler agent tool cron -> automations (#114841)
* refactor(agents): route scheduler tool-name consumers through canonical identity

Introduce AUTOMATIONS_TOOL_NAME + isAutomationsToolName() in
src/agents/tools/automations-tool-name.ts as the single source of truth for
the scheduler agent tool's name, and convert every exact-name consumer:
factory descriptors, deferred-followup availability detection, add-counting,
policy deny lists, mutation classification, trusted media set, tool catalog
id, system-prompt tool order and tool-line map, sandbox deny defaults,
delegation capability map, MCP loopback probes, and local-model lean deny.

Behavior-neutral: the constant still resolves to "cron". Prepares the
rename in RFC openclaw/rfcs#50 so the flip is a one-line change with no
scattered literals.

* feat(agents): rename scheduler agent tool cron -> automations

Flip AUTOMATIONS_TOOL_NAME to "automations" and register the legacy name:

- TOOL_NAME_ALIASES gains cron -> automations, so persisted toolsAllow/
  toolsDeny lists, tool groups, and creator allowlists written before the
  rename keep matching through the same shipped mechanism as bash -> exec.
  No doctor rewrite needed.
- isAutomationsToolName() accepts legacy names so saved transcripts keep
  their mutation/replay-safety classification; MUTATING_TOOL_NAMES retains
  the legacy entry for the same reason.
- Tool label, catalog label, and tool-search keywords follow the rename
  ("cron" kept as a search synonym).
- Regression tests cover old-name policy matching (allow and deny), legacy
  transcript replay classification, and legacy creator allowlists
  normalizing to the canonical id.

Model-facing description strings still say cron; those move in the
follow-up strings PR. Part of RFC openclaw/rfcs#50 Phase 1.

* test(agents): update creator-cap expectations for canonical automations id

The creator tool surface derives from normalized live tool names, so derived
toolsAllow outputs now emit "automations". Passthrough paths without a
creator cap keep storing user input verbatim; those expectations stay on the
legacy name as stored-data coverage.

* fix(gateway): canonicalize legacy cron tool calls and restore scheduler deny protection

Review follow-ups from ClawSweeper and Codex on the rename (RFC 0026):

- MCP loopback tools/call resolves legacy "cron" names to the published
  automations tool without re-advertising the old name in tools/list.
- Gateway /tools/invoke canonicalizes legacy names before core-id checks and
  exact-name dispatch, so pre-rename integrations keep working.
- Security fix: dangerous-tools deny lists (owner-only HTTP deny and
  control-plane set) were keyed on the literal "cron", so the renamed tool
  silently lost default-deny and owner-only protection on the HTTP invoke
  surface. Lists now use the canonical constant, and the gateway.tools.allow
  un-deny filter normalizes both sides so legacy allow entries still lift it.
- Voice high-impact confirmation list and MCP serve creator allowlist follow
  the canonical name.

Existing cron-regression suite now proves the legacy path end to end:
default deny 404 for both names, legacy allow entry lifts the deny, and
non-owner protection holds.

* fix(agents): cover stdio MCP legacy calls, probe prompts, and prompt snapshots for the rename

- stdio MCP servers (openclaw-tools-serve / plugin tools handlers) resolve
  legacy "cron" callTool names to the published canonical tool, matching
  the HTTP loopback behavior; listTools stays canonical-only.
- Live probe prompts instruct harnesses to load/call the automations MCP
  tool (mcp__openclaw__automations) instead of the retired name.
- Prompt snapshot fixture filter follows the canonical name (the renamed
  tool had silently dropped out of the Codex dynamic-tools snapshots);
  snapshots regenerated as a clean rename.
- Type-cast the new mcp-http handler test payloads for check-test-types.

* test(agents): update tool-surface expectations for the automations rename

CI-surfaced fallout in shards not covered by the focused local runs: tool
availability, agent-config filtering, coding-tools construction,
model-provider lean policy, and skill dispatch all assert the scheduler
tool's surface name. Mock fixtures and expectations follow the canonical
id; legacy-name coverage stays in the dedicated policy/creator-cap/invoke
regression suites.

* test(gateway): update tool-resolution exclude expectations for automations rename

* test(security): update trust-model audit expectations for automations rename

* docs(agents): declare cron a permanent scheduler-tool alias per owner decision

Maintainer decision (Omar): cron is not being retired anywhere — config keys,
RPC methods, schedule syntax, and the CLI token all keep it, and the tool
alias follows the same permanent contract as bash -> exec. No doctor rewrite
and no removal window; comments updated to state the contract instead of a
deprecation plan.

* chore(agents): regen prompt snapshots after rebase onto main

* fix(agents): teach canonical automations tool in fallback guidance and reuse the identity source

Review follow-ups: the structured-list fallback still taught models the cron
tool; the cron-scope test echoed its own stub; MCP serve allowlist and voice
confirmation hardcoded the name instead of the canonical constant.

* fix(mcp): place automations identity import outside the header comment

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-07-30 07:16:13 -07:00
Peter Steinberger
dc60a9442d feat(talk): support GPT-Live over gateway relay (#115831)
* feat(talk): add GPT-Live gateway relay peer

* fix(talk): ignore duplicate GPT-Live sideband audio

* fix(openai): harden GPT-Live relay startup

* fix(deps): replace vulnerable werift ip helper

* fix(deps): scope werift ip override version

* fix(openai): normalize relay startup errors

* test(ci): register GPT-Live gateway live shard

* fix(talk): tighten GPT-Live relay readiness

* fix(talk): keep relay override helper private

* fix(talk): resolve relay readiness with launch model

* fix(openai): preserve GPT-Live media clock

* fix(talk): align GPT-Live relay readiness and framing

* fix(openai): expire pending GPT-Live reservations

* fix(openai): harden GPT-Live delegation audio

* style(openai): satisfy RTP reorder lint
2026-07-29 12:54:23 -04:00
Peter Steinberger
7441362014 feat(openai): support GPT-Live over backend WebSocket (#115622)
* feat(openai): add GPT-Live websocket bridge

* chore: defer GPT-Live changelog to release

* fix(android): preserve GPT-Live relay readiness gate

* fix(openai): normalize GPT-Live assistant completion
2026-07-29 04:15:03 -04:00
Peter Steinberger
46dd03ad0a fix(talk): add GPT-Live consult safety parity (#115562) 2026-07-29 00:55:33 -04:00
Peter Steinberger
f78ba09120 feat(talk): support GPT-Live realtime voice over ChatGPT OAuth (#115226)
* feat(gateway): share the canonical browser-origin policy with plugins

Export resolveAcceptedBrowserOrigin through openclaw/plugin-sdk/webhook-request-guards
so browser-facing plugin routes reuse the Gateway's real origin contract instead of a
narrow allowedOrigins array check. Private LAN/Tailnet Control UI loads and the
Host-header fallback were previously rejected with 403 by plugin offer routes while the
Control UI itself worked.

Moves the loopback/forwarded-header helpers to net.ts (re-exported from auth.ts) so the
guard can delegate without importing gateway auth, and migrates the Codex realtime
broker onto the shared seam.

* feat(talk): let providers own agent delegation for realtime voice

Adds an optional runAgentConsult callback to the browser-session create request and
injects the existing embedded consult runtime from talk-client, bound to the same agent
and session key the GA tool path uses. Providers whose realtime protocol delegates work
through their own control channel (rather than GA function calls) can now reach the
OpenClaw agent without a client round-trip.

Threads the effective per-session model into browser-session capability resolution so a
request-level model override selects the right capability set, and propagates a caller
abort signal into consultRealtimeVoiceAgent so a superseded delegation stops its run.

* feat(openai): support GPT-Live realtime voice over ChatGPT OAuth

Implements OpenAI's quicksilver/frameless session natively for Talk browser sessions.
The Gateway creates the WebRTC call (multipart sdp+session to https://api.openai.com/v1/live)
and owns the sideband control socket, so the browser never holds upstream credentials;
delegation.created events run through the OpenClaw agent and stream back as speakable
context appends.

Verified end-to-end on 2026-07-28 against a ChatGPT Pro OAuth profile: call create 201
with an rtc_* id and answer SDP, sideband session.started, session.close teardown.
ChatGPT OAuth is preferred over a Platform API key because /v1/live access for platform
keys is waitlist-gated; the legacy chatgpt.com backend route returns 403 for every model
and protocol version and is not used.

Accepted models are gpt-live-1-codex and gpt-live-1-boulder-alpha; the voice allowlist is
the ten values the route actually accepts, since an invalid voice is rejected at call
creation and cannot be repaired afterwards (session.update reports immutable_field_update).

* docs: document GPT-Live Talk support and its route gotchas

Records the working route and auth, the accepted models and voices, the browser-only
scope, and the two traps that cost the most time: the chatgpt.com backend route returns
403 Voice session access denied for every model, and that same 403 is also what an
invalid voice returns, so it must not be read as an account entitlement block.

* fix(openai): resolve GPT-Live CI failures

* refactor(openai): own zod runtime dependency

* fix(openai): satisfy lint and live-shard gates for GPT-Live

Types the retry-delay finish callback as Error so the rejection reason is provably an
Error at the call site; the abort path already normalized a non-Error AbortSignal reason,
but the unknown parameter type hid that from static analysis.

Registers the new GPT-Live live test in the native-live-extensions-openai shard
expectation. The shard selector already picked the file up from the real tree; only the
hardcoded list in the tooling test lagged.

* fix(openai): clean up post-rebase capability resolver

* fix(openai): preserve GPT-Live delegation fragments

* fix(openai): close GPT-Live sideband handoff race

* fix(openai): accept UUID GPT-Live call ids

* style: apply oxfmt to GPT-Live sources and Talk docs

* style: format Talk docs after rebase

* fix(openai): keep GPT-Live transcript context across ignored delegations
2026-07-28 15:05:55 -04:00
Peter Steinberger
1cbbda18c3 perf(logging): flush file transport asynchronously off the request path (#114769)
* perf(logging): flush file transport asynchronously off the request path

* fix(ci): record flushLogger surface growth and drain before log reads

- +1 public export/callable budget with annotation: logger file-transport
  flush for graceful shutdown drains; regenerate SDK API baseline
- three tests that read the log file right after logging now drain the
  async file transport first (flushLogger) instead of racing the flusher

* test: drain async log transport before reading talk and request-trace logs

* test: drain async log transport in CLI logger file tests

* test: drop unused withTempDirSync import
2026-07-27 19:40:43 -04:00
Peter Steinberger
fa6a93ac97 fix: recheck voice confirmation after tool rewrites (#114721)
* fix(security): revalidate voice confirmation params

* chore: leave changelog to release automation
2026-07-27 16:10:54 -04:00
Colin Johnson
de9ed64c29 feat(talk): enable GPT Live with Codex OAuth (#113354) 2026-07-25 20:41:27 -04:00
Peter Steinberger
4bfb26415a feat(agents): explicit per-surface agent targets + default-role materialization (#113637)
* refactor(agents): add explicit ambient target seams

* fix(doctor): materialize ambient default-agent roles

* fix(agents): satisfy dependency and docs checks

* chore: leave agent release note to release process

* test(agents): prove shared heartbeat fan-out survives doctor
2026-07-25 05:37:41 -07:00
Vincent Koc
9698d38950 refactor(plugins): rely on shared alias resolution (#113523) 2026-07-25 14:30:43 +08:00
Peter Steinberger
73bba03e4c refactor: canonicalize session delivery state (#113225)
* refactor: canonicalize session delivery state

* test: canonicalize reply persistence fixtures

* test: canonicalize talk delivery fixtures

* test: canonicalize voice session routes

* test: canonicalize attachment delivery fixtures

* test: migrate gateway delivery fixtures

* fix: skip invalid session delivery rows

* test: align delivery SDK surface gates

* fix: preserve legacy delivery precedence

* test: canonicalize heartbeat delivery fixtures

* fix: preserve delivery route prompt identity

* test: canonicalize session delivery fixtures

* fix: preserve recoverable legacy delivery routes

* fix: canonicalize remaining session state

* fix: preserve canonical session classification

* style: format delivery state changes

* test: refresh plugin SDK delivery baseline

* test: avoid mutating session fixture input

* style: simplify delivery identity check

* style: simplify delivery origin spread

* fix: preserve fresh delivery route metadata

* test: assert canonical surface route switch

* fix: canonicalize doctor file-store imports

* fix: preserve transitional delivery migration state

* fix: satisfy canonical delivery CI gates

* ci: scope GitHub App token permissions

* test: infer canonical delivery projections

* test: canonicalize ACP requester delivery fixtures

* test: canonicalize harness rollback fixture

* style: apply pinned formatter
2026-07-24 01:01:19 -07:00
Peter Steinberger
099d6351b3 refactor(sessions): canonical lineage model — creation provenance, fork ancestry, generation chain, typed row contract (#111861)
* fix(sessions): preserve spawn/fork lineage across implicit daily/idle rollover

* refactor(sessions): canonical creation model with forkSource ancestry and generation chain

* feat(sessions): stamp creation provenance across all creation paths and emit created events

* refactor(gateway): lock lineage patching, split control from navigation, add typed session-row contract

* docs(gateway): document creation provenance stamping and lineage patch tightening

* fix(sessions): keep provenance proof-only on wire fallbacks and strip node-local lineage from cron continuations

* fix(gateway): never journal a created event for session adoption

* fix(gateway): keep post-create work on adoption while gating the created event

* fix(sessions): restore trusted ensure-main provenance and stamp navigation parent at spawn

* fix(sessions): allow parentSessionKey through the direct child spawn patch

* fix(ci): break type cycles, satisfy export scan, regenerate Swift protocol models

* refactor(sessions): replace createdBy with createdActor

* fix(protocol): export session row type

* fix(sessions): preserve proven creation provenance

* fix(sessions): close lineage creation gaps

* test(sessions): align atomic spawn lineage coverage

* test(sessions): widen transcript search reconcile wait

* fix(sessions): stamp reset-created rows

* test(sessions): keep reset provenance coverage focused

* fix(sessions): journal chat-created rows

* test(ci): anchor release skill reads to repo

* test(ci): avoid cached module paths
2026-07-22 22:54:31 -04:00
Dallin Romney
635d396755 refactor(talk): run the Gateway realtime relay through the shared session harness (#112590)
* refactor(talk): adopt session harness in gateway relay

* fix(talk): preserve relay harness behavior

* style(talk): format relay barge-in call

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-22 14:40:32 -07:00
Peter Steinberger
e10d004257 feat(agents): mobile_ui agent tool (PR 3/3) (#112255)
* feat(agents): mobile_ui agent tool for Android UI control (PR 3/3)

Add a dedicated model-facing tool that drives another Android app through the
PR2 mobile.ui.observe/act node commands, completing the vertical slice
(agent -> tool -> node.invoke -> AccessibilityService).

- Mirrors the desktop computer tool's safety model: owner-only + HTTP-denied
  (dangerous-tools), raw node.invoke of mobile.ui.* redirected to this tool so
  the generic nodes tool cannot bypass it, run/tool-call idempotency, and the
  phone-arm workflow (mobile.ui.* must be explicitly armed).
- One call is observe or one act; every act automatically re-observes for
  postcondition verification and preserves the landed outcome if re-observe fails.
- Fail-closed confirmation: all state-changing acts (activate, set_text, tap,
  swipe) require confirmed=true after the model reviews the proposed effect;
  observe, scroll, wait, and navigation global_actions do not. The keyword list
  only enriches the confirmation message and is never the sole gate (a11y labels
  are localized/iconographic/coordinate-blind).
- Node selection resolves an explicit id against the full device set first
  (case-insensitively) and rejects an ineligible or ambiguous match, so an
  explicit selection can never be silently redirected to the wrong phone.
- All observed UI text is treated as untrusted; the tool description forbids
  following instructions found in app UI.

Additive; no protocol bump. mobile-ui-tool + registration + policy tests pass;
core tsgo and lint verified on Testbox. On-device drive is exercised via the
PR1/PR2 emulator proof; this PR is the agent-side tool + tests.

Follow-up: computer-tool.ts has the same latent node-resolution ordering bug
(explicit id searched only among eligible nodes); tracked separately.

* fix(agents,phone-control): migrate mobile_ui arming hints/tests to gateway.nodes.commands.allow

Match main's node-command arming rename (gateway.nodes.allowCommands ->
gateway.nodes.commands.allow / commands.deny): update the mobile_ui tool arm-hint
matchers to the gateway's current rejection strings and fix the phone-control /
tool tests to the current config shape. Production write path was already correct.

* fix(agents): register mobile_ui in owner-only denylist; trim phone-control under max-lines

- tool-resolution.exclude.test.ts: mobile_ui joins the owner-only core
  tools, so add it to the expected plugin/inherited denylists.
- phone-control: derive ArmGroup from a single ARM_GROUPS const and
  collapse parseGroup's ||-chain, dropping index.ts back under 700 lines.

* fix(agents): centralize mobile_ui global-action names; regenerate tool-display snapshot

- Extract GLOBAL_ACTION_NAMES const so the schema, action type, and
  validator share one source. This also removes the bare `name: "back"`
  type-annotation literal that scripts/tool-display.ts's name-regex was
  misreading as a phantom runtime tool.
- Regenerate apps/.../tool-display.json to add the mobile_ui display entry
  (was missing from the Swift snapshot).
2026-07-22 01:49:14 -07:00
Peter Steinberger
6f29fc88e9 refactor(sessions): migrate pure readers to read-only session accessors (#112568)
* refactor(sessions): migrate pure readers to read-only session accessors

* test(sessions): teach mocks and declarations the read-only accessors

* test(sessions): align remaining harnesses with read-only accessors
2026-07-22 01:16:35 -07:00
Peter Steinberger
6f2fa019bd fix: honor configured default agent in consults (#111749) 2026-07-20 01:43:00 -07:00
Peter Steinberger
0f95e66b7f feat(talk): add durable client voice sessions (#111216)
Live-append voice transcripts into the agent session and persist a per-agent SQLite call record across relay and client transcript paths.

Add run-scoped spoken confirmation for high-impact actions, mutation digests, bootstrap-context injection, talk.client.transcript and talk.client.close protocol methods, and Control UI adoption. This adds zero new configuration.

Co-authored-by: Clifton King <clifton@users.noreply.github.com>
2026-07-19 01:06:49 -07:00
Peter Steinberger
b75b62fb1c test(talk): isolate consult session storage (#110078) 2026-07-17 17:40:08 +01:00
WhatsSkiLL
4d3b18811e feat(android): add Wear real-time Talk controls (#109483)
* feat(android): add Wear real-time Talk controls

* fix(android): satisfy Wear Talk CI checks

* fix(talk): remove unused client language parameter

* fix(android): harden Wear realtime Talk routing

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* chore(android): refresh Wear Talk metadata

* chore(android): align native i18n baseline

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 13:46:05 +01:00
Peter Steinberger
e3618454f2 refactor(talk): add realtime voice session harness and adopt in google-meet and voice-call (#109497)
* refactor(talk): add realtime voice session harness and adopt in google-meet and voice-call

* fix(google-meet): satisfy prefer-const in realtime engine wiring
2026-07-16 21:28:44 -07:00
Peter Steinberger
a0fac37f14 feat: add OpenAI Video Talk (#109579)
* feat(talk): add OpenAI Video Talk

Co-authored-by: wuxuanshu <1064076525@qq.com>

* fix(protocol): refresh native Talk capability model

* chore(i18n): refresh control UI fallback baseline

* chore(i18n): defer locale refresh to workflow

---------

Co-authored-by: wuxuanshu <1064076525@qq.com>
2026-07-16 21:25:09 -07:00
Peter Steinberger
92146f9f80 refactor(talk): share audio-energy stats and speech-threshold gate across voice surfaces (#109466) 2026-07-16 18:10:26 -07:00
Peter Steinberger
6bea5ec113 refactor(talk): remove consult test dependency seam (#107432) 2026-07-14 04:49:11 -07:00
Peter Steinberger
b76a7f453b refactor(auto-reply): trim internal export surface (#106409)
* refactor(auto-reply): trim internal export surface

* chore(deadcode): update auto-reply export baseline
2026-07-13 06:17:20 -07:00
Peter Steinberger
6c5084f1ad feat(xai): add realtime voice provider (#106267)
* feat(xai): add realtime voice provider

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>

* fix(xai): satisfy realtime voice validation

* fix(xai): harden realtime relay boundaries

* chore: drop release-owned changelog edit

* chore(i18n): refresh native voice catalogs

* chore(i18n): refresh Control UI raw-copy baseline

* chore(plugin-sdk): refresh API baseline hashes

* chore(i18n): use canonical main catalogs

* chore(i18n): refresh realtime voice source inventory

* chore: refresh xai voice landing head [skip ci]

* chore: refresh integrated protocol artifacts [skip ci]

---------

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>
2026-07-13 05:17:24 -07:00
Peter Steinberger
e2ec8283c4 refactor(deadcode): trim mid-size src exports (#105888)
* 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
2026-07-13 00:42:56 -07:00
Peter Steinberger
1b313dc4d4 chore(tooling): enforce indexed access in core tests (#105375)
* test(tooling): enforce indexed access in core tests

* test(tui): constrain theme environment overrides

* test(doctor): enforce indexed access in migration fixtures
2026-07-12 14:29:52 +01:00
Peter Steinberger
6b95f98fe7 fix(core): make indexed access explicit across remaining src (NUIA phase 3b) (#104773)
* 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.
2026-07-11 20:47:34 -07:00
Peter Steinberger
7bf80dc2c6 chore(tooling): enforce formatting and refresh TypeScript checks (#104239)
* chore(tooling): enforce current formatter and refresh checks

* chore(tooling): keep release changelog formatter-owned

* chore(tooling): retain compatible Node type surface

* ci: enforce formatting for docs-only changes

* ci: isolate docs formatter check

* chore(tooling): apply updated lint and format rules

* chore(tooling): satisfy updated switch lint

* style(ui): apply Linux formatter layout

* test(doctor): match quiet local audio contribution

* test(doctor): assert quiet output only

* test(doctor): follow restored information contract
2026-07-11 01:09:51 -07:00
Peter Steinberger
f94a7dc183 feat(codex): supervise native Codex sessions (#104045)
* feat(codex): add native session supervision

* fix(codex): harden supervision integration

* fix(codex): preserve locked harness ownership

* fix(codex): fence native session archive

* fix(codex): revalidate archive binding ownership

* feat(codex): integrate supervision runtime

* feat(sessions): preserve harness-owned execution

* feat(sessions): persist harness ownership invariants

* feat(gateway): enforce harness-owned sessions

* feat(setup): enable detected Codex supervision

* feat(mac): expose supervised Codex sessions

* feat(ui): make Codex sessions actionable

* docs(codex): document session supervision

* test(codex): cover integration ownership

* chore(i18n): refresh supervision inventories

* fix(setup): finalize Codex activation atomically

* test(codex): narrow binding store update

* fix(sessions): preserve legacy model locks

* test(macos): serialize Codex catalog fixtures

* fix(sessions): preserve legacy lock admission

* chore(i18n): reconcile supervision metadata

* test(sessions): mark legacy lock fixture

* fix(macos): drain final Codex catalog frame

* docs: leave supervision note to release

* style(macos): satisfy Codex catalog type length

* chore: record session accessor seam owners

* fix(macos): honor configured Codex supervision

* fix(codex): preserve harness-owned model locks

* fix(codex): satisfy supervision lint gates

* chore(i18n): refresh native supervision inventory

* fix(codex): align supervision validation contracts

* fix(codex): close supervision boundary gaps

* fix(codex): preserve supervision activation contracts

* fix(codex): dispose standalone supervision runtime

* fix(codex): pin supervised source connection

* fix(plugins): bind delegated runs to exact session target

* fix(codex): scope supervised sessions to configured agents

* fix(codex): fingerprint effective supervision home

* fix(codex): normalize supervision plugin policy

* fix(codex): keep supervised bindings stable across upgrades

* fix(codex): guard all supervised binding connections

* fix(codex): preserve catalog filters and pending CAS identity

* fix(codex): preserve supervision identity for diagnostics

* fix(codex): bind uncertain commits to supervision connection

* fix(codex): satisfy supervision type boundaries

* fix(macos): reconcile current main validation

* fix(codex): handle absent runtime config in supervision

* fix(doctor): own local audio acceleration check

* fix(codex): satisfy integration lint gates

* fix(codex): satisfy lifecycle safety guards
2026-07-11 00:12:08 -07:00
Peter Steinberger
e8fcc93cd3 fix(talk): await realtime tool result delivery (#103268)
* fix(talk): await realtime tool result delivery

* fix(talk): terminally cancel queued results

* chore: keep release changelog out of PR

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-09 20:11:20 -07:00
Peter Steinberger
5f9e0e20d4 fix: scope task suggestions to supported surfaces (#102743)
* fix: make task suggestions surface-aware

* fix: honor task suggestion action scopes

* fix: align task surface compatibility types

* fix: isolate task suggestions across surfaces

* style: satisfy task selector lint

* chore: defer task suggestion release note

* test: dedupe gateway capability fixture

* test: cover combined gateway capabilities
2026-07-09 12:59:50 +01:00
xydt-tanshanshan
f0d4d4f2fc fix(talk): use truncateUtf16Safe for LLM-prompt-facing text truncation (#102477)
* fix(talk): use truncateUtf16Safe for snippet text truncation

fast-context-runtime.ts normalizeSnippet and heartbeat-events-filter.ts
buildExecEventPrompt used raw .slice(0, N), which can produce lone
surrogates when truncation boundaries cross emoji surrogate pairs.

* test(talk): cover UTF-16 snippet boundary

---------

Co-authored-by: hailory <hailory@xydigit.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-09 08:39:38 +01:00
Vincent Koc
84e5327720 fix(text): keep bounded outputs UTF-16 safe (#101355)
Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-06 21:33:24 -07:00
Martin Moellenbeck
cac05ff695 Fix realtime voice-call barge-in cancellation (#90749)
* fix voice call realtime barge-in cancellation

* chore: retrigger PR checks

* chore: retrigger PR checks

* fix voice call realtime barge-in fallback

* fix voice call provider barge-in precedence

* fix voice call speech-started fallback contract

* fix late provider barge-in queued audio clear

* fix realtime handler test raw message parsing

* chore rerun ci

* Document realtime speech-start capability

* fix voice call barge-in interruption policy

* fix(voice-call): centralize realtime barge-in

Co-authored-by: Martin Möllenbeck <martin.moellenbeck@5minds.de>

* chore(changelog): leave voice fix to release flow

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 23:30:16 +01:00
Vincent Koc
170150a306 fix(talk): quarantine unreadable realtime tool names 2026-07-05 23:34:56 +02:00
Peter Steinberger
6df0fb818d feat: add session thread management (#98510)
* feat: add session thread management

Squash of codex/thread-management (025aefc3ad1) onto origin/main:
pin/archive/rename sessions via sessions.patch, archived-aware
sessions.list, lifecycle fencing, read-only archived chat, SDK +
Swift protocol support, Control UI session management.

* refactor(ui): minimal session rows with hover-revealed management

Chat picker and sidebar recents share session-row primitives: single-line
rows, relative timestamps, rename/archive/pin revealed on hover or focus,
accent pin badge for pinned rows, and an active-run spinner in the trail
slot. Sidebar floats pinned sessions above recency via the shared
comparator and gains archive/pin actions through the unified sessions-view
patch fallback. Archive eligibility is one shared policy
(canArchiveSessionRow); the sidebar/picker active-run tooltip now uses the
real sessionsView.activeRun locale key.

* fix: align session admission with mailbox-era main

Integration fixes after rebasing onto current main: sessions_list mailbox
test expectations learn the archived/pinned row fields and archived:false
list param; gateway agent admission treats a session as deleted only when
both the requested and canonical alias sets miss it (legacy bare-main
stores and exec-approval followups read under different spellings); cron
persist tests keep a consistent store across claim-guarded persist calls;
the ACP abort hook test asserts abort propagation instead of signal
identity; drop dead lifecycle writes flagged by no-useless-assignment and
fix the promise-executor return in the codex compact test.

* fix(qa): align UI e2e and shard fixtures with redesigned session rows

Sidebar session rows are wrapper divs with an inner link now: update the
navigation browser tests and chat-flow Playwright selectors. Seed a real
per-test session store for the auto-fallback admission guard instead of
depending on leftover host files at /tmp/sessions.json. Teach the
test-projects routing fixture about the suites that newly import the
shared temp-dir helper. Document the Codex thread-format contract for
archivedAt/pinnedAt (flag derived from server-stamped timestamp, epoch ms
here vs Codex epoch seconds) at the type and in the session docs.

* test: route auto-fallback suite through temp-dir helper plans

The auto-fallback suite now imports the shared temp-dir helper for its
seeded session store, so the top-level helper routing fixture must list
it in the auto-reply plan.
2026-07-04 14:30:47 -04:00
Dallin Romney
1a04c9c2ad refactor: consolidate string reader mechanics (#99676)
* refactor: consolidate string reader mechanics

* fix: declare model catalog normalization dependency

* fix: keep model catalog dependency-free

* refactor(core): keep string readers internal
2026-07-03 18:00:07 -07:00
Dallin Romney
c7aca4f029 refactor: consolidate async timing helpers (#99721) 2026-07-03 17:58:15 -07:00
Dallin Romney
00b7eac5c3 refactor: consolidate number coercion callers (#99671)
* refactor: consolidate number coercion callers

* fix: stabilize plugin sdk surface resolution
2026-07-03 16:24:43 -07:00
Marvinthebored
b3b51b0c91 fix(anthropic): surface Discord pre-tool commentary
Route Anthropic pre-tool narration through the commentary progress lane, preserve shared channel progress defaults, and keep Discord/Telegram reasoning gates explicit.

Thanks @Marvinthebored!
2026-06-30 18:12:07 -07:00
Josh Lehman
0dfa22c6e0 refactor: add embedded run session target seam (#90439) 2026-06-23 10:08:29 -07:00
Vincent Koc
b574da57cf chore(deadcode): share levenshtein distance helper 2026-06-21 14:23:43 +08:00