Commit Graph
958 Commits
Author SHA1 Message Date
can1357 bddf9989b5 feat: added host-uri frame and rpc bridge for read/write/cancel routing
- Added `set_host_uri_schemes` and host-uri frame/type definitions; documented read/write/cancel behavior.
- Added `RpcHostUriBridge` in rpc mode to register schemes, dispatch read/write/cancel ops, and clear pending requests.
- Added internal URL write support with lowercased scheme matching, handler routing, and hashline-prefixed success output.
- Added Python host-uri APIs/exports, cancellable client request handling, and host-uri read/write test coverage.
2026-05-15 00:54:09 +02:00
can1357 ba2928da6b feat(coding-agent): added scratch-directory handling to status-line path segment
- Updated the status-line path segment to detect project directories under OS scratch roots and strip the scratch root when rendering.
- Switched scratch-root paths to use the new icon.scratchFolder glyph and registered that symbol across theme variants.
- Added tests covering scratch-root trimming, nested scratch subpaths, and non-scratch fallback icon behavior.
2026-05-15 00:47:05 +02:00
can1357 933058a241 feat(goals): added per-session goal mode with token budget tracking
- Added GoalRuntime with wall-clock and token accounting, budget steering, and lifecycle operations (create, pause, resume, drop, complete).
- Exposed goal tool as a hidden agent tool, activated only when goal mode is enabled.
- Integrated goal continuation loop in InteractiveMode with auto-submit between turns.
- Added status line segment and theme icons for goal mode state.
2026-05-14 06:40:41 +02:00
can1357 88e486be29 fix(coding-agent/modes): hardened context breakdown against absent session fields
- Hardened context usage accounting to tolerate missing session fields by defaulting skills and tools to empty arrays.
- Guarded message and system-prompt token counting with presence checks to avoid access errors on partial session objects.
2026-05-14 06:37:25 +02:00
can1357 3592865fe1 fix: plan mode types 2026-05-14 05:38:09 +02:00
can1357 ef5cbef51f feat(coding-agent): added resolve-based plan approval flow in coding-agent
- Removed ExitPlanModeTool and deleted exit-plan-mode docs/tests, dropping the old approval contract outputs.
- Replaced plan-mode approval flow from exit_plan_mode to resolve across session, SDK, controllers, and discovery.
- Added standing resolve handler accessors and updated resolve routing for queued or standing approval handlers.
- Added PlanApprovalDetails and enforced normalized, validated approval titles with readable plan-file requirements.
- Extended resolve schema and invocation signatures with optional extra metadata and reason trimming behavior updates.
- Updated plan and resolve prompts and changelog guidance to require resolve action, reason, and extra.title for apply/discard.
2026-05-14 05:33:30 +02:00
can1357 ba47b0e32f fix(tools): recovered malformed conflict:// paths during write conflict resolution
- Updated conflict URI parsing to accept `path:conflict://N` and record the removed prefix in `recoveredPrefix`.
- Updated write conflict handling to resolve single or wildcard IDs through shared helpers and append a recovery note when a malformed prefix was stripped.
- Added regression tests for recovered prefixes and end-to-end write-path recovery and documented the change in the changelog.
2026-05-14 05:03:04 +02:00
Can BölükandGitHub 8f1d98fa38 Merge branch 'main' into fix/skill-chip-and-silent-abort 2026-05-14 04:51:41 +02:00
Can BölükandGitHub 57ce77fa79 Merge pull request #1042 from tsagi2045/fix/status-line-context-pct
fix(coding-agent): align status-line context% with /context command output
2026-05-14 04:49:11 +02:00
Can BölükandGitHub 7a50b9ed58 Merge branch 'main' into fix/token-display-exclude-cache-read 2026-05-14 04:45:05 +02:00
Can BölükandGitHub 3ad9255b18 Merge branch 'main' into dmarsh/acp-thinking-level-push 2026-05-14 04:43:55 +02:00
Can BölükandGitHub 9530f94a36 Merge pull request #1061 from ldx/fix/mcp-oauth-persist-dynamic-client
fix(coding-agent): persist dynamically registered MCP OAuth client_id
2026-05-14 04:43:08 +02:00
Can BölükandGitHub 38255a4e6e Merge pull request #1062 from enieuwy/fix/copy-handoff-context
Fix /copy fallback for handoff context
2026-05-14 04:42:53 +02:00
can1357 f1f6516056 refactor: reorganized exports and removed obsolete helper branches
- Removed export leakage by demoting many helper and const symbols to module-local scope.
- Renamed underscore-prefixed internals and cache fields, then updated related references and `satisfies never` checks.
- Deleted obsolete logic branches and helpers, including harmony-stream interruption flow and unused benchmark runtime helpers.
- Updated Biome config and manifests by broadening lint coverage and removing an unused `@napi-rs/cli` dev dependency.
- Adjusted tests and utilities to use renamed test helpers and remove redundant private test-only helpers/locals.
2026-05-14 04:36:19 +02:00
enieuwy fa1d83e527 Fix copy fallback for handoff context 2026-05-14 09:41:06 +08:00
cognitive c118eacdaa fix: gate SILENT_ABORT_MARKER at three unguarded render sites
Codex review flagged that the silent-abort sentinel
("__omp.silent_abort__") persists into AssistantMessage.errorMessage
but three downstream consumers render errorMessage verbatim:

- session-observer-overlay.ts: renders "✗ Error: __omp.silent_abort__"
  when content is empty (confirmed user-visible today)
- print-mode.ts: writes marker to stderr and exits non-zero (latent;
  plan-mode→compact not reachable from print mode today, but unguarded)
- acp-agent.ts: emits marker as agent_message_chunk text to ACP
  clients when message has no other notifications (latent)

Add isSilentAbort() guard at each site. Extend the SILENT_ABORT_MARKER
consumer list in messages.ts doc comment to include all six consumers.
Add regression tests: overlay (2 tests), print-mode (2 tests), ACP
replay (1 test).

Op: correct
Restores: spec:silent-abort-marker-never-surfaces
2026-05-13 23:58:13 +00:00
Vilmos Nebehaj a7f73ee645 fix(coding-agent): persist dynamically registered MCP OAuth client_id
When an MCP server uses OAuth Dynamic Client Registration (RFC 7591) and
no client_id is pre-configured, MCPOAuthFlow registers a fresh public
PKCE client on each authorize, captures the issued client_id into a
private field, then discards it once the flow object goes out of scope.
At refresh time, MCPManager#resolveAuthConfig calls refreshMCPOAuthToken
with auth.clientId from mcp.json — which is empty for these servers —
so providers that require client_id on the refresh grant (e.g. Linear at
mcp.linear.app/token) reject with HTTP 401 invalid_client. The user is
forced to /mcp reauth manually every time the access token expires.

This change threads the resolved/registered client credentials back out
of the OAuth flow and persists them into mcp.json so refresh has what
it needs indefinitely:

- MCPOAuthFlow exposes resolvedClientId / registeredClientSecret getters.
- MCPCommandController#handleOAuthFlow returns OAuthFlowResult with
  credentialId + clientId + clientSecret, populated from the flow's
  post-login state.
- The initial-connect non-wizard path and /mcp reauth path persist the
  returned client credentials into both auth.{clientId,clientSecret}
  (used at refresh) and oauth.{clientId,clientSecret} (used by future
  /mcp reauth to skip re-registration).
- The wizard's onOAuth callback signature now returns the same shape;
  #launchOAuthFlow folds the registered credentials into wizard state so
  the final mcp.json entry built by #buildServerConfigWithAuth includes
  them under auth.{clientId,clientSecret}.

Servers that configure a static oauth.clientId in mcp.json (Notion,
Slack, Datadog) are unaffected: #tryRegisterClient short-circuits, the
returned clientId equals the configured one, and the write-back is a
no-op.

Adds two MCPOAuthFlow unit tests covering both paths.
2026-05-13 15:39:04 -07:00
David Marshallandomp b626609314 refactor(coding-agent/acp): extracted ACP_BOOTSTRAP_RACE_GUARD_MS and consolidated race notes
/simplify pass on 4882d1e38. Three small cleanups, no behavior change.

* Extracted the inline 50ms bootstrap-race guard into an exported
  ACP_BOOTSTRAP_RACE_GUARD_MS constant at the top of acp-agent.ts.
  Source uses it in the #scheduleBootstrapUpdates setTimeout. Tests import
  it and call a new waitForBootstrapGuard() helper (constant + 30ms slack
  for setTimeout drift) instead of three hardcoded Bun.sleep(80) sites —
  tests now bind to the source-of-truth instead of dueling magic numbers.
* Consolidated four block comments that all narrated the same race story
  into one canonical explanation at the install site (#scheduleBootstrapUpdates).
  Field declaration, #registerPreparedSession, and the setSessionConfigOption
  handler keep brief one/two-line pointers. Net change is roughly 30 lines
  of comments removed without losing the diagnosis.
* Trimmed the handler-site thinkingHandledBySubscription comment from six
  lines to three; the local-variable name carries the intent.

Verified:
* bun test test/acp-agent.test.ts: 11/11 pass
* biome check on touched files: clean
* No behavior change (no test had to be updated)

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-13 16:43:45 -05:00
David Marshallandomp 4882d1e386 fix(coding-agent/acp): deferred thinking-level lifetime subscription until after bootstrap-guard
Addresses codex review on #1060: an extension session_start handler that
calls setThinkingLevel via the exposed extension action (line 1541) would
have run BEFORE #registerPreparedSession set the record into #sessions and
BEFORE the session/new response was delivered to the client, causing
config_option_update to be pushed for a session id the client did not yet
know about. This is the exact race that #scheduleBootstrapUpdates already
documents and guards for available_commands_update / session_info_update
(Zed's 'Received session notification for unknown session' drop).

Moved the session.subscribe(...) installation out of #registerPreparedSession
and into #scheduleBootstrapUpdates's 50ms timer callback so the lifetime
subscription shares the same response-delivery guard as the existing
bootstrap notifications. The pre-bootstrap thinking level is still
communicated to the client through the response payload's configOptions
(newSession / loadSession / resumeSession / unstable_forkSession all return
it), so no state is lost; it is only the notification that is deferred.

For client-driven setSessionConfigOption({thinking}) the handler now only
skips its own push when the lifetime subscription is already installed.
Pre-bootstrap the handler keeps pushing (the client knows the session id
because they passed it in), post-bootstrap the subscription pushes
exactly once. No double-push, no missing pre-bootstrap notification.

Tests:
- updated existing pushes-config-option-update test to await past the 50ms
  bootstrap timer before driving the internal setThinkingLevel
- updated the single-config_option_update-per-setSessionConfigOption test
  the same way
- added 'suppresses lifetime config_option_update during the bootstrap
  window' regression that drives setThinkingLevel synchronously after
  newSession and asserts zero notifications, then asserts notifications
  resume after the bootstrap timer fires
- bun test test/acp-agent.test.ts: 11/11 pass

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-13 16:34:54 -05:00
David Marshallandomp c7722838b7 fix(coding-agent/acp): pushed config_option_update on every thinking-level change
ACP clients (Zed, etc.) only received `config_option_update` notifications
when they themselves drove the change via `session/set_session_config_option`.
Internal thinking-level updates (slash commands, automatic model-driven
adjustments, extension UI) bypassed the notification path, so client config
panels went stale until the next user-initiated change.

AgentSession now emits a `thinking_level_changed` event from
`setThinkingLevel`, and AcpAgent installs a session-lifetime subscription on
each managed session that pushes a fresh `config_option_update` whenever the
event fires — independent of prompt-turn lifecycle. The
`session/set_session_config_option` handler no longer pushes its own
notification for the `thinking` config (lifetime subscription covers it);
the response still returns fresh `configOptions` so callers see the new
state synchronously. Subscriptions are released in `#disposeSessionRecord`.

Also consolidated four duplicate `config_option_update` send sites into a
new `#pushConfigOptionUpdate(record)` helper.

Tests: added two cases to `test/acp-agent.test.ts` — one verifying internal
`setThinkingLevel` calls produce a `config_option_update` and a no-op
re-set produces none, and one verifying client-driven
`setSessionConfigOption(thinking, …)` produces exactly one notification.

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-13 16:14:18 -05:00
Miroslav Drbal 084488b680 fix(coding-agent): exclude cacheRead from token display, add per-subagent cost
Token counter (token_total status-line segment, subagent progress tree,
session-observer stats line) previously included cacheRead in its cumulative
sum. With Anthropic prompt caching, cacheRead per turn equals the full cached
context, so summing across N turns gives N*context_size -- a session with a 1M
context and 5 turns showed ~5M tokens despite no compaction occurring.

Fix: display shows input + output + cacheWrite per turn. cacheWrite is kept
because each byte is written once; cacheRead re-reads the same context every
turn. Dedicated cache_read/cache_write status-line segments still show cache
activity; billing cost is unaffected.

Also adds per-subagent cost display (dollar amount, statusLineCost color)
accumulated incrementally from message_end events. Hidden when cost is zero
(subscription/OAuth providers). Brings token and cost display in line with
what Claude Code shows per-agent.
2026-05-13 19:26:38 +02:00
cognitiveandGitHub e6cce9147c Merge branch 'main' into fix/skill-chip-and-silent-abort 2026-05-14 02:08:45 +09:00
cognitiveandchatgpt-codex-connector[bot] (P2 review on PR #1043) f02ab20acb fix(coding-agent/tui): refreshed pending bar on tagged-custom dequeue
Op: correct
Restores: ref:44e5e0bb8 — queued /skill: chip lifecycle parity with plain-text steer

EventController.#handleMessageStart now mirrors the user-role refresh in
the custom branch, gated on readPendingDisplayTag(details). Without this,
AgentSession's tag-keyed dequeue mutated #steeringMessages /
#followUpMessages correctly but pendingMessagesContainer kept painting
the stale chip until an unrelated trigger (next user submit, dequeue key,
compaction flush) fired a refresh.

Non-queued custom variants (ttsr-injection, irc:*, async-result,
hookMessage) skip the refresh — they never registered a pending chip, so
rebuilding pendingMessagesContainer for them would be pure waste.

Pairs with the existing E4 (array splice) regression — the new E10 covers
the UI-refresh side of the same dequeue event with both positive and
negative gate assertions.

Co-Authored-By: chatgpt-codex-connector[bot] (P2 review on PR #1043)
2026-05-13 15:28:31 +00:00
can1357 af07faec11 feat: Bun 1.3.14
- Raised the Bun minimum version to >=1.3.14 across package metadata, install scripts, and changelog notes.
- Removed the Photon native image pipeline and added SIXEL-based `sixel` support in pi-natives.
- Migrated coding-agent image handling and resizing to `Bun.Image`, including updated tests and a JPEG quality bump to 80.
- Added HTTP/2 fetch bootstrap with HTTPS-only fallback and updated Bun build flags for autoload suppression/`--keep-names`.
2026-05-13 13:21:59 +02:00
cognitive 8aba137941 fix(coding-agent/tui): silenced spurious "Operation aborted" on plan-mode compaction approval 2026-05-13 08:18:07 +00:00
cognitive 44e5e0bb80 fix(coding-agent/tui): rendered queued /skill: as compact pending chip 2026-05-13 08:17:15 +00:00
Leo Kim e7738832c2 fix(coding-agent): align status-line context% with /context command output
Status-line's context_pct segment was computing tokens via
calculatePromptTokens(lastAssistantMessage.usage), which sums input +
cacheRead + cacheWrite from the Anthropic API usage object. The /context
slash command is computed by computeContextBreakdown, an offline estimate
over the live session state (systemPrompt + tools + skills + messages).

Both numbers are correct under their own definition, but they can
diverge by 2x+ on the same session when a turn rotates cache tiers
(e.g. 5m → 1h ephemeral re-cache) and cache_creation_input_tokens spikes.
Users read the two surfaces as one consistent dashboard and treat the
mismatch as a bug.

Repro: same session at the same moment reports 212K (21.2%) in /context
and 44.2%/1M in the status line — ~230K gap driven by per-turn
cache_creation on a system-prompt boundary.

This change makes status-line use the same computeContextBreakdown
source as /context so both surfaces stay consistent. The breakdown
result is cached with a 2s TTL inside the component so the per-frame
status-line render does not re-walk every message via
estimateMessagesTokens on long sessions. The Anthropic API per-turn
prompt size remains observable via existing token_in / cache_read /
cache_write / token_total segments.
2026-05-13 16:58:59 +09:00
can1357 edd08864c6 fix(coding-agent/slash-commands): fixed slash command shutdown handler return contract
- Updated the TUI shutdown slash command handler to return a `SlashCommandResult` instead of `void`.
- Returned `commandConsumed()` after clearing the editor and invoking runtime shutdown.
- Imported `SkillPromptDetails` as a type in the input controller message imports.
2026-05-13 06:20:07 +02:00
can1357 3a76cc4b3d chore: reformat 2026-05-13 06:17:18 +02:00
can1357 7286e63ec5 fix(coding-agent/acp): delayed bootstrap notifications by 50ms to avoid race
- Zed dispatches RPC responses and notifications on separate async tasks, so `setTimeout(0)` lost the race against the session registration handler.
- Dropped `available_commands_update` left the slash-command palette empty (#1015; zed-industries/zed#55965).
2026-05-13 06:15:28 +02:00
Ogrodevandcan1357 4e4e74be49 fix(coding-agent/acp): tighten ACP conformance per review feedback
Addresses the codex review comments on #1015 plus a sweep of adjacent
ACP conformance gaps surfaced while wiring them up.

Tool call + diff metadata
- acp-event-mapper: thread session cwd through and resolve every
  `ToolCallLocation` (initial args, in-flight updates, result details)
  to absolute paths against it; ACP requires absolute paths for
  client-side file mapping.
- edit/modes/patch: emit the destination path for moves in the diff
  result so post-edit "open file" actions land on the new file.

Permissions
- agent-session: pass cwd into `extractPermissionLocations` and resolve
  raw `path`/`file`/etc. fields against it before sending
  `session/request_permission`.
- agent-session: gate the permission wrapper on
  `bridge.capabilities.requestPermission && bridge.requestPermission`,
  matching the read/write/bash capability+method pattern.

acp-agent
- `authenticate`: validate `methodId` against the methods advertised by
  `initialize` and reject anything else, so malformed clients fail fast.
- `setSessionConfigOption(MODE_CONFIG_ID)`: also emit
  `current_mode_update` so clients tracking `modes.currentModeId` see
  the same transition `session/set_mode` would produce.
- Pass `runtime.notifyConfigChanged` to builtins; emit
  `available_commands_update` from a shared `reloadPlugins` helper
  reused by `/reload-plugins`, `/marketplace`, and `/plugins`.
- prompt resource handling: route `resource` content with `image/*`
  MIME into the `images` array instead of dropping it as an opaque
  blob; non-image blobs still fall back to the URI placeholder.
- pass session cwd to the event mapper.

Builtins
- model: call `runtime.notifyConfigChanged()` after a successful
  `setModel` so the ACP config selector reflects the new model
  immediately.
- mcp: redact query strings and userinfo from MCP server URLs before
  emitting them in `/mcp list` (prevents leaking `?exaApiKey=…` style
  secrets); wire `manager.setAuthStorage(...)` before `prepareConfig`
  in `/mcp test|resources|prompts` so OAuth servers can refresh tokens.
- ssh: reject non-integer `--port` values via a `^\d+$` guard instead
  of silently coercing through `Number.parseInt`; list project hosts
  first and dedupe user-scope duplicates to match capability-loader
  precedence.
- export: reject clipboard aliases (`--copy`, `clipboard`, `copy`)
  before passing them to `exportToHtml` as a filename.
- compact / force / move / browser: surface underlying failures via
  `usage(errorMessage(...))` instead of letting them crash the command.
- session save|delete: route through the active SessionManager so the
  persist writer is consulted and stale storage references are removed.
- marketplace / plugins / reload-plugins: call `runtime.reloadPlugins()`
  on install/uninstall/upgrade and enable/disable so slash command
  registries and command lists refresh consistently.
- shared.usage: make async and `await runtime.output(...)` so
  `sessionUpdate` text is never dropped or reordered.
- types: document the new `reloadPlugins` and `notifyConfigChanged`
  runtime hooks.

bash tool
- Use a shared `fireKill()` from the abort listener so `session/cancel`
  terminates the remote command immediately instead of waiting for the
  next `currentOutput()` round trip.
- Race `currentOutput()` against the abort signal so a stuck
  `terminal/output` RPC cannot delay cancellation.
- Kill the terminal before reading final output on timeout so a slow
  output read cannot let a timed-out command keep running past the
  enforced timeout.

Tests
- acp-agent.test: extend the existing config-option assertions to
  verify both `model` and `thinking_level` changes emit
  `config_option_update` notifications scoped to the right session.
- acp-builtins.test: cover `/model` emitting both
  `notifyTitleChanged` and `notifyConfigChanged`; lock in the parsed
  `mcp add` / `ssh add` call shapes so future arg-parser regressions
  fail the test instead of silently writing different configs; add a
  `reloadPlugins` stub plus a typed `notifyConfigChanged` slot to the
  shared test runtime factory.
- acp-stdout-hygiene.test: drain stderr in parallel and assert no
  JSON-RPC frame leaks onto it; terminate the spawned process so the
  stderr pump resolves deterministically.

CHANGELOG: itemize the above under `[Unreleased] > Fixed`.

CI
- bun run check: clean (TS + Rust)
- bun run test: 4128 pass / 689 skip / 0 fail (TS); 252 pass / 0 fail
  (Rust nextest)
- bun run ci:test:smoke: --version / --help / `stats --help` all OK
2026-05-13 06:00:45 +02:00
Ogrodevandcan1357 275108974a feat(acp): add acp CLI subcommand and wire terminal-auth into launch
- Adds omp acp subcommand that launches the agent as an ACP stdio server
- Registers the subcommand in the CLI dispatcher
- Threads terminal-auth args and ACP flags through the launch and main orchestrators
- Exports AgentSession on the public SDK surface
- Updates skills loader to support skill→slash-command conversion and prompt injection
- Updates input-controller to dispatch ACP built-in slash commands
2026-05-13 06:00:44 +02:00
Ogrodevandcan1357 f81d9b7fef feat(acp): extend AcpAgent with session management and model negotiation
- Adds create/resume/list/page session lifecycle handling to AcpAgent
- Implements mode switching (default vs. plan), MCP server configuration, and model/thinking config negotiation with the connected client
- Routes incoming ACP connections to AgentSession via the new ClientBridge
2026-05-13 06:00:44 +02:00
Ogrodevandcan1357 b707cdaa08 feat(acp): implement ACP protocol adapters and terminal-auth support
- Adds AcpClientBridge, adapting an ACP AgentSideConnection to the internal ClientBridge interface
- Adds ACP event mapper translating AgentSessionEvents to ACP SessionUpdate/SessionNotification wire payloads (tool-kind classification, content truncation, text normalization)
- Adds terminal-auth flag constant and prepareAcpTerminalAuthArgs helper for authenticated terminal handles
2026-05-13 06:00:44 +02:00
can1357 fc1ff60294 fix(packages/coding-agent): corrected interactive submit shutdown handling in coding-agent
- Updated submitInteractiveInput to await checkShutdownRequested after submission, avoiding premature teardown (#1020).
- Mapped extension UI shutdown hook to set ctx.shutdownRequested for deferred teardown handling (#1020).
- Added regression coverage for interactive shutdown propagation and issue #1020 teardown behavior.
2026-05-13 05:24:33 +02:00
can1357 a14a2c402c fix(packages/coding-agent): resolved compaction queue plan ordering
- Pinned final plan path before handleCompactCommand so queued messages use approved plan, not draft.
- Added regression coverage for setPlanReferencePath timing before compaction queue flush.
2026-05-13 05:24:33 +02:00
can1357 e7b4b4c20d fix(coding-agent): fixed read tool streaming routing and result expansion behavior
- Updated event-controller read-tool streaming handling to wait for a parseable target before routing tool calls, avoiding early component binding for unresolved arguments.
- Allowed internal-URL read calls to bypass the regular read grouping path and fall through to direct tool execution.
- Adjusted read tool rendering to honor the computed `expanded` flag for completed output instead of forcing expanded output.
2026-05-13 04:42:43 +02:00
can1357 e1589bb137 fix(coding-agent/modes): parsed selection from path before language detection
- Updated read entry syntax highlighting to derive language from a path split from selection suffixes.
2026-05-13 04:34:08 +02:00
can1357 64b4aa1ae0 feat(coding-agent): implemented PR diff URL parsing for pr://<N>/diff
- Replaced `op: pr_diff` with `pr://<N>/diff` URL variants and routed PR diffs through URL parsing.
- Added `readArgsHaveTarget` checks to gate read-call tracking on `path`/`file_path` targets.
- Added auth-key-aware GitHub caching with scoped rows, default auth resolution, and hard-TTL invalidation.
- Added markdown output rendering for read with markdown-cell layout, ANSI-aware truncation, and expand-width cache reuse.
- Updated PR diff and cache tests, replacing deprecated `pr_diff` cases with `/diff` and auth/TLL coverage.
2026-05-13 04:32:16 +02:00
can1357 d483531b6b fix(coding-agent): decoupled internal URL read calls from read tool grouping
- Added readArgsTargetInternalUrl in the read tool group component to detect targets handled by InternalUrlRouter from path or file_path arguments.
- Updated event-controller and UI helper read rendering paths to skip grouping read tool calls when those arguments target internal URLs.
- Passed session cwd and settings into internal URL resolution in read.ts and added tests for internal versus non-internal target detection.
2026-05-13 04:05:23 +02:00
can1357 2654859712 fix(coding-agent): wire ctx.shutdown() to InteractiveMode.shutdownRequested
The extension shutdown context action installed by
ExtensionUiController.initializeHookRunner was an empty stub, so
ctx.shutdown() in interactive mode silently did nothing while extensions
fell back to process.exit(0), bypassing session flush and terminal
restore. Flip InteractiveModeContext.shutdownRequested so the main
loop's existing checkShutdownRequested() drives the graceful path.

Fixes #1020.
2026-05-13 02:58:02 +02:00
Can BölükandGitHub f72e7ddbea Merge branch 'main' into feat/plan-mode-approve-compact-context 2026-05-13 02:46:59 +02:00
can1357 efad62e808 Merge PR #1033: feat(skill-command): route /skill:* through the submission keybinding
Slash skill invocations bypassed the Enter / Ctrl+Enter contract that
every other slash command honors. Now Enter steers, Ctrl+Enter queues
a follow-up, sharing one #invokeSkillCommand helper between the editor
submit handler and handleFollowUp. Compaction short-circuit ordering
preserved.

Closes #1033
2026-05-13 02:32:52 +02:00
Miroslav Drbalandcan1357 68627b0857 feat(coding-agent): add rpc-ui mode with tool UI context over RPC protocol
Adds a new `rpc-ui` mode that extends the existing headless RPC mode with
interactive tool support (ask tool, extension UI dialogs, etc.).

In plain `rpc` mode the session has `hasUI=false` and no UI context is
wired, so interactive tools are disabled. `rpc-ui` mode sets `hasUI=true`
and wires a single shared `RpcExtensionUIContext` instance into both the
tool context store and the extension runner. Both consumers share the same
`pendingExtensionRequests` map and output closure, so `extension_ui_response`
messages received on stdin are routed to the correct waiting promise
regardless of which code path (tool or extension) created the request.

Changes:
- `args.ts`: add `rpc-ui` to the `Mode` union and the parse guard
- `launch.ts`: expose `rpc-ui` in the OCLIF flag definition and help text
- `main.ts`: propagate `rpc-ui` through all RPC-mode guard conditions and
  pass `setToolUIContext` to `runRpcMode` when the mode is `rpc-ui`
- `rpc-mode.ts`: accept optional `setToolUIContext` callback; create one
  shared `RpcExtensionUIContext` instance and pass it to both the tool
  context store and the extension runner
2026-05-13 02:18:57 +02:00
metaphoricsandcan1357 a4258cfc2c feat(skill-command): route /skill:* through the submission keybinding
Makes `/skill:<name> [args]` work identically under both submission
keybindings, mirroring how free text is already routed during streaming:

- `/skill:foo` + Enter, streaming     -> steer queue (interrupt)
- `/skill:foo` + Ctrl+Enter, streaming -> followUp queue
- `/skill:foo` + Enter, idle           -> idle prompt
- `/skill:foo` + Ctrl+Enter, idle      -> idle prompt (was: literal text)

A single private helper `#invokeSkillCommand(text, streamingBehavior)`
on `InputController` handles the dispatch; the Enter submit handler
calls it with "steer", and `handleFollowUp` calls it with "followUp"
after the compaction short-circuit so a skill typed during compaction
rides the same `queueCompactionMessage` queue as free text.

Behavior deltas vs upstream/main:
- Enter on `/skill:foo` during streaming now steers (was: queued as
  followUp). Users who relied on the followUp default can press
  Ctrl+Enter -- the same key they already use for free-text follow-ups.
- Ctrl+Enter on `/skill:foo` is new capability; previously the
  literal string `/skill:foo ...` was sent as plain followUp text and
  the skill was never invoked.

Op: extend
2026-05-13 02:18:55 +02:00
cognitive 0eb8d0fdcd feat(coding-agent/plan-mode): add "Approve and compact context" approval choice
A fifth ExitPlanMode approval choice — sits between the existing
"Approve and execute" (purge session) and "Approve and keep context"
(full transcript). Runs `handleCompactCommand` against the plan-mode
transcript with a planning-specific custom instruction rendered from
`plan-mode-compact-instructions.md`, then dispatches the plan-approved
synthetic prompt so it lands as the first entry in the freshly-
summarized transcript — giving execution a fresh cache anchor with
the rationale carried over.

Cancel/fail contract:
- ok       → bookkeeping runs, plan-approved synthetic prompt dispatched.
- cancelled → bookkeeping runs (tools restored, plan reference path
              recorded), warning surfaced, dispatch skipped.
              `markPlanReferenceSent` is intentionally deferred past
              the cancel guard so `AgentSession.#buildPlanReferenceMessage`
              re-injects the plan on the operator's next prompt() call.
              If we marked it sent on cancel, the executor's first turn
              would have no plan context.
- failed   → bookkeeping runs, error already surfaced by executeCompaction,
             dispatch proceeds best-effort. Approval intent stands.

Cancel vs. fail is discriminated via `instanceof CompactionCancelledError`
at the session/compaction error boundary (introduced in the previous
commit), so any abort source — operator Esc, extension hook, programmatic
abort — classifies uniformly without input-modality or message-string
coupling.

Op: extend
2026-05-12 23:01:06 +00:00
cognitive bad4c133e7 feat(coding-agent/session): typed CompactionCancelledError sentinel and CompactionOutcome
Introduce `CompactionCancelledError` and `CompactionOutcome` ("ok" |
"cancelled" | "failed") so callers can discriminate user-driven aborts
from generic failures via `instanceof`, instead of inspecting error
messages or `AbortError`-name strings.

`AgentSession.compact()`'s two abort-rejection sites now throw the
typed sentinel; the model-call wrapper normalizes AbortError-shaped
rejections to the sentinel only when the compaction's abort signal
is actually set, preserving every other exception unchanged so real
compaction bugs are not silently relabeled as cancellations.

`CommandController.executeCompaction` and `handleCompactCommand`
return `Promise<CompactionOutcome>`; the catch classifies via
`instanceof CompactionCancelledError`. Existing callers (`/compact`,
loop runner, auto-compact) ignore the return value — non-breaking.

Op: extend
2026-05-12 22:58:27 +00:00
can1357 478db5183a feat(tools): added strict conflict parsing for read/write tools
- Added conflictCount metadata and warning badge output to read results for files with unresolved conflicts.
- Added conflict detection parsing with strict marker matching and session-scoped conflict IDs.
- Added write-path conflict resolution for `conflict://N` using token expansion and marker validation before splicing.
- Added unit and integration tests for conflict scanning, history lifecycle, URI validation, and workflows.
2026-05-12 10:55:09 +02:00
can1357 8d144e17ec feat(coding-agent/eval): added local python-runner subprocess execution
- Replaced Python execution with a local `python -u runner.py` subprocess and NDJSON stdin/stdout framing.
- Removed shared-gateway architecture, including coordinator lifecycle APIs, `useSharedGateway` wiring, and `jupyter` CLI/actions.
- Simplified setup checks to a plain Python 3 availability probe and removed automatic dependency-install fallbacks.
- Updated kernel cancellation and display processing to use status frames, SIGINT/SIGTERM escalation, and normalized output coercion.
- Added `python-runner` integration and display tests while deleting legacy websocket and kernel lifecycle test suites.
2026-05-12 09:09:24 +02:00
Can BölükandGitHub 7f94047453 Merge branch 'main' into fix/export-and-tree-support-developer-messages 2026-05-12 06:21:20 +02:00