Commit Graph

12983 Commits

Author SHA1 Message Date
can1357 12238f55ca feat: implemented native ctok tokenization engine with model scopes
- Implemented the `ctok` Rust native tokenization engine with offline support for Claude V3, V47, V5, and V5Sonnet families.
- Replaced global token estimation with model-scoped `Tokenizer` instances and provider-anchored transcript accounting across packages.
- Added vocabulary generation scripts, test fixtures, and comprehensive unit tests for tokenizer routing and matching modes.
2026-08-19 23:27:29 +02:00
can1357 c39004063e feat(coding-agent): formatted multiline descriptions and tasks in subagent HUD
- Replace newline characters with visual indicators in subagent HUD descriptions and task previews.
- Add unit tests verifying multiline description and task rendering.
2026-08-19 22:58:25 +02:00
can1357 74bc1f442e feat(ai): implemented fallback handling and option for qwen reasoning effort
- Added `qwenTemplateReasoningEffort` model compatibility option to disable Qwen chat template kwargs for strict local servers.
- Implemented fallback handling to strip rejected `chat_template_kwargs.reasoning_effort` and hoist values to top-level fields.
- Added comprehensive test coverage for Qwen reasoning effort fallback and keyword rejections.
2026-08-19 17:40:39 +02:00
can1357 416b30a8d5 feat(tui): supported risk notes with warning glyphs in settings lists
- Add support for risk notes and warning markers on setting items in the TUI settings list component.
- Update the external thinking setting schema and help command to include a warning about provider abuse enforcement.
2026-08-19 16:26:57 +02:00
can1357 858f7dd91f test(export): re-pinned html template bytes for regenerated tool-views
The ask-card note renderer (#8786) grew tool-views.generated.js by 126 bytes; CI regenerates the asset so the byte-pinned template contract (bytes/chars/sha256) moved. Values verified identical between CI and a fresh local gen:tool-views.
2026-08-19 12:48:11 +02:00
can1357 22b40b47e1 chore: bump version to 17.3.8 2026-08-19 12:35:37 +02:00
can1357 5fb8d1f8bf Merge PR #8995: fix(cli): strip launch-global flags before non-launch subcommands (@roboomp) 2026-08-19 12:21:02 +02:00
can1357 0001e389bb Merge PR #8993: fix(commit): preserve binary patch terminators in split-commit round-trip (@roboomp) 2026-08-19 12:21:02 +02:00
roboomp ec56f8d4cf fix(cli): strip launch-global flags before non-launch subcommands
`resolveCliArgv` hoisted a subcommand hidden behind leading global launch
flags to the front and forwarded those flags to the subcommand's own
parser (#2970). Launch-shaped commands (`launch`/`acp`) share the launch
flag surface, but strict-parsing subcommands like `update` declare only
their own flags, so a leading `--cwd` reached `node:util.parseArgs` and
threw `Unknown option '--cwd'`. This bit users whose shell alias/wrapper
runs `omp --cwd <dir> update`.

Leading launch-global flags are now stripped when the hoisted subcommand
is not launch-shaped, and still forwarded for `launch`/`acp`. Shared the
launch-command set with the profile bootstrap to keep one source of truth.

Fixes #8891
2026-08-19 10:10:16 +00:00
roboomp 985e4ad515 fix(commit): preserve binary patch terminators in split-commit round-trip
parseFileDiffs split the captured `git diff --cached --binary` on
"
diff --git ", consuming the newline that terminates each file block, and
patch.join ended with `.replace(/\n+$/, "")`. Both dropped the blank line
that terminates a `GIT binary patch` block, so rebuilding a split-commit
patch produced a corrupt binary patch rejected by `git apply --binary`.

Split on a line-start lookahead so blocks keep their terminators verbatim,
and concatenate join parts without stripping trailing newlines. Both
trailing and mid-diff binary blocks now round-trip byte-exact.

Fixes #8899
2026-08-19 10:08:40 +00:00
can1357 5d18fd814d chore(changelog): normalized entries and added /mcp reauth OAuth discovery note
Covers merged PR #8989, whose branch omitted a CHANGELOG entry (issue #8922).
2026-08-19 12:00:15 +02:00
can1357 a349650bac Merge PR #8990: fix(tui): scroll the /model Roles view so clipped rows stay reachable (@roboomp) 2026-08-19 11:59:55 +02:00
can1357 f2e11a3d72 Merge PR #8989: fix(mcp): run oauth discovery on reauth when handshake needs no auth (@roboomp) 2026-08-19 11:59:55 +02:00
roboomp 8ea64a6a8d fix(mcp): run oauth discovery on reauth when handshake needs no auth
`/mcp reauth <name>` probed the server with `{ oauth: false }` and treated a
successful unauthenticated `initialize` as proof that OAuth was unnecessary,
hard-erroring with "Server connection succeeded without OAuth; reauthorization
is not required." Per the MCP spec a server may allow unauthenticated
`initialize` while requiring a bearer token for `tools/call`, so this left no
way to acquire a credential for such servers.

When the handshake succeeds without an in-band tool challenge, fall back to
`discoverOAuthEndpoints(config.url)` and proceed with the flow if the server
advertises OAuth metadata; only refuse when no OAuth endpoint is discoverable.

Fixes #8922
2026-08-19 09:53:26 +00:00
can1357 a720b8d6ac fix(coding-agent): bound TinyFish locale regex to whole subtags
Unanchored regex mapped BCP-47 script subtags to bogus regions
(lang:zh-hans -> location=HA) and prefix-matched 3+ letter codes
(lang:eng -> language=en). Require a subtag boundary, matching the
Perplexity provider's parsing.
2026-08-19 11:52:55 +02:00
can1357 d61c33349a Merge branch farm/5a737841/tinyfish-honor-lang-directive: fix(coding-agent): honor lang: directive in TinyFish search (@roboomp) 2026-08-19 11:52:55 +02:00
can1357 0253c85026 Merge PR #8985: fix(sdk): thread response model into after_provider_response context (@roboomp) 2026-08-19 11:52:55 +02:00
can1357 e966b4aa4d Merge PR #8983: fix(mcp): refresh broker-backed MCP OAuth credentials (@roboomp) 2026-08-19 11:52:54 +02:00
can1357 8557366401 Merge PR #8979: fix(coding-agent): paint optimistic row for idle /skill submits (@roboomp) 2026-08-19 11:52:54 +02:00
can1357 9ffc0b2a17 Merge PR #8978: fix(compaction): reject stale pre-compaction anchor in context breakdown (@roboomp) 2026-08-19 11:52:53 +02:00
can1357 b4c04ef0b7 Merge PR #8976: fix(commit): fail loudly when staged binary truncates split-commit diff (@roboomp) 2026-08-19 11:52:53 +02:00
can1357 0b20c251eb Merge PR #8970: fix(tui): pin anchored regions under an unpinned streaming seam (@roboomp) 2026-08-19 11:52:52 +02:00
can1357 9a8b0ef80a Merge PR #8967: docs: clarify bash.patterns gates the bash tool only, not eval (@roboomp) 2026-08-19 11:52:52 +02:00
roboomp aed63e7bd5 fix(tui): scroll the /model Roles view so clipped rows stay reachable
The Roles panel renderer looped from the first row with a hard height cap and no scroll offset, so roles and model-keyed fallback chains past the visible height were never drawn and unreachable by keyboard, with no truncation indicator. Unlike the sibling provider list (model-browser windows via #windowStart/#ensureSelectedVisible), the Roles panel had no equivalent.

Window #renderRolesView around #roleIndex via #ensureRoleVisible, offset mouse hit-testing by the scroll start bounded to the visible count, and draw an up/down '+N more' hint when the list is clipped.

Fixes #8817
2026-08-19 09:52:41 +00:00
roboomp 78ef6805f3 fix(sdk): thread response model into after_provider_response context
ExtensionRunner.emitAfterProviderResponse accepted the response model but
discarded it, calling createContext() with no model. Response-scoped hooks
therefore saw the primary session model in ctx.model and ctx.models.current()
even when the response came from a cross-provider side request, so an extension
that revokes a credential on an HTTP 402 could target the wrong provider.

Call createContext(model) to match emitBeforeProviderRequest, plus a regression
test asserting both fields expose the response model.

Fixes #8955
2026-08-19 09:44:22 +00:00
roboomp 7150f122f5 fix(coding-agent): honor lang: directive in TinyFish search
The shared query pipeline parses a lang:/language: directive into StructuredQuery.lang, which sibling providers (DuckDuckGo, Perplexity, SearXNG) map onto their native locale params. The TinyFish provider dropped parsed.lang entirely, so every request fell back to the API's US/English default and non-US locales were silently lost.

Map parsed.lang onto TinyFish location (ISO 3166-1 alpha-2) and language (ISO 639-1): lang:it-it yields location=IT&language=it, lang:it yields language=it only. Behaviour is unchanged when no locale directive is present.

Fixes #8913
2026-08-19 09:43:54 +00:00
roboomp 9cc881ce5b fix(mcp): refresh broker-backed MCP OAuth credentials
Remote OAuth MCP servers dropped out of /mcp under `omp auth-broker
serve` once their access token expired: neither the client nor the
broker could complete the refresh.

- Client: the MCP manager threw on the broker-redacted refresh sentinel
  (REMOTE_REFRESH_SENTINEL) instead of asking the broker to refresh. It
  now routes redacted MCP refreshes through
  AuthStorage.forceRefreshCredentialById, which calls back to the broker
  (the real refresh token never leaves the broker host).
- Broker: the serve process had no mcp_oauth:* refresh path, so
  POST /v1/credential/:id/refresh answered "Unknown OAuth provider". Its
  AuthStorage is now built with a refreshOAuthCredential override that
  refreshes MCP credentials with a generic refresh_token grant from the
  credential's embedded token endpoint and client id. The background
  refresher keeps MCP tokens live through the same path.

Extract shared refreshManagedMcpOAuthCredential and
mcpOAuthServerUrlFromCredentialId helpers so both paths use identical
refresh material selection and RFC 8707 fallback-resource logic.

Fixes #8933
2026-08-19 09:34:51 +00:00
roboomp 0808226ca3 fix(coding-agent): paint optimistic row for idle /skill submits
InputController.#invokeSkillCommand cleared the draft and awaited the full
promptCustomMessage dispatch with no transcript render. AgentSession.#promptWithMessage
runs awaited preflight (memory recall, before_agent_start hooks, auto-thinking
classification, pre-prompt compaction) before the message reaches the agent, so a slow
step such as a Hindsight auto-recall timeout left the composer cleared with no pending
row, unlike a normal prompt's optimistic row from startPendingSubmission.

Idle skill submissions now paint an optimistic skill row before the awaited dispatch;
the canonical message_start reconciles it in place via EventController instead of
appending a duplicate. Streaming submissions still queue and show their chip.

Fixes #8895
2026-08-19 09:19:47 +00:00
roboomp e6c0cf90a4 fix(compaction): reject stale pre-compaction anchor in context breakdown
getContextBreakdown used message position (anchorIndex >= pending.cutoffCount) as a proxy for usage freshness. After a mid-run compaction rebased the in-flight snapshot, an in-flight provider response whose request predated the compaction landed past the rebase cutoff carrying pre-compaction usage, so it out-ranked the rebased estimate and reported the pre-compaction token count (~2.6x the real one). That phantom overflow tripped the "freed too little context to make progress" guard and drove the frame-rescue path on a byte-identical tokensBefore.

Assistant context snapshots now carry a monotonic compaction epoch, bumped in rebaseAfterCompaction and stamped at message-record time. A post-cutoff anchor whose epoch predates the pending snapshot's epoch is no longer trusted over the rebased estimate.

Fixes #8887
2026-08-19 09:13:33 +00:00
roboomp 6996b36f4a fix(commit): fail loudly when staged binary truncates split-commit diff
Split-commit captured the staged diff with `git diff --cached --binary`,
whose stdout is hard-capped at GIT_COMMAND_OUTPUT_LIMIT_BYTES (8 MiB) by
readCappedText. A single large binary (base85-encoded inline) crossed the
cap; the capture was truncated silently, so files sorting after the binary
were absent from the parsed diff and stage.hunks threw a misleading
`No diff found for <path>` naming an innocent file.

Surface truncation as GitCommandResult.truncated, add a requireComplete
diff option that throws the new GitOutputTruncatedError instead of
returning a silently truncated diff, and have runSplitCommit request a
complete diff and abort with a clear message pointing at the real cause.

Fixes #8897
2026-08-19 09:07:29 +00:00
roboomp 7cff20cfd0 fix(tui): pin anchored regions under an unpinned streaming seam
TUI.render merged live-region seams with a topmost-seam-wins rule that
adopted only that seam's pin policy for the whole frame. While the primary
turn streams, the transcript reports the topmost, unpinned seam, so the
frame-wide pin flag becomes false and a pinned AnchoredLiveContainer below
it (the /btw panel, the working HUD) loses its pinning: once its content
grows past the viewport, the emit path commits the scrolled-off rows as
frozen snapshots on every growth frame, piling duplicates into native
scrollback.

Track a pinnedBoundary (start row of the topmost pinned region)
independently of which seam wins the topmost merge, and cap every commit
ceiling at it. Equivalent to the prior behavior for a fully-pinned frame
and for a frame with no pinned region; only the mixed case changes.

Fixes #8793
2026-08-19 08:51:13 +00:00
roboomp a0b7ca6708 docs: clarify bash.patterns gates bash tool only, not eval
bash.patterns only feeds the bash tool's approval decision. The eval
tool declares the exec tier and can spawn a shell via subprocess, so a
deny rule there does nothing for the same command run through eval;
under yolo the exec call resolves to allow. Note the scope and point at
tools.approval.eval as the lever that closes the path in
bash-tool-runtime.md, approval-mode.md, and settings.md.

Fixes #8838
2026-08-19 08:46:21 +00:00
roboomp 3acc57de8c fix(task): initialize extension runtime on subagent revival
Both subagent revivers rebuilt the session but never wired the extension
runtime, leaving it pre-init where every action method throws
ExtensionRuntimeNotInitializedError. An extension with a tool_call handler
touching a runtime action then tripped the fail-closed gate in emitToolCall
and blocked every tool, including the hidden yield, so the revived agent
could neither finish nor exit and looped until killed.

Both the warm lifecycle reviver (executor.ts) and the cold persisted
reviver (persisted-revive.ts) now call the shared initializeExtensions
helper on the rebuilt session, restoring runtime actions, onError, and the
session_start event.

Fixes #8824
2026-08-19 08:44:55 +00:00
can1357 d94bdfa1bb test: hardened new spinner and title-latch suites against full-suite pollution
- Exported stopSharedSpinnerTicker() and wired it into InteractiveMode.stop(): a live block missed by per-component stopAnimation kept the shared 80ms interval alive as a lingering event-loop handle; the spinner suite uses it to observe a freshly armed ticker instead of one leaked by earlier files
- Title-disposal tests now save/clear/restore PI_NO_TITLE (main() in ACP/RPC mode sets it process-wide), matching the prewarm and orphan-submit precedent
2026-08-19 03:20:50 +02:00
can1357 aa98ea9ed5 test: settled in-flight auto-title request between orphan-submit iterations
The title latch from PR #8911 dedupes a second title start while one is in flight; the orphan-submit loop implicitly relied on the first mocked request having settled. Drain its promise chain at a macrotask boundary before the next submit.
2026-08-19 02:04:51 +02:00
can1357 3566bd9b41 fix(ai): unified Cursor interaction-query handling after merging #8889 and #8830
- Kept the shared cursor/interaction-query module as the single handler and deleted the duplicate local implementation in cursor.ts
- Added the named webFetchRequestQuery approval case (field 9 is named under the regenerated proto)
- Preserved the deliberate no-fake-VM-success semantics for setupVmEnvironmentArgs (review of #8047)
- Updated the field-9 regression test to assert the named decode of the raw same-field reply, which also pins the LEN-prefix wire framing
2026-08-19 01:47:20 +02:00
can1357 20bd4ab97b chore(changelog): normalized [Unreleased] sections after merges and added missing entries
- Repaired union-merge artifacts in packages/coding-agent/CHANGELOG.md (duplicated 17.3.6/17.3.7 blocks; promoted the new entries back to [Unreleased])
- Added missing [Unreleased] entries for PRs #8833, #8866, #8879, #8903, #8905, #8915, #8916, #8917, #8920, #8923, #8928, #8929, #8937
2026-08-19 01:42:50 +02:00
can1357 e61775a470 fix(coding-agent): mention oauth exemption in apiKey validation error; add validation tests 2026-08-19 01:39:18 +02:00
can1357 539d841b10 Merge PR #8937: fix(coding-agent): allow auth oauth without apiKey in models.yml (@usr-bin-roygbiv) 2026-08-19 01:39:18 +02:00
can1357 17e47b3eb7 Merge PR #8920: fix(compaction): bound summarization input and stop retrying overflow (@PaleRoses)
# Conflicts:
#	packages/agent/src/compaction/compaction.ts
2026-08-19 01:39:07 +02:00
can1357 130cc9c0a3 fix(tui): also accept legacy CSI ~ Shift+Enter form in /tree selector
Mirrors the composer's raw-sequence fallback (editor.ts:1466) so
\x1b[13;2~ triggers summarize-and-switch instead of being dropped as
shift+f3, completing the parity requested in issue #8821.
2026-08-19 01:38:35 +02:00
can1357 f60e32f9b8 Merge PR #8916: fix(tui): treat bare LF as Shift+Enter in the /tree selector (@re2zero) 2026-08-19 01:38:35 +02:00
can1357 fc24a491fb Merge PR #8915: fix(session): only advertise --resume when the session is on disk (@re2zero) 2026-08-19 01:38:35 +02:00
can1357 74366ee996 Merge PR #8911: fix(session): generate titles from /skill invocation args (@qiyi71w) 2026-08-19 01:38:34 +02:00
can1357 195033a432 Merge PR #8909: fix(coding-agent): condition think prelude guidance for subagents (@olegpulatov) 2026-08-19 01:38:34 +02:00
can1357 c57d710a67 Merge PR #8905: Advisor blocker advisories wake a new turn instead of parking in the immune window (@STRML) 2026-08-19 01:38:34 +02:00
can1357 12cfaceef1 Merge PR #8903: fix(discovery): expand extension-package MCP env placeholders (@drycode) 2026-08-19 01:38:34 +02:00
can1357 22439b6be2 Merge PR #8896: fix(settings): hide excluded search providers from summary (@poorpaper) 2026-08-19 01:38:34 +02:00
can1357 0e8c451f66 Merge PR #8889: fix(cursor): answer interactionQuery and resume idle-stall MCP turns (@bnivanov) 2026-08-19 01:37:01 +02:00
can1357 9975e5c70e docs(coding-agent): fix stale worker-cwd comment in js eval process entry
resolveWorkerSpawnCmd no longer pins the host-entry worker cwd to the
install dir; the subprocess inherits the agent cwd (or the package root
under the bun-test fallback). Update the chdir rationale accordingly.
2026-08-19 01:37:01 +02:00