Commit Graph
3993 Commits
Author SHA1 Message Date
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 6d00cc1f08 test(ai): added reasoning model helper for OpenAI response history tests
- Added getOpenAIReasoningModel to wrap the bundled gpt-5-mini model with a non-gpt-5 name in tests.
- Replaced all OpenAI responses test model constructions using gpt-5-mini with the new helper to bypass reasoning-model branching during payload assertions.
2026-05-14 06:23:55 +02:00
can1357 ad2e5c0578 refactor(coding-agent/exa): renamed tool detail field from response to raw
- Updated the Exa tool factory to emit details using a raw field rather than response.
- Updated the MCP wrapped Exa tool to emit details using a raw field rather than response.
2026-05-14 06:16:31 +02:00
can1357 71f3997afa fix(session): resolved session persistence flow to use sync write/read APIs
- Added sync truncation helpers to recursively prepare session entries and externalize image data.
- Reworked session persistence to use synchronous preparation plus `writeSync` with close-state checks.
- Added synchronous session-storage APIs and rerouted write paths to `writeLineSync`/`readTextSync`.
- Added `BlobStore.putSync`, migrated hashing to `Bun.SHA256`, and updated hash tests accordingly.
2026-05-14 06:12:41 +02:00
can1357 cf627d5577 docs(coding-agent/prompts): updated hashline prompt to clarify delta-only payloads
- Expanded the hashline tool rules to state that patch payloads should only contain newly added lines and must not duplicate existing content.
- Clarified that insertion and replacement operations affect only their specified targets, with adjacent lines remaining unchanged.
- Reinforced widening edits to self-contained syntactic units before selecting the smallest patch operation.
2026-05-14 05:58:25 +02:00
can1357 8fc5b78f30 feat(read): added comma-separated scatter gather line selector support
- Extended selector regex and parser to accept ranges like `:5-16,960-973`.
- Ranges are sorted and merged automatically before reading.
- Out-of-bounds ranges surface as inline notices instead of errors.
- Added `#readLocalFileMultiRange` and `#buildInMemoryMultiRangeResult` for file, archive, notebook, and internal URL targets.
2026-05-14 05:58:25 +02:00
can1357 cf4173a100 feat(exa): replaced raw JSON responses with human-readable formatting
- Added formatGenericResponse to handle objects, arrays, MCP content blocks, and primitives.
- Applied formatted output to MCPWrappedTool, createExaTool, and propose-changelog tool.
- Replaced raw response in details field with structured response object.
2026-05-14 05:58:25 +02:00
can1357 fe7b3d7005 refactor(coding-agent): removed intent property from WriteTool 2026-05-14 05:58:25 +02:00
can1357 3592865fe1 fix: plan mode types 2026-05-14 05:38:09 +02:00
can1357 786c25e6c7 fix(coding-agent): resolved coding-agent cli --help startup init cycle
- Fixed root `cli --help` startup by preventing the config/model-registry initialization cycle.
- Extracted config validation, migration, and loading logic from config.ts into config/config-file.ts.
- Added ConfigFile helpers for migration, validated JSON/JSONC/YAML loading, status caching, and reset.
- Added a regression test that runs `cli.ts --help` with temp HOME/XDG env paths and expects exit code 0.
2026-05-14 05:35:16 +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 0b62f2971b fix(ci): restore @napi-rs/cli dep and align tests with current types
The earlier exports/cleanup refactor removed @napi-rs/cli from
packages/natives devDeps, breaking every native job. It also left two
test files calling private symbols and a stale KeyId literal:

- packages/natives: re-add @napi-rs/cli (catalog) so node_modules/.bin/napi
  exists for build-native.ts.
- test/acp-agent.test.ts: import ACP_BOOTSTRAP_RACE_GUARD_MS from
  modes/acp/acp-agent (previously implicit via mass-export refactor).
- test/silent-abort-overlay-render.test.ts: lowercase 'Ctrl+S' -> 'ctrl+s'
  to match the KeyId union.
2026-05-14 05:12:07 +02:00
can1357 1fb59df0bb fix(edit): stripped all leading @ prefixes from hashline input headers
- Updated parseHashlineInputPreviewHeader to strip all leading "@" markers before resolving the preview path, matching existing parser behavior.
- Added a regression test in edit renderer tests confirming both canonical "@@" and longer "@" runs render as clean file paths without extra "@" characters in titles.
2026-05-14 05:06:00 +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 4de99a481b Merge pull request #1063 from chuaaron/fix/edit-format-reminder
fix(edit): add format reminder to hashline prompt
2026-05-14 05:02:52 +02:00
can1357 d62480dc65 fix(edit): slim format-reminder and use configured separator
- Drop duplicated op listing from the reminder; <ops> already defines
  the four shapes one block above.
- Replace hardcoded `~` with the {{hsep}} helper so the reminder
  tracks PI_HL_SEP / HL_EDIT_SEP overrides, matching the rest of
  hashline.md and addressing Codex review on #1063.
- Shrink the WRONG/RIGHT example (smaller anchor, no padding runs)
  since the reminder's only job is contrasting on-line vs next-line
  payload placement.
2026-05-14 05:01:55 +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 ed88f0f90d Merge branch 'main' into fix/context-window-fallback 2026-05-14 04:48:16 +02:00
Can BölükandGitHub 26931fe8ce Merge pull request #1055 from jiwangyihao/fix/browser-worker-startup-errors
fix(browser): surface tab worker startup errors
2026-05-14 04:47:31 +02:00
Can BölükandGitHub 3d2bbe5e8f Merge branch 'main' into fix/browser-stealth-target-setup 2026-05-14 04:46:30 +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 1ea87b26bc feat(coding-agent): added hidden skill flag for system prompt filtering
- Added optional `hide` metadata to skill capabilities so `SKILL.md` frontmatter intent is preserved when skills are loaded.
- Filtered system prompt skill rendering to exclude `hide: true` skills from the `<skills>` listing while keeping them loadable.
2026-05-14 04:38:14 +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
Aaron Z 58d7723c79 fix(coding-agent/edit): add format reminder to hashline prompt to prevent anchor+content on same line
Models frequently write '+ ANCHOR| CONTENT' instead of '+ ANCHOR'
followed by '~CONTENT' on the next line. Add a compact FORMAT block
between </ops> and <rules> with a WRONG/RIGHT example that directly
addresses this failure mode.
2026-05-14 10:03:33 +08:00
enieuwy fa1d83e527 Fix copy fallback for handoff context 2026-05-14 09:41:06 +08:00
can1357 6b6cc417f2 test(coding-agent/acp): bumped ACP stdout-hygiene timeout to 60s for slow CI runners 2026-05-14 03:26:25 +02: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
can1357 453071d34d fix(coding-agent): restored coordinate-mapping dimension note and made bash SGR test color-mode agnostic
- Restored formatDimensionNote bracket form '[Image: original WxH, displayed at WxH. Multiply coordinates by S to map to original image.]' that tests assert. The Bun 1.3.14 refactor regressed it to a less informative 'Image resized from …' line.
- Broadened bash-sixel-render multi-line styling assertion to accept both truecolor (38;2;) and 256-color (38;5;) SGR runs so CI runners with TERM=dumb don't fail. The contract being tested — every line carries its own SGR — is independent of color depth.
2026-05-13 20:43:03 +02:00
Miroslav Drbal 8c77d2b15a fix(coding-agent): copy cost into async task progress on completion
The async job completion path copied durationMs, tokens, and extractedToolData
from SingleResult back into the AgentProgress object, but missed cost.
Add progress.cost = singleResult?.usage?.cost.total ?? 0 to the same block.
2026-05-13 20:19:53 +02:00
Miroslav Drbal 5cc8095cd1 refactor(coding-agent): extract appendAgentStats helper in render.ts
Eliminates the three-way duplication of toolCount/tokens/cost stat
appending across renderAgentProgress (running), renderAgentProgress
(completed), and renderAgentResult.
2026-05-13 20:07:09 +02:00
Miroslav Drbal 08551b83a5 fix(coding-agent): show cost in final subagent result line
renderAgentResult (rendered after the task tool resolves) was missing the
cost display present in renderAgentProgress. Read cost directly from
result.usage?.cost.total which is already available on SingleResult.
2026-05-13 20:04:55 +02: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
can1357 c7d04f3a13 fix(coding-agent): constrained bash cwd auto-detect regex to single-line cd commands
- Updated BashTool's leading `cd` regex to stop matching newline characters so cwd extraction only applies to a single-line `cd ... &&` prefix.
- Added a regression test for multiline commands with a later-line `&&` to ensure each line of the script executes normally.
2026-05-13 19:19:50 +02:00
jiwangyihao 11a19eb8d4 fix(browser): bound stealth target setup during tab open
Keep the active page stealth setup synchronous, but make the broader CDP target UA override sweep selective and best-effort. Non-page or ephemeral Chrome targets can otherwise block worker initialization long enough for browser.open to hit the tool timeout before the tab worker sends ready.

Fixes #1053
2026-05-14 01:19:01 +08:00
cognitiveandGitHub e6cce9147c Merge branch 'main' into fix/skill-chip-and-silent-abort 2026-05-14 02:08:45 +09:00
jiwangyihao 8830b2e367 fix(browser): surface tab worker startup errors
Forward worker error and messageerror events while acquireTab waits for the initial ready/init-failed response. This prevents async worker module-load or early startup failures from being reported only as a generic tab worker init timeout.
2026-05-14 00:34:55 +08:00
can1357 7fd2a7b309 fix(coding-agent/tools): highlighted multi-line bash commands in result rendering
- Added a new formatBashCommandLines helper that syntax-highlighted each command line and applied the dim prefix only to the first line.
- Updated the shell renderer to emit command output as line-based entries instead of a single dimmed string.
- Extended the bash renderer test to verify multi-line commands keep ANSI styling on every rendered line.
2026-05-13 18:15:57 +02: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 6eda70aada refactor: replaced abortableSleep with scheduler.wait and fetchWithRetry
- Removed local `abortableSleep` in favour of Node's built-in `scheduler.wait` from `node:timers/promises`.
- Consolidated per-provider retry/fetch loops into a shared `fetchWithRetry` utility in `packages/utils`.
- Moved `extractHttpStatusFromError`, `isRetryableError`, and related helpers out of `packages/ai` into `packages/utils`.
- Deleted `extractRetryDelay` in favour of `extractRetryHint` with unified header and body parsing.
2026-05-13 16:40:58 +02:00
Burke T fcaafda0fa fix(coding-agent): preserve bundled contextWindow/maxTokens when discovery returns sentinel fallbacks
When cached or freshly-discovered provider models carry UNK_CONTEXT_WINDOW
(222222) / UNK_MAX_TOKENS (8888) sentinels, #mergeResolvedModels was
replacing the bundled model wholesale — wiping out the correct values.

Switch to a field-level merge that preserves the bundled model's
contextWindow and maxTokens when the replacement only has sentinel
fallbacks. Custom models (via #mergeCustomModels) already had this
protection via ?? fallback; provider discoveries didn't.

Fixes the TUI showing 222222/8888 instead of the real context/token
limits for discovered models.
2026-05-13 08:43:06 -03:00
can1357 7530114c01 refactor(coding-agent): simplify bun runtime guard
Replace bespoke semver parser, JSONL probe, and stringWidth errata check
with a single Bun.semver.order comparison against MIN_BUN_VERSION.
2026-05-13 13:36:46 +02: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