Commit Graph

1584 Commits

Author SHA1 Message Date
can1357 b0f1b5c0c5 Merge PR #6496: fix(ai): preserve Anthropic server-tool history (@roboomp) 2026-07-24 16:26:52 +02:00
can1357 3676b5d97f feat: implemented client usage tracking and reporting in the auth broker
- Add usage history, reporting, and client summary endpoints to the auth broker.
- Implement SQLite persistence, batching, and periodic flushing for observed client usage.
- Integrate usage reporting into the coding agent session for completed assistant messages.
- Update stats aggregator and dashboard to retrieve usage history snapshots from the broker.
2026-07-24 15:20:46 +02:00
roboomp 07fcec1e68 fix(ai): preserved Anthropic server-tool history
Persisted native server-tool calls and web-search results in assistant content, replayed them only to the issuing Anthropic provider, and retained Umans gateway filtering.

Fixes #6495
2026-07-24 08:49:43 +00:00
can1357 c1d4e38aa6 feat(coding-agent): added live session delegation with turn-based transcript display
- Added `LIVE_DELEGATION_MESSAGE_TYPE` constant and delegation message handling for voice sessions.
- Implemented turn-based transcript coalescing with user and assistant turn counters.
- Added transcript display row with normalized rendering in the live visualizer.
- Refactored controller to send delegation messages via `sendCustomMessage` with configurable frame styling.
- Removed microphone permission error reporting from silence detection logic.
2026-07-24 09:16:50 +02:00
can1357 c9c0882724 feat(audio): replaced Chromium browser audio with native audio stack
- Switched from `miniaudio` to `maudio` Rust crate and added `AudioCapture` and `AudioPlayback` native classes.
- Removed browser-side audio infrastructure including Web Audio API, audio worklet processor, and WebRTC runtime.
- Migrated STT recorder and transcriber modules to use native `AudioCapture` with callback-based streaming.
- Replaced streaming audio player with native `AudioPlayback` that writes PCM directly without TypeScript intermediaries.
- Removed ffmpeg, wav, and platform-specific playback commands from the audio toolchain.
2026-07-24 08:54:16 +02:00
can1357 af9e8546a9 feat: implemented session account selection and pinning via slash command
- Add `pinSessionOAuthAccount` storage method and active account flag to the auth storage API.
- Introduce session account selector component, controller logic, and interactive mode delegation.
- Implement the `/session pin` builtin slash command with text listing and account pinning capabilities.
- Add unit tests covering session account selection, component navigation, and command handling.
2026-07-24 07:57:55 +02:00
can1357 4f97aea2db Merge PR #6468: fix(tools): closed spilled output descriptors on error/abort paths (@roboomp) 2026-07-24 06:51:36 +02:00
roboomp a39dbc9b44 fix(tools): guarantee spill sink close when tail replay fails
#finalizeFile marked the sink finalized then ran the capped-artifact tail
replay before closing. A write error during that replay threw before
sink.end(), and because #finalized was already set the executor finally
paths calling dispose() could not retry the close, leaking the descriptor
and masking the original tool error.

Moved sink.end() into a finally around the tail replay and swallowed both
the replay and close errors so the descriptor is always released and
dispose() never throws.
2026-07-24 03:53:21 +00:00
roboomp 31098f9248 fix(tools): closed spilled output descriptors on error/abort paths
OutputSink.dump() was the only path that closed the spill Bun.FileSink.
The bash and Python executors re-throw on failure and their finally
blocks never closed the sink, so any large-output command that errored
leaked the artifact descriptor until an unrelated read (e.g. a SKILL.md
load) hit EMFILE.

Added an idempotent OutputSink.dispose() that closes the sink exactly
once (awaiting any in-flight sink creation, guarding post-finalize
resurrection) and wired it into every executor's finally block.

Fixes #6463
2026-07-24 03:44:12 +00:00
can1357 681d7daf65 feat(computer): unified native addon, /computer toggle, function tool
- Replaced the separate GUI-linked pi_natives.desktop.linux-x64 addon with
  a pure-Rust X11 backend (x11rb RustConnection capture via RandR/GetImage,
  XTest input with keysym mapping) compiled into the core addon on every
  published target; Linux arm64 and musl are now supported and headless
  hosts load the addon unaffected.
- Removed the native-desktop-linux cargo feature, desktop_unsupported.rs,
  lazy desktop loader, second napi build, desktop packaging/CI steps, GUI
  build dependencies, and the now-unreferenced vendored libspa crate;
  reverted setup-system-deps to main.
- Preserved the desktop input hardening semantics on the unified backend:
  XTest layouts reject negative origins and coordinates beyond 0..=32767,
  batch coordinates stay bound to the frame last returned to JS with
  intermediate screenshots deferred, coordinate input requires a
  previously returned frame, and failed chord releases still release
  every held key.
- Enforced a 60s worker-side execute deadline (DESKTOP_DEADLINE_EXCEEDED):
  no input is emitted after expiry and wait-heavy batches are rejected
  upfront.
- Added int32 fail-closed validation for coordinates, drag points, and
  scroll deltas at the JS ingress and gateway schema.
- Exposed computer to models without native OpenAI computer-use support as
  a regular function tool with a typed GA action schema across OpenAI,
  Azure, and Codex Responses providers, including named forced choice.
- Added the /computer slash command (on/off/status/toggle) for
  session-only enablement via runtime tool registration in SessionTools.
- Updated docs, changelogs, and contract tests accordingly.
2026-07-24 01:40:05 +00:00
usr-bin-roygbiv 4fe03e25cb fix(coding-agent): align computer session ownership 2026-07-24 01:40:05 +00:00
usr-bin-roygbiv b9504f65e7 feat: add native Codex computer use 2026-07-24 01:40:04 +00:00
can1357 fc3e9970c7 style: organized imports in session modules after fallback merge 2026-07-24 02:26:26 +02:00
can1357 366bd6203e Merge PR #6392: feat(coding-agent): add usage-aware model fallback (@eggpeat) 2026-07-24 02:25:35 +02:00
can1357 77669aed54 Merge PR #6395: feat: configure xdev prompt docs (@joeshull) 2026-07-24 02:25:35 +02:00
can1357 2e3fbbbd2a Merge PR #6432: fix(session): clear session-scoped tool state (@roboomp) 2026-07-24 02:24:15 +02:00
can1357 e2a986c6b6 Merge PR #6429: fix(session): preserve compaction data for rewinds (@roboomp) 2026-07-24 02:24:05 +02:00
can1357 9c0ad16b8a Merge PR #6431: fix(agent): commit plan-reference flag on delivery, not construction (@roboomp) 2026-07-24 02:24:05 +02:00
Brent 8a9630c031 fix(coding-agent): reselect fallback account by health 2026-07-24 02:23:51 +02:00
Brent 93af91b7f5 fix(coding-agent): preserve fallback CI contracts 2026-07-24 02:23:51 +02:00
Brent 0bfb0bd1e3 feat(coding-agent): add usage-aware model fallback 2026-07-24 02:23:51 +02:00
Joe Shull f4641c165e feat: allowlist xdev prompt docs 2026-07-24 02:23:22 +02:00
can1357 9687818228 fix(session): cleared branch-scoped tool state
Applied the session-scoped tool reset after /branch and /btw create their
branched logical sessions, closing the same stale-state leak as /new,
handoff, and cross-session switches.

Added a branch transition to the staged-preview regression matrix.
2026-07-24 02:23:15 +02:00
roboomp 55d18e89a5 fix(session): cleared handoff-scoped tool state
Applied the session-scoped tool reset after handoff creates its replacement session.

Added regression coverage for stale staged preview directives across handoff.

Fixes #4093
2026-07-24 02:23:15 +02:00
roboomp e6cdfd6187 fix(session): cleared session-scoped tool state
Cleared queued tool-choice directives and ACP always decisions after successful logical session transitions.

Added new-session and cross-session regression coverage for staged resolves and both ACP always decisions.

Fixes #4093
2026-07-24 02:23:15 +02:00
can1357 9a2639e507 refactor(session): converted PERMISSION_OPTIONS_BY_ID from object to Map
- Changed lookup from bracket notation to Map.get() to safely fail closed on unknown permission IDs.
2026-07-24 01:42:25 +02:00
can1357 f5a4c5fe2a fix(coding-agent): exported advisor stats types and update move command test
- Export specific advisor stats types instead of re-exporting all session advisors.
- Update move command tests to mock session-level move actions.
2026-07-24 01:37:41 +02:00
can1357 7eeaba0471 refactor(coding-agent/session): restructured monolithic agent session
- Extracted internal handlers and logic from AgentSession into dedicated runner, guard, and coordinator modules.
- Created standalone modules for bash execution, evaluation runners, IRC bridging, and prewalk coordination.
- Established dedicated session components for tracking stats, todos, streams, and retry fallback chains.
- Preserved existing session behavior while significantly reducing monolithic class size and complexity.
2026-07-24 01:24:44 +02:00
can1357 46d2b7d864 Merge PR #6439: fix(compaction): stop feeding reasoning back to Claude summarizer (@roboomp) 2026-07-23 23:05:47 +02:00
can1357 8cab2b7cd5 fix(session): run prompts issued while disposing instead of dropping them
- The memory-backend transition await added in PR #6428 guarded with #isDisposed, which beginDispose() sets immediately; prompts issued in the disposing window were silently dropped instead of running their final turn and settling via the dispose abort.
- Guard now only drops the prompt when disposal began during the transition await.
2026-07-23 22:42:34 +02:00
roboomp 5a70eda7d7 fix(compaction): stop feeding reasoning back to Claude summarizer
Both compaction serializers reproduced prior assistant reasoning as text
bound for a Claude target, tripping Anthropic's reasoning_extraction
refusal and wedging Fable 5 sessions:

- context-full: serializeConversation rendered thinking verbatim inside
  <thinking> tags via the anthropic dialect renderer. Now drops thinking
  blocks when the summary target dialect is anthropic; other dialects
  (e.g. Harmony) keep native reasoning.
- snapcompact: emitted ¶think sections baked into replayed archive
  frames. Added an includeThinking serialize option (default true) and
  wired the agent session to disable it for Anthropic-dialect models.

Fixes #6093
2026-07-23 20:38:27 +00:00
can1357 83e0e4cdac Merge PR #6435: fix(session): resume resolved tool stalls (@roboomp) 2026-07-23 22:38:05 +02:00
roboomp 055a0ce0af fix(session): resumed resolved tool stalls
- Preserved stalled assistant turns when every emitted tool call had a result, including synthetic unexecuted results.

- Kept unresolved and non-stall tool errors replay-safe and covered terminal error agent_end delivery.

Fixes #6414
2026-07-23 20:18:03 +00:00
can1357 29c2bd2595 Merge PR #6415: fix(compaction): judge remote-preserve reuse against the active model (@roboomp)
# Conflicts:
#	packages/coding-agent/src/session/agent-session.ts
2026-07-23 22:16:11 +02:00
can1357 72ff07ff84 Merge PR #6428: fix(memory): synchronize live backend lifecycle (@roboomp) 2026-07-23 22:15:25 +02:00
can1357 a6072d0013 Merge PR #6427: fix(session): validate blob refs before path join (@roboomp) 2026-07-23 22:15:22 +02:00
roboomp 111de5ab71 fix(agent): commit plan-reference flag on delivery, not construction
#buildPlanReferenceMessage set #planReferenceSent = true while building the
message, before it was handed to agent.prompt. Any pre-send setup bail (the
four #promptGeneration generation-bail returns) or throw (@-mention reads,
before_agent_start hooks) between build and delivery left the flag true with
nothing delivered, and the #promptWithMessage finally never cleared it — so the
retry short-circuited at `if (this.#planReferenceSent) return null` and the
approved plan was silently dropped for the rest of the session.

Move the flag commit to the delivery hand-off point in #promptWithMessage: set
it only when a plan-reference message was built AND we are about to call
#promptAgentWithIdleRetry. Every bail/throw now leaves the flag clear so the
next prompt re-injects the plan. The compaction-success resets (issue #1246)
still clear it for re-injection on the next turn.

Fixes #4094
2026-07-23 19:54:52 +00:00
roboomp cb63ebd9f5 fix(session): preserved compaction data for rewinds
Kept superseded summaries and preserveData durable while deriving forward transcript elision from the active compaction.

Added branch and rewind coverage for snapcompact archives and OpenAI remote replacement history.

Fixes #4090
2026-07-23 19:53:05 +00:00
roboomp 5a1f227a6b fix(memory): synchronized live backend lifecycle
- Serialized backend transitions across runtime state, tools, and prompts.
- Rehydrated Mnemopi listeners after clear and enqueue maintenance.
- Made memory.backend the sole post-migration local runtime gate.

Fixes #5638
2026-07-23 19:52:09 +00:00
roboomp 5f47afba16 fix(session): validate blob refs before path join
parseBlobRef sliced the blob:sha256: suffix and returned it unvalidated;
get/getSync then fed it into path.join(this.dir, hash), so a crafted ref
like blob:sha256:../../../etc/passwd escaped the blob directory and read
arbitrary files into resolved image history (base64, raw UTF-8, and the ACP
sync path).

Reject any suffix that is not a canonical 64-char lowercase hex hash in
parseBlobRef, the single choke point for every resolution entry point. Reuse
the shared BLOB_HASH_RE in gc-cli instead of its duplicate HASH_RE.

Fixes #4088
2026-07-23 19:51:53 +00:00
roboomp 34fef55d25 fix(session): serialize ArtifactManager first-use init
#ensureDir checked #initialized then set it across an await
#scanExistingIds() gap, so two concurrent first-use save/allocatePath
callers both re-seeded #nextId=maxId+1 and allocateId() handed both the
same id — silently overwriting the first artifact (same toolType) or
making artifact:// resolution ambiguous (different toolTypes).

Memoize the initial scan as a single in-flight #initPromise so all
concurrent callers share one initialization and receive distinct ids.

Fixes #4091
2026-07-23 19:46:30 +00:00
roboomp 116b8f4597 fix(compaction): judged remote-preserve reuse against the active model
After an OpenAI remote compaction, prepareCompaction decided whether to
keep the provider-native replay boundary or re-expand its originals by
asking whether *any* compaction candidate (every role model plus the
largest-context available model) shared the payload's provider. In a
multi-role setup where a role such as modelRoles.smol stays on OpenAI,
the check passed forever, so a session switched to a non-OpenAI active
model kept a placeholder-only summary and never recovered the compacted
span for the rest of the session.

Judge reusability against the active model — the one that assembles the
request context every turn — instead of the candidate set. When the
active model cannot replay the payload, re-expand the originals into a
portable local summary, matching the self-healing already present for
single-provider migrations.

Fixes #6343
2026-07-23 19:12:50 +00:00
can1357 da1056226e Merge PR #5464 port: persist vibe sessions across restarts (@roboomp) 2026-07-23 18:07:22 +02:00
can1357 5d66eb7f2a Merge PR #5464: fix(coding-agent): persist vibe sessions across restarts (@roboomp) 2026-07-23 18:06:11 +02:00
can1357 2ffb67e3c7 fix: reconciled merged tests and dead code with current main structure
- warp completion test updated to event-taking notification signature
- hindsight test config gained required timeout fields
- dropped orphaned parseBillingConfig and advisor secret-collection dupes
- deduped fixture key; formatter pass on merged files
2026-07-23 18:02:31 +02:00
pr-eval 424458e99d chore(secrets): dropped drive-by changes unrelated to secret placeholders
Reverted branch-side edits to spawn-policy prompts/tests, settings tab
groups, mermaid cache typing, prewalk todo gating, and packages/ai test
churn back to merge-base content; trimmed their changelog entries. These
repaired stale CI against an older main and are stale or conflicting
against current main.
2026-07-23 17:56:29 +02:00
can1357 c0c1622012 Merge PR #4636: feat(secrets): add friendly names to secret placeholders (@Mathews-Tom)
# Conflicts:
#	packages/ai/test/pi-native-client.test.ts
#	packages/coding-agent/src/advisor/runtime.ts
#	packages/coding-agent/src/prompts/tools/eval.md
2026-07-23 17:56:24 +02:00
can1357 4af619433b fix(coding-agent): counted queued-but-uninjected async-result follow-ups as pending async work
A completed delivery hands off from the AsyncJobManager to the session's
yield queue before the follow-up is injected (idle flush runs on a delayed
post-prompt task; mid-turn entries wait for the next step boundary). In
that window hasPendingAsyncWork() read false from manager state alone, so
a terminal yield observed there terminated the run and silently dropped
the delivered result - the stale-success class the quiescence barrier
exists to prevent. The wake predicate now also counts queued async-result
entries on the yield queue; added a session-level contract test that
pinned the window (failed before, passes after).
2026-07-23 17:52:52 +02:00
can1357 c522eceff2 Merge PR #6119: feat: lift subagent async/auto-background limits via owner-routed delivery and quiescence (@korri123)
# Conflicts:
#	packages/coding-agent/src/task/executor.ts
2026-07-23 17:52:52 +02:00
can1357 dee5fa63be fix(coding-agent): pointed retry backstops at renamed persistence helper 2026-07-23 17:50:15 +02:00