Commit Graph

754 Commits

Author SHA1 Message Date
can1357 3f304ee5a8 refactor(agent-core): isolated token counting into a new local tokenizer
- Extracted native token counting into a new localized `tokenizer.ts` wrapping `@oh-my-pi/pi-natives`.
- Introduced a lightning-fast byte-length estimation logic for token counting when accurate counting is disabled.
- Diverted token calculations to the faster estimator during test environments and when `PI_TOKENIZER_ACCURATE` is falsy.
- Updated agent base and coding-agent sessions to consume the new localized `countTokens` utility.
2026-06-18 01:57:23 +02:00
can1357 17ce678468 fix(coding-agent): handled provider error finish reasons and preserve subprocess failure codes
- Added detection for provider error finish reasons occurring before tool calls to identify fatal messages.
- Prevented subprocess tool execution finalization from resetting a non-zero exit code when yield items exist.
- Ensured a default error message is set in stderr when a subprocess fails after yielding a result.
2026-06-18 01:11:10 +02:00
can1357 a050474af7 feat: migrated validation schemas and tool definitions from Zod to ArkType
- Migrated all wire protocol, schema definitions, and tools validation from Zod to ArkType across multiple packages.
- Updated extension runtimes, custom tools loader, and TypeBox compatibility shim to expose and use ArkType instances.
- Added a comprehensive ArkType migration guide, validation parity tests, and helper utilities.
- Removed redundant PDF asset routing and parsing implementations from the read tool.
2026-06-18 00:59:53 +02:00
can1357 d4317d3d20 feat(ai): consolidated OpenAI-family streaming and add OpenRouter API support
This change introduces a new `openrouter` API type and extensively refactors OpenAI-family streaming providers, centralizing shared logic and improving robustness.

Key changes include:
- **Unified OpenAI-family Logic:** Consolidated core utilities, compat resolution, request shaping, and stream processing into `openai-shared.ts`, reducing duplication across `openai-completions`, `openai-responses`, and `openai-codex-responses`.
- **OpenRouter API Type:** Introduced a dedicated `openrouter` API type with dual-surface compatibility, allowing it to dispatch requests as either OpenAI Chat Completions or Responses.
- **Enhanced Provider Integration:**
    - Improved Perplexity search to leverage shared OpenAI streaming transports, including API-key fallback to OpenRouter and support for Perplexity's Responses API.
    - Integrated xAI-specific logic directly into the shared `stream.ts` dispatch, removing the dedicated `xai-responses` provider.
    - Refined credential parsing for Google Gemini CLI and handling of Azure deployment names.
- **Robustness & Consistency:** Improved error handling for Codex, standardized output token parameter resolution, and ensured consistent application of reasoning suppression across all Chat Completions dialects.
- **New Documentation:** Added `provider-endpoint-constraints.md` to detail endpoint-specific behaviors and quirks for various providers.
- **Telemetry & Debugging:** Extended telemetry propagation to advisor calls and overflow compaction tasks. Improved debugging for Codex WebSocket failures and stream error messages.
- **Tooling & Security:** Updated browser stealth scripts to prevent detection and added a new `ts-no-inline-cast-access` TTSR rule.
2026-06-17 21:36:48 +02:00
can1357 eb67863e75 feat(coding-agent/tools): secured browser stealth scripts against detection
- Bound native Reflect methods to local variables in the browser launch script to prevent detection.
- Updated stealth injection scripts to use the bound Reflect methods instead of global Reflect calls.
- Fixed a type assertion issue in the AgentSession tool proxy.
2026-06-17 20:59:20 +02:00
can1357 af6e83a651 fix(coding-agent): replaced JSON string equality checks with deep equality
- Changed provider delta input comparisons in `buildResponsesDeltaInput` to use `Bun.deepEquals` instead of stringified JSON checks.
- Updated session message diffing to return early on length changes and compare normalized entries with deep equality.
- Replaced JSON-string assertions in the issue-966 repro test with `Bun.deepEquals` for stable equality checks.
2026-06-17 13:45:11 +02:00
can1357 54d212ec33 feat(coding-agent): added advisor immune-turn window for concern/blocker interruptions
- Tracked completed primary turns in `AgentSession` and started an immune-turn window after each interrupting advisor steer.
- Routed follow-on `concern`/`blocker` notes to the aside channel while the immune window is active, while preserving prior auto-resume-suppressed handling.
- Added the `advisor.immuneTurns` setting and tests for immune-turn detection and delivery-channel decisions.
2026-06-17 13:21:47 +02:00
can1357 e4a87fa3ce feat(coding-agent): added matplotlib rendering and image persistence across session reload
- Added Matplotlib figure PNG rendering and display tracking in Python runner to emit PNG output immediately when figures are displayed via display(fig).
- Extended session persistence to externalize oversized image payloads in both content and details.images, enabling tool result images to survive session reload.
- Enhanced session loader to resolve image data payloads and blob references across content and details.images during session reconstruction.
- Added image cache invalidation in TUI image component when image protocol, cell dimensions, or Kitty Unicode placeholder mode changes.
- Added comprehensive test coverage for Matplotlib display, image persistence across reload, and TUI image rendering with protocol and dimension changes.
2026-06-17 13:19:28 +02:00
can1357 d0e896a0ee fix(coding-agent): clean rebased session stop state
- Removed obsolete context-usage provider fields left unused after rebasing the session stop branch.
- Sorted the rebased SDK import block so `bun check` stays clean.
2026-06-17 12:28:10 +02:00
can1357 6e918712fd fix(coding-agent): guard session stop continuations
- Guarded `session_stop` continuations against aborted or superseded hook results before queueing hidden follow-up turns.
- Reported compaction recovery continuations from `#checkCompaction` and skipped stop hooks while internal recovery owns the next turn.
- Let terminal empty-stop retry caps fall through to `session_stop` and added regression coverage for aborts, empty-stop caps, and promotion recovery.
2026-06-17 12:26:52 +02:00
ben c40bc8365e fix(coding-agent): honor session stop reason fallback 2026-06-17 12:26:52 +02:00
ben bd14fed678 fix(coding-agent): finalize session stop lifecycle 2026-06-17 12:26:52 +02:00
ben c93774f892 fix(coding-agent): implement session stop hook semantics 2026-06-17 12:26:52 +02:00
ben b73325b103 fix(coding-agent): emit session_stop after subagent completion 2026-06-17 12:26:01 +02:00
ben b7ac4b4c43 fix(coding-agent): use session stop extension event 2026-06-17 12:26:01 +02:00
ben 8e45ed9016 fix(coding-agent): add subagent stop extension event 2026-06-17 12:26:00 +02:00
can1357 a0cffe4814 feat: updated model-aware API-key resolution and antigravity endpoint failover
- Updated getApiKey signatures to accept a Model and return ApiKey or ApiKeyResolver.
- Updated stream key handling to resolve credentials per model and use seedApiKeyResolver for retries.
- Added antigravityEndpointMode setting with auto/production/sandbox endpoint selection.
- Added 429/5xx endpoint failover for Gemini stream, usage, search, and image calls.
2026-06-17 12:24:21 +02:00
can1357 409196bf2e fix(coding-agent/session): fixed context usage breakdown to prefer completed in-turn anchors
- Fixed context breakdown to anchor estimates on the latest completed assistant usage message after compaction.
- Adjusted pending-context usage selection to prefer an in-turn provider anchor when available at/after cutoff.
- Added a contextUsageRevision cache token so status-line context memo invalidates after snapshot clear.
2026-06-17 12:24:20 +02:00
can1357 48decd15d7 fix(coding-agent): fixed context usage tracking to keep status and selector totals in sync
- Added context snapshot metadata to AssistantMessage for prompt and non-message token history.
- Anchored context usage calculations on assistant snapshots and computed percent numerically.
- Updated status-line, /context, selector, and interactive mode flows to share session usage totals.
- Extended status-line cache fingerprinting and invalidation for assistant usage and prompt/tool/skill changes.
2026-06-17 12:24:20 +02:00
can1357 0b04fda921 fix(coding-agent): added vision fallback for text-only model image attachments
- Added `images.describeForTextModels` configuration defaulting to true for text models.
- Added `describeAttachedImagesForTextModel` to persist images and generate local:// descriptions.
- Added image-description notices to session flow with hidden typing and pre-user insertion.
- Added fallback behavior that returns notes when vision is unavailable or output is empty.
2026-06-17 12:24:18 +02:00
roboomp 75d8d97220 fix(session): persisted todo reminder injections
Recorded todo reminder developer messages in the session log so JSONL transcripts match model-visible context when reminders are enabled.\n\nFixes #2824
2026-06-17 03:49:55 +00:00
can1357 eaba315cbd security(coding-agent): sanitized artifact names and wrapped extension and MCP tools
- Sanitized artifact filenames by normalizing tool names before composing spill paths.
- Applied `wrapToolWithMetaNotice` to custom tool adapters and RPC-host tools in agent-session setup.
- Wrapped SDK-registered extension/custom tools with the same meta-notice adapter during session creation.
2026-06-17 01:53:24 +02:00
can1357 84f8d127dc Merge remote-tracking branch 'origin/farm/41a13455/skip-empty-sessions' 2026-06-17 00:22:34 +02:00
can1357 ef5e5fd27c fix(coding-agent): fixed parked subagent restoration from persisted sessions
- Fixed cold revival flow so parked subagents are restored from persisted sessions at startup.
- Fixed session-init persistence to include spawns and readSummarize fields for replay accuracy.
- Fixed latest-session lookup by adding peekSessionInit for lock-free persisted contract access.
- Added lifecycle and session tests for cold-revive success, decline, and retry paths.
2026-06-17 00:21:20 +02:00
can1357 d6e390c1ca fix(coding-agent): reclaimed stranded advisor cards when interrupted runs settle
- Queued advisor concern cards now get reclaimed as visible advice during settle when auto-resume suppression is active and the session is idle.
- Preserve logic was narrowed to keep advisor cards hidden only during abort teardown, allowing steers during resumed streaming turns.
- A regression test was added to verify stranded advisor steers are persisted as visible advice without triggering an advisor-only resume turn.
2026-06-16 23:14:54 +02:00
roboomp e3f48b44bd fix(cli): preserved explicit session rewrites
Kept shutdown flushes lazy while allowing explicit atomic rewrites to materialize pre-assistant session entries.

Added regression coverage for rewriteEntries before the first assistant message.

Fixes #2800
2026-06-16 21:00:25 +00:00
can1357 3459371724 fix(coding-agent/advisor): fixed advisor concern/blocker notes being stranded after interrupts
- Added resolveAdvisorDeliveryChannel in advisor tooling to map each note to aside, steer, or preserve using severity, auto-resume suppression, core-streaming, and abort state.
- Updated AgentSession advice enqueuing to route concern/blocker notes through that resolver, preserving them only when the interrupted turn is idle or tearing down and steering them during active resumed turns.
- Added regression tests for resolveAdvisorDeliveryChannel covering nit versus interrupting severities across streaming, aborting, and suppression combinations.
2026-06-16 22:53:39 +02:00
roboomp 54e79162b4 fix(cli): skipped empty session persistence
Prevented shutdown flushes from materializing sessions that never produced assistant output, and kept close from marking a non-existent session file current.

Added regression coverage for opening omp and exiting before any prompt or assistant turn reaches history.

Fixes #2800
2026-06-16 20:50:51 +00:00
can1357 0f013b455e feat: added LaTeX math rendering support for terminal and TUI outputs
- Added LaTeX math and Mermaid allowances in terminal and final-chat prompts.
- Added inline math tokenization in TUI for $, $$, \(\), and \[\].
- Added LaTeX-to-Unicode conversion helpers and exports for math rendering.
- Fixed inline math detection to skip escaped dollars and currency-like spans.
2026-06-16 21:45:10 +02:00
can1357 712e859022 feat(coding-agent): restored the verbose /dump and /advisor dump raw output
- Rewrote `formatSessionDumpText` in `session-dump-format.ts` to emit the pre-16.x full dump: system-prompt prelude, model/thinking config, tool inventory with parameters, and the transcript as markdown role headings (`## User`, `## Assistant`, `### Tool Call`/`### Tool Result`), reusing `renderDelimitedThinking` for `<thinking>` blocks.
- Dropped the compact default and the `[raw]` flag from `/dump`: removed the `isRaw` parameter from `handleDumpCommand` in `command-controller.ts`, `interactive-mode.ts`, and `types.ts`, and removed the `inlineHint: "[raw]"`/`compact` plumbing in `builtin-registry.ts`.
- Updated the `formatSessionAsText` doc comment in `agent-session.ts` to describe the verbose dump shape.
- Removed the obsolete `formatSessionDumpText raw thinking` suite from `advisor.test.ts` and refreshed `session-dump-format.test.ts` to assert the verbose dump output.
- Recorded the revert in the coding-agent changelog and trimmed `/dump` from the compact transcript tool-intent-prefix entry.
2026-06-16 20:53:05 +02:00
can1357 5bce7ed6df feat: added advisory transcript formatting and one-shot benchmark metrics
- Introduced advisory note output as `<advisory>` tags with optional severity and guidance.
- Updated session transcript formatting to `### Session update` and inline watched role labels.
- Added shared `escapeXmlText` utility and escaped XML-sensitive text in advisor outputs.
- Added one-shot success run token metrics and one-shot statistics reporting.
2026-06-16 18:34:50 +02:00
can1357 9cb0b4b643 fix(coding-agent): fixed session magic-keyword ordering and stranded queue handling issues
- Fixed magic-keyword notices to preserve ordering in agent-session processing.
- Fixed stranded queue behavior during queued steer/skill delivery in session logic.
- Updated agent-session and input-controller tests covering suppression, keywords, and queues.
- Updated unreleased changelog notes describing the magic-keyword and queue fixes.
2026-06-16 17:59:15 +02:00
can1357 1e3909a151 fix(coding-agent/session): split queued-message editor restore between dequeue and interrupt
- Generalized `isUserQueuedMessage` to a user-attribution predicate (`role === "user"` or custom `attribution === "user"` and not display-suppressed) so visible agent-authored steers (advisor cards, IRC/extension asides) and hidden goal/plan/budget steers are all excluded from editor restore, not just advisor cards.
- Gave `AgentSession.clearQueue` a `{ forInterrupt }` option: plain Alt+Up dequeue restores user messages and preserves every other queued message for the continuing stream, while Esc+abort keeps only advisor cards (for `abort()`'s `#extractQueuedAdvisorCards` preservation) and drops other internal steers so the post-abort `#drainStrandedQueuedMessages` can't auto-resume the interrupted run.
- Threaded `forInterrupt: options?.abort` from `InputController.restoreQueuedMessagesToEditor` and kept `queuedMessageCount` on actual displayable-queue semantics so `hasPendingMessages()`/RPC and the empty-submit abort gate stay accurate.
- Updated skill-queue tests to cover both policies (hidden and visible agent-authored steers preserved on dequeue, dropped on interrupt) and refreshed the changelog entry.
2026-06-16 16:27:53 +02:00
can1357 6bbc573c6f fix(coding-agent/session): suppressed subagent breadcrumbs so --continue resumes the parent session
- Added a `suppressBreadcrumb` option to `SessionManager.open()` so headless opens skip writing the per-TTY `--continue` breadcrumb, and passed it from the subagent opens in `task/executor.ts` and the HTML export open in `export/html/index.ts`, which run in the parent's terminal and were clobbering the breadcrumb with their own artifact-dir session file.
- Added `resolveBreadcrumbToInteractiveRoot()` and applied it in `continueRecent()` so already-poisoned breadcrumbs pointing inside a parent's artifacts dir (`<parent>/<agentId>.jsonl`) resolve back up to the top-level interactive session.
- Added `subagent-breadcrumb.test.ts` covering both that a subagent open keeps `--continue` on the parent and that a stale subagent-pointing breadcrumb is recovered.
2026-06-16 16:05:50 +02:00
can1357 623e9d3710 fix(coding-agent/session): restricted queued-message editor restore to user-authored messages
- Added `isUserQueuedMessage()` to `agent-session.ts`, treating only plain user turns and visible `attribution: "user"` custom messages (e.g. `/skill`) as restorable, so advisor concern/blocker notes, hidden goal/plan/budget steers, and IRC/extension asides no longer leak into the editor on Esc/Alt+Up.
- Reworked `clearQueue()` to return only user-authored messages while re-queuing advisor cards via `replaceQueues()` (so the user-interrupt abort path still re-records them as advice) and dropping other agent-authored steers to prevent a silent auto-resume on leftover internal context.
- Filtered `getQueuedMessages()` chips and rewrote `popLastQueuedMessage()` to skip agent-authored cards and pull the last user-authored entry, while `queuedMessageCount` still counts all displayable queued work.
- Extended `input-controller-skill-queue.test.ts` with a `queueAdvisorSteer` helper and cases asserting advisor/IRC cards count as pending work but stay out of chips, restore, and `popLastQueuedMessage`, and survive `clearQueue()`.
2026-06-16 16:05:36 +02:00
can1357 97a8c2186b fix(coding-agent/session): excluded streaming-edit guard aborts from reasonless retry
- Updated #isRetryableReasonlessAbort to reject reasonless aborts when the streaming-edit guard flag is set.
- This prevented routing those aborts through retry logic and avoided prompt hangs or unintended guard bypasses during edit-stream recovery.
2026-06-16 15:32:59 +02:00
can1357 5d875e9574 Merge PR #2753: fix(agent): retry subagent model fallback chains
Install a subagent's ordered model candidates as child-session retry fallback chains so a retryable provider failure advances to the next candidate instead of killing the worker (issue #2750).
2026-06-16 15:22:16 +02:00
can1357 13bcefd414 Merge PR #2689: fix(session): retry empty reasonless aborts
Auto-retry empty/reasonless provider aborts without model fallback (issue #2685). Includes review fix b7a3d01439: skip the retry while the session is disposing to avoid a shutdown hang.
2026-06-16 14:52:42 +02:00
can1357 b7a3d01439 fix(session): skip reasonless-abort retry while disposing
A dispose-driven bare abort() yields the same empty/reason-less aborted turn as a transient provider abort, but with #isDisposed set and #abortInProgress unset. #isRetryableReasonlessAbort matched it and routed it through #handleRetryableError, which created #retryPromise and scheduled a continuation the disposed guard then skipped without resolving the promise — hanging the in-flight prompt() in #waitForPostPromptRecovery during shutdown.

Guard the predicate on !#isDisposed so lifecycle aborts settle the turn, and add a regression test. Addresses review feedback on #2689.
2026-06-16 14:37:02 +02:00
roboomp eca8d120dd fix(session): retried reasonless empty aborts
Empty provider-side aborted turns now enter the existing auto-retry path without switching retry model fallback, while aborted turns with partial content still settle normally.\n\nFixes #2685
2026-06-16 14:31:15 +02:00
metaphorics c0ceef7af2 feat(coding-agent): re-inject eager task/todo nudges after compaction
The first-message eager-task / eager-todo preludes are the oldest messages in a
session, so auto-compaction summarizes them away and the agent silently loses the
delegate-via-tasks / phased-todo guidance mid-work. Re-assert those reminders on
the auto-continuation turn that follows a compaction.

- Widen #createEagerTaskPrelude / #createEagerTodoPrelude to accept
  `string | undefined`; `undefined` (post-compaction) skips only the
  first-message and prompt-suffix gates, keeping the mode / agent-kind /
  plan-mode / surviving-todo / active-tool gates intact.
- Reminder-only post-compaction: the todo nudge never attaches a forced `todo`
  tool_choice on the resumed turn (forcing a tool after a mid-turn compaction
  would override the agent's in-flight action).
- Add #buildPostCompactionEagerNudges() and prepend its output on the single
  #scheduleAutoContinuePrompt continuation hook. All three call sites are
  willRetry-safe, so overflow/incomplete retry recoveries never carry the nudge.

Op: extend
2026-06-16 14:22:51 +02:00
roboomp 7b62bffb34 fix(agent): matched routed retry primaries
Matched retry fallback roles against the plain model selector as well as the routed in-flight selector, preserving configured chains for compat-routed OpenRouter and Vercel models.

Added regression coverage for a compat-routed OpenRouter primary using a plain role selector.
2026-06-16 09:01:58 +00:00
roboomp 3d3cdb42d4 fix(agent): kept at-suffixed fallback ids
Stopped retry fallback selector parsing from treating every @ suffix as upstream routing, preserving exact model ids like google-vertex Claude @default variants.

Resolved fallback candidates from raw selectors during preflight so routed selectors still work without corrupting exact at-suffixed ids.
2026-06-16 08:37:49 +00:00
roboomp ad58175946 fix(agent): restored routed retry primaries
Resolved retry fallback primaries from the raw selector during cooldown restore so OpenRouter and Vercel upstream pins survive fallback recovery.

Added regression coverage for routed OpenRouter primaries reverting after cooldown expiry.
2026-06-16 08:16:49 +00:00
roboomp 3cdb867d28 fix(agent): preserved routed subagent fallbacks
Kept OpenRouter and Vercel upstream routing suffixes in subagent retry fallback selectors so same-base routed candidates stay distinct.

Resolved retry fallback candidates from the raw selector before model switching so routed fallback models keep their requested upstream route.
2026-06-16 07:47:48 +00:00
can1357 3c5e32f21b fix(coding-agent): made advisor toggle session-local and refreshed the status line
- SetAdvisorEnabled now used settings.override for advisor.enabled when enabling or disabling, keeping advisor toggles session-local.
- /advisor on|off handlers now called refreshStatusLine after each toggle, and the status line updates immediately in the UI.
- A regression test was added to assert setAdvisorEnabled invokes override with both values and does not call set.
2026-06-15 21:20:07 +02:00
can1357 b1c0243bab fix(coding-agent): fixed advisor auto-resume suppression for user interruptions
- Passed USER_INTERRUPT_LABEL through abort paths in collab, ACP, RPC, runtime, and SDK flows.
- Added userInitiated to synthetic continue inputs and session prompt calls.
- Suppressed advisor auto-resume during user aborts and preserved queued concerns.
- Cleared suppression on user prompts and reclaimed parked advisor cards on abort settle.
2026-06-15 20:51:56 +02:00
can1357 336f1a8b16 Merge PR #2626: fix(coding-agent): open isolated subagent sessions in worktree cwd 2026-06-15 19:46:14 +02:00
can1357 af99ba4406 Merge PR #2687: fix(agent): stop retrying interrupted tool streams 2026-06-15 19:46:11 +02:00
roboomp 55000301be fix(agent): preserved classifier refusal fallback
Checked structured classifier refusals before the interrupted-output retry guard so provider refusals with explanatory content still use the configured fallback path.

Fixes #2683
2026-06-15 15:48:06 +00:00