`CreateElicitationRequest` is a discriminated union — even after
narrowing on `mode === "form"`, both `ElicitationRequestScope` (no
`sessionId`) and `ElicitationSessionScope` (with `sessionId`)
remain in the union. The new live-getter regression test was reading
`calls[N]!.sessionId` directly, which CI tsgo rejected with TS2339.
Per-element `if (!call || call.mode !== "form" || !("sessionId"
in call))` narrows to the session-scoped variant. Spelled three times
because loop-style narrows don't propagate to the assertions below.
Matches the discriminator pattern used in the older 'translates select'
test at line ~927.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
`biome check` enforces print-width on the two test-only call-sites that
`ast_edit` collapsed onto a single line during the sessionId-getter
rewrite. Auto-formatter wrap, no behavior change.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
`AgentSession.sessionId` is a getter that reads through to
`sessionManager.getSessionId()` and mutates when an extension command
calls `ctx.newSession` or `ctx.switchSession` (both exposed in the
same #configureExtensions block). Snapshotting the id once at factory
time routed later elicitations to the pre-switch id — diverging from
every other sessionUpdate call in this file, which already reads
record.session.sessionId live.
createAcpExtensionUiContext now takes `getSessionId: () => string` and
calls it per elicitation. Caller passes `() => record.session.sessionId`
so each select / confirm / input picks up the current id.
Also simplifies elicitFromAcpClient: `onAbort` and `finish` had
identical settlement bodies differing only by the resolve value, with a
hand-rolled `removeEventListener` symmetry comment to keep them in
sync. Collapsed to a single settle path — `onAbort = () =>
finish(undefined)` — so future changes to settlement apply to both
paths automatically. Doc-comment tightened to call out that late SDK
`accept` responses (not just rejections) after abort/timeout are also
dropped silently.
New regression test asserts that mutating the captured sessionId
between elicitations is reflected in the next request.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
OpenCode-Go and OpenCode-Zen handle reasoning content internally
and reject client-supplied reasoning_content in message history.
When retry fallback forwards conversation history to
opencode-go/kimi-k2.6, the compat layer was injecting synthetic
reasoning_content: '.' on assistant tool-call turns, causing
HTTP 400: 'Extra inputs are not permitted'.
Gate isKimiModel in requiresReasoningContentForToolCalls on
!isOpenCodeProvider so the injection path is skipped for
OpenCode providers while preserving existing behavior for
native Kimi API, DeepSeek, and OpenRouter.
Promotes the stub acpExtensionUiContext to a createAcpExtensionUiContext
factory invoked per session inside #configureExtensions. select / confirm
/ input each map to a single-property `value` schema and round-trip
through a shared elicitFromAcpClient helper that mirrors
RpcExtensionUIContext.#createDialogPromise:
- capability gating on clientCapabilities.elicitation.form
- runtime typeof narrowing on accept payloads (wrong-type / missing
key / no content all fall back to the stub return values)
- dialogOptions.signal: pre-aborted short-circuits before any SDK
call; mid-flight abort races the in-flight elicitation. Symmetric
removeEventListener on both onAbort and finish paths.
- dialogOptions.timeout: setTimeout(.unref()) settles the promise via
onTimeout + stub fallback. A throwing onTimeout is caught and
logged so the elicitation promise still settles.
- late SDK rejections after abort/timeout are dropped silently;
transport failures log via logger.warn with { sessionId, method,
error }.
Empty/whitespace-only placeholders on `input` and empty/whitespace-only
messages on `confirm` are treated as absent (trim-aware), matching the
behavior documented in the CHANGELOG bullet.
15 new tests cover request shape, decline/cancel, missing capability,
transport failure, pre-abort, mid-flight abort, wrong-typed accept,
missing `value` key, no content, timeout, whitespace placeholder,
empty-message join, and throwing onTimeout.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
- Updated the hashline mismatch error to describe anchor mismatches against the current file.
- Rewrote hashline tool instructions to clarify insert payload rules, anchor usage, and avoidance of fabricated hashes.
- Expanded stale-edit detection and tests to recognize the revised anchor-mismatch rejection wording.
- Added an internal accounting-state guard and used it to skip goal usage flushing when accounting was inactive.
- Updated goal abort handling to return early unless accounting or pause logic was required, then paused only a cloned active goal state before committing.
- Aligned related tests/types by tightening OpenAI helper typing and using Tool typings for the goal tool registry.
- Discouraged coreutils in favor of dedicated read/search/find/edit/write tools.
- Prohibited pipe truncation via head/tail since artifacts handle full output.
- Prohibited stderr redirection since stdout and stderr are already merged.
- Added an HTML comment state tracker to prompt formatting.
- Updated ASCII symbol replacement to skip substitutions inside `<!-- ... -->` comment blocks across lines.
- Added tests that preserved comment text while converting symbols outside comments.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
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.
- 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.
- 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.
- 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.
- 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.