Commit Graph

811 Commits

Author SHA1 Message Date
can1357 8c35861d96 feat(coding-agent): implemented ordered compaction fallback and settings
- Replaced legacy `compaction.strategy` and `remoteEnabled` settings with `compaction.methodOrder` across session maintenance, schema, and tests.
- Added automatic fallback mechanism to try subsequent compaction methods upon failure or unsupported model capabilities.
- Added mouse drag-and-drop reordering support and click handlers to multi-select settings submenus.
- Updated documentation and test suites to reflect ordered compaction strategy preferences and fallback chains.
2026-08-20 02:59:49 +02:00
can1357 0cdd37fc15 feat(pi-natives/tools): implemented utok tokenizer for multiple models
- Replaced the `ctok` implementation with the `utok` universal tokenizer supporting multiple model families and UTF text encodings.
- Added tokenizer support and embedding data for Qwen3, DeepSeek V3, Kimi K2, and GLM-5 model variants.
- Added fixture generation scripts, vocabulary packers, and golden test suites for validating tokenization parity.
- Updated dependency requirements and Bazel workspace definitions for new crates and tools.
2026-08-20 01:45:04 +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
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
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 8a74892c3b Merge PR #8864: fix(task): refresh model roles before agent discovery (@z80dev) 2026-08-19 01:37:00 +02:00
can1357 68c636f0b5 Merge PR #8717: fix(pi-ai): honor onPayload replacement payloads in openai-completions, bedrock and cursor (@ranxianglei) 2026-08-19 01:36:03 +02:00
can1357 565d53515b feat(coding-agent): added providers.cacheRetention setting for prompt caching
- Add the `providers.cacheRetention` setting to control prompt-cache retention options per request.
- Forward configured cache retention preferences through the settings-aware stream function.
- Update documentation and test coverage for long cache retention behaviors.
2026-08-19 00:56:50 +02:00
bnivanov f5976d7129 fix(session): resume Cursor idle stalls after unmarked MCP results
The idle watchdog aborts the request signal and cursor.ts closes
the Connect stream, so there is no in-flight server exec to race.
Unmarked MCP/todo blocks can continue once every emitted call has
a matching result, same as HTTP/2 RST.
2026-08-18 14:48:45 +02:00
bnivanov 271e7ba892 fix(cursor): answer interactionQuery so hosted fetch can continue
Cursor hosted web search / Exa / unnamed field-9 WebFetch send
interaction_query and block the Run RPC until the client writes
interaction_response. Dropping the frame leaves the HTTP/2 stream
alive on heartbeats that are not semantic progress, so the 300s
idle watchdog aborts with "Provider stream stalled while waiting
for the next event".

Approve network permission gates and reject interactive
ask / switch-mode / create-plan. Leave VM setup unanswered
rather than inventing a success result.
2026-08-18 14:48:45 +02:00
ranxianglei 9aefdb5f81 Merge branch 'main' into fix/onpayload-replacement-completions-bedrock-cursor 2026-08-18 09:13:09 +08:00
z80 ced78801ba fix(task): refresh model roles before agent discovery 2026-08-17 20:43:06 -04:00
can1357 bf8537015e Merge branch 'main' into pr-8772 2026-08-17 15:55:20 +03:00
can1357 ba71a0aa6c docs(extensions): included sessionId in delete fallback request shape 2026-08-17 11:06:16 +03:00
can1357 9913c58ec1 Merge branch 'main' into pr-8052 2026-08-17 11:00:58 +03:00
Yang Yang 848f7fb0fd feat(catalog): default paid xAI and SuperGrok to grok-4.6
Point xai and xai-oauth at grok-4.6, already in the bundled catalog.
Tests pin the default id in models.json and load picker fixtures from
the catalog so the next bump does not rot hardcoded name or cost.
2026-08-16 16:29:14 -07:00
ranxianglei 574a83f5f5 fix(pi-ai): honor onPayload replacement payloads in openai-completions, bedrock and cursor
The onPayload hook contract (README, docs/extensions.md) is that a non-undefined
return replaces the provider request payload, and every provider except these
three implements it (anthropic, openai-responses family, google, ollama — see
the earlier fix for the responses providers). openai-completions, amazon-bedrock
and cursor invoked the hook fire-and-forget and sent the original payload, so
extensions hooking before_provider_request could never transform the wire body
on these providers.

- openai-completions: await the hook and apply a non-undefined replacement to
  the params used for the request body, raw request dump and error-path
  fallback state
- amazon-bedrock: same for the ConverseStream command input
- cursor: await the hook for the AgentRunRequest; buildGrpcRequest becomes
  async and is exported for direct testing (transport is HTTP/2)
- devin-agent intentionally unchanged: it does not fire the hook at all (its
  payload is a protobuf object), which is a feature gap rather than a dropped
  replacement; documented in README/docs instead
- regression tests: captured wire body reflects async/sync replacement, and an
  undefined return keeps the original payload (completions + bedrock over a
  mocked fetch; cursor by decoding the serialized run request)
2026-08-16 19:22:49 +08:00
can1357 7af249b190 fix(coding-agent): preserved tool-search history on disk 2026-08-16 02:43:33 +02:00
can1357 c9da0718ba Merge PR #8572: fix(lsp): gate rust-analyzer/reloadWorkspace behind rust-analyzer check (@roboomp) 2026-08-16 02:43:33 +02:00
can1357 dba8cfcd13 Merge PR #8677: fix(browser): prefer Chrome for Testing on macOS headless launch (@roboomp) 2026-08-16 02:43:30 +02:00
can1357 4a37b7cc09 docs(browser): qualified spawned kill behavior 2026-08-16 02:13:39 +02:00
can1357 92ce5db781 Merge PR #8651: fix(browser): clarify close release semantics (@koopmannleon19977-cmyk) 2026-08-16 02:13:38 +02:00
can1357 9af713f2b0 Merge PR #8576: fix(mcp): keep Exa MCP servers that request non-native tools (@dhruvkej9) 2026-08-16 02:13:38 +02:00
can1357 ea8d1d2191 docs(coding-agent): restored retry policy trailing newline 2026-08-16 02:03:17 +02:00
can1357 210cce26bd Merge PR #8516: fix(session): resume Cursor turns after HTTP/2 stream reset (@joseotaviorf) 2026-08-16 02:03:17 +02:00
can1357 c84954435b Merge PR #8537: fix(ai): report Umans usage from weighted effective requests (@MertSoylu) 2026-08-16 02:03:15 +02:00
can1357 ca297741cb Merge PR #8538: fix(coding-agent): keep the system prompt byte-stable across date/cwd changes (@MertSoylu) 2026-08-16 02:03:14 +02:00
roboomp d9eb0586bd fix(browser): prefer Chrome for Testing on macOS headless launch
On macOS the shared headless browser daemon launched from the system Google Chrome app bundle, running as a com.google.Chrome instance. macOS LaunchServices could then deliver the user's open-URL Apple Events to the daemon instead of their own Chrome, silently swallowing link clicks.

ensureChromiumExecutable now prefers the isolated Chrome for Testing binary (com.google.chrome.for.testing) on macOS, falling back to system Chrome only when Chrome for Testing cannot be obtained. Other platforms keep the download-avoiding system Chrome preference.

Fixes #8673
2026-08-15 19:38:25 +00:00
MertSoylu 9f6fc1f0c7 fix(ai): surface Umans request exhaustion without a burst ceiling
When a payload reports weighted counters but omits hard_cap, the soft/hard
split collapses to a single umans:requests row keyed off the authoritative
weighted effective-request counter, so a spent account can report exhausted
instead of being stuck at warning forever. Raw burst traffic above the limit
still never fabricates exhaustion; weighted headroom stays decisive (#7858).
2026-08-15 18:16:45 +03:00
koopmannleon19977-cmyk 7b6029277a fix(browser): clarify close release semantics 2026-08-15 15:11:49 +02:00
Yang Yang 86866b8bbf fix(catalog): omit Responses penalties on all first-party xAI models
xAI's /v1/responses rejects presence/frequency penalties for every Grok
model, not only reasoners. Gate supportsPenaltyAndStopParams on isXaiHost
so xai/grok-2 no longer serializes presence_penalty.
2026-08-14 22:02:52 -07:00
Yang Yang 01db5b04ee fix(catalog): omit unsupported reasoning.summary on paid xAI Responses
First-party xAI /v1/responses rejects reasoning.summary. Bake
supportsReasoningSummary=false for both xai and xai-oauth so paid
grok-4.5 effort requests send only reasoning.effort, matching SuperGrok.
2026-08-14 22:02:07 -07:00
Yang Yang 651f20957b feat(catalog): replay xAI encrypted reasoning on later turns
Stop stripping type=reasoning history for xai and xai-oauth so
encrypted_content from include is sent back on the next Responses request.
2026-08-14 22:00:50 -07:00
Yang Yang c228dea58b feat(catalog): route paid xAI through Responses like SuperGrok
Switch XAI_API_KEY models from Chat Completions to /v1/responses, default
both xai and xai-oauth to grok-4.5, and include reasoning.encrypted_content.
2026-08-14 22:00:50 -07:00
roboomp 40e830f9cf fix(lsp): gate rust-analyzer/reloadWorkspace behind rust-analyzer check
reloadServer() sent the rust-analyzer-specific rust-analyzer/reloadWorkspace
request to every server before falling back to workspace/didChangeConfiguration.
Servers that crash on an unknown method instead of replying -32601 (Roslyn,
dotnet/roslyn#84890) were killed by `lsp reload` rather than reloaded.

Gate the request on isRustAnalyzerClient (exported from client.ts) or a
"rust-analyzer" server name; every other server reloads via
workspace/didChangeConfiguration directly. Consolidate tool.ts's inline
rust-analyzer detection onto the same helper.

Fixes #8571
2026-08-15 04:04:28 +00:00
dhruv.kejriwal f36cf20d56 fix(mcp): keep Exa MCP servers that request non-native tools
Exa MCP servers were always filtered out because the native Exa integration covers web_search_exa. But configs that explicitly request web_fetch_exa or web_search_advanced_exa have no native equivalent, so filtering them made /mcp reconnect exa fail and hid those tools. Keep the MCP server mounted when its tools restriction includes anything beyond web_search_exa, while still extracting the API key for native search.
2026-08-15 00:39:58 +05:30
Larry Gordon cb4b936b93 fix(extensions): rebuilt the fallback context on each invocation
Review follow-up on #8052. The fallback trampolines captured one
`ExtensionContext` at `ExtensionRunner.initialize` and reused it for the
life of the session, unlike every other dispatch site, which builds one
per call. `createContext()` materializes `cwd` and `hasUI` as values, so
a handler kept seeing the workspace the runner initialized in — wrong
the moment `SessionManager.moveTo()` relocates the session (`/move`),
where a handler that scopes or prompts against `ctx.cwd` would allow the
old workspace and deny the new one.

Both trampolines now build the context inside the invocation. A denied
mutation is a rare path, so the extra object costs nothing that matters,
and anything else `createContext()` snapshots is refreshed with it.

Covered by an integration test that moves the session's cwd after
initialize and asserts the handler sees the new one; hoisting the
context back out of the invocation fails it.
2026-08-14 08:55:45 -07:00
Larry Gordon 6ad935d093 fix(extensions): resolved brokered file paths and named their session
Review on #8052 found three problems in the write/delete fallback seam.

A symlink guard that only `lstat`'d the final component let the same
escape through a symlinked ancestor: `ws/link/file` under a
`ws/link -> /outside` link reached a handler as a lexically innocent
path, so a helper's prefix allowlist passed while the bytes landed
outside. Refusing every symlinked component is not available, since
`/var` and `/tmp` are links on macOS and every path under `os.tmpdir()`
traverses one. So `req.dst` is now the path the failed syscall itself
acted on, via `resolveSyscallTarget` beside `confineToWorkspace`: fully
resolved for a write, resolved up to the last component for a delete,
because `unlink` removes a link rather than following it. Resolving also
closes the TOCTOU window a refusal left open. A path that cannot be
canonicalized — a dangling final link, or an ancestor whose own
resolution is denied — is not brokered at all.

Per-handler throw isolation lived outside the per-extension trampoline,
so a throw from one extension's first handler advanced the registry to
the next extension and skipped every later handler that one had
registered. Each handler call is now wrapped individually.

The registry stays process-wide. A subagent spawned with restricted
tools gets `preloadedExtensionPaths: []` and loads no extensions of its
own, so scoping resolution to the originating session would turn its
brokered writes into hard failures, and a host that registers once in
its top-level session expects its subagents covered. The request names
its origin instead: `req.sessionId` against the handler's own
`ctx.sessionManager.getSessionId()`, entered by `ExtensionToolWrapper`,
which `sdk.ts` already puts around the whole tool registry whenever a
runner exists. Both registries are also walked over a snapshot, so a
concurrent session shutdown cannot make another session's walk skip
whichever handler shifted into the hole.

Unit tests go 30 -> 35 and integration 6 -> 7, covering the resolved
target, a symlinked ancestor on both seams, a dangling link, a target
whose own metadata is behind the boundary, same-extension handler
ordering after a throw, and `req.sessionId` matching the handler's own
session end to end.
2026-08-14 08:55:44 -07:00
Larry Gordon 6e4334c003 feat(extensions): broker denied file writes and deletes
A host that runs omp inside an OS sandbox can grant a path mid-session but cannot
apply that grant to an in-process write: `write` and `edit` do their I/O in the
agent process, so an out-of-workspace write fails and stays failed until the
process restarts under a wider profile.

Nothing available today closes that. A `tool_call` handler can block and a
`tool_result` handler can rewrite content, but neither can re-run a tool.
`ctx.invokeTool` delegates execution, but the delegated native tool runs in the
same process under the same restrictions. And the failure lands AT the write
syscall - after the tool computed the final content, before it returned - so the
bytes are gone with the throw, and reconstructing them means reimplementing
`edit`'s hashline protocol and the snapshot bookkeeping.

The byte-write that `write`, `edit` and `apply_patch` perform on an ordinary file
path already funnels through one two-line primitive
(`file ? file.write(content) : Bun.write(dst, content)`) at four call sites.
Routing that primitive through `writeFileWithFallback` gives an embedder a single
seam to intercept a permission-denied write: the native tool still records its own
snapshot under the real destination path once a handler reports success, so a
follow-up hashline `edit` on that path keeps working.

Only a permission boundary diverts - `EPERM`/`EACCES`/`EROFS`. Two cases needed
more than that:

- `Bun.write` creates missing parents itself, and when that `mkdir` is the denied
  operation it reports the subsequent `open()`'s `ENOENT` instead of the denial -
  making a sandboxed write into a new out-of-tree directory indistinguishable from
  an ordinary bad path. Redoing the `mkdir` explicitly recovers the real errno, and
  because it runs through the same enforcement path as the write it also sees
  kernel-level denials (Seatbelt, LSM) that a `stat`/`access` probe reports as
  writable. If no handler takes the write, the original `ENOENT` is still what
  propagates, with the recovered denial attached as its `cause`.
- `apply_patch` creates the parent as a separate step before writing, so a denial
  there threw before the seam was ever reached. That `mkdir` now tolerates a
  permission denial when a fallback is registered, letting the write report it.

A denial reached through a SYMLINK is never brokered. The in-process write follows
the link, so the kernel denied the link's TARGET, but a handler receives `dst` and
a privileged helper opening it with ordinary follow semantics would land the bytes
wherever the link points. That also defeats the obvious helper-side defence, since
a prefix allowlist passes when the link sits inside the allowed root while its
target does not. omp cannot vouch for the destination, so it refuses rather than
hand the ambiguity to a privileged writer - the same answer `confineToWorkspace`
already gives an unresolvable link.

Removing a file is a different primitive, so it gets its own seam
(`deleteFileWithFallback`, `registerFileDeleteFallback`) covering `edit`'s `REM`,
a hashline `MV`'s source unlink, and `apply_patch`'s delete op. Two differences
from the write path: `ENOENT` is never diverted, since nothing is created on the
way to an unlink and `REM` needs it to become a not-found error; and the seam
refuses a target it can confirm is a directory, because `unlink` on a directory
reports `EPERM` on Darwin and is otherwise indistinguishable from a sandbox
denial. That check cannot always run - a sandbox denying the unlink usually denies
the target's metadata too - so the request carries `confirmedFile`, and a handler
is required to use a plain unlink rather than resolving or recursing.

The two registries are deliberately separate. A write handler brokers `content` to
`dst`, so a delete request reaching it with no content invites brokering an empty
write and truncating the file it was asked to remove.

With nothing registered both seams are inert: the primitives run exactly as
before, a failure rethrows from the same place, and no extra syscalls are
performed.

Scope is deliberately narrow. Archive-member and SQLite writes are unchanged -
neither is a byte-write to a path, so brokering them needs a different request
shape - along with the ACP bridge's `writeTextFile`, the `lsp` tool's own
workspace-edit and formatter writes, and directory removal.
2026-08-14 08:52:34 -07:00
MertSoylu 30f92ad986 fix(coding-agent): keep the system prompt byte-stable across date/cwd changes
Move the per-request date/cwd line out of the system prompt into a
first-turn system-reminder so open-weight providers keep their tool-schema
prefix cache; the reminder refreshes itself at midnight. Closes #7404.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-14 13:16:54 +03:00
MertSoylu f02679bdf5 fix(ai): report Umans usage from weighted effective requests
Split the request limit into a weighted soft-cap row and a raw burst-ceiling
row so healthy accounts no longer read as exhausted; surface the rolling
window's resets_at as a countdown. Closes #7858.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-14 12:10:18 +03:00
José Otávio Rizzatti Ferreira 63ac830b50 fix(session): resume Cursor turns after HTTP/2 stream reset 2026-08-14 01:56:14 -04:00
can1357 ad318c7572 build: configured docker build pipelines for cargo native addons
- Switched Docker images to build native addons via cargo/napi-rs (`OMP_NATIVE_BUILD_BACKEND=cargo`) instead of Bazel.
- Updated Cargo.toml workspace members explicitly to prevent loading errors from stale directories under crates/.
- Added depth-agnostic patterns to .dockerignore files to exclude nested build outputs from Docker build contexts.
- Added OMP_NATIVE_CARGO_PROFILE environment variable to support configuring cargo profiles for addon builds.
2026-08-14 07:09:48 +02:00
can1357 58f319912e feat: introduced dynamic version discovery and rate limit parsing for google
- Added dynamic Antigravity version discovery with environment variable overrides and fallback endpoint support.
- Introduced structured Google RPC `ErrorInfo` rate limit reason parsing and backoff classification.
- Added `gemini-3.7-flash` and `deepseek-v4-pro:preview` model configurations alongside updated pricing.
- Removed system instruction injection logic and dropped unsigned thinking blocks for Antigravity requests.
2026-08-13 23:59:37 +02:00
can1357 a2aad5408e Merge PR #8443: fix(natives): static-link win32 MSVC CRT so addon needs no VC++ redist (@roboomp) 2026-08-13 18:46:08 +02:00
roboomp 2e2bf1f3a5 fix(natives): pin cmake opus build to static MSVC CRT (/MT)
The win32 addon static-CRT switch enabled the static_link_msvcrt cc
feature, but audiopus_sys's bundled opus is built through the generated
CMake toolchain, which pinned CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL
(/MD) as authoritative under CMP0091 NEW. The opus objects could then
still emit /MD and pull VCRUNTIME140.dll / conflict with the static CRT
the rest of the addon links, leaving the outcome dependent on compile-
flag ordering.

Pin CMAKE_MSVC_RUNTIME_LIBRARY to MultiThreaded (static release /MT) in
the msvc toolchain.cmake so opus deterministically matches rustc's
+crt-static and the static_link_msvcrt feature.

Verified with a fully cold `bazel build //:natives-win32-x64-baseline`
(opus recompiled): the produced .node imports no VCRUNTIME140.dll and no
api-ms-win-crt-* — only core Windows system DLLs.

Fixes #8439
2026-08-13 16:21:23 +00:00
roboomp 246dda7f1c fix(natives): static-link win32 MSVC CRT so addon needs no VC++ redist
The shipped win32-x64 pi_natives addon linked the dynamic MSVC CRT (/MD)
and imported VCRUNTIME140.dll from the Visual C++ Redistributable, which
is absent on a clean Windows install. LoadLibrary of the extracted .node
then failed with error 126 ("The specified module could not be found"),
so omp could not start after a fresh `irm install.ps1 | iex`.

Static-link the CRT for the win32 addon: +crt-static for rustc (crate
BUILD select) plus the static_link_msvcrt cc feature enabled for win32 in
the native_addon transition, so its C deps (opus/cmake, tree-sitter,
blake3, ring) compile /MT in lock-step. The rebuilt .node imports only
core Windows system DLLs -- no VCRUNTIME140.dll, no api-ms-win-crt-*.

Fixes #8439
2026-08-13 16:00:33 +00:00
roboomp bb0314a5a1 fix(tui): stopped direct herdr pane flicker
Kept direct Herdr panes on the host-safe in-place resize path so streaming redraws no longer clear and replay pane scrollback.

Updated the resize regression, stress scenario, renderer docs, and changelog.

Fixes #8431
2026-08-13 14:34:03 +00:00
can1357 2d512cb253 refactor: generalized thinking loop guard for multiple model families
- Generalized thinking loop guard and helper functions to support Gemini, DeepSeek, and Grok model families.
- Replaced `withGeminiThinkingLoopGuard` and related Gemini-specific symbols with generalized counterparts.
- Removed deprecated `enableGeminiThinkingLoopGuard` options and associated tests.
- Updated test suites and agent session logic to use the generalized thinking loop guard and model family tokens.
2026-08-13 06:15:00 +02:00
can1357 dc7784e4b4 feat(nix): implemented wayland screencast support and restructured package builder
- Added `withWaylandScreencast` package override option to selectively link libpipewire for Wayland screencast support.
- Refactored Nix package builder structure to eliminate wrapper scripts and directly install binary outputs.
- Updated home-manager module description to clarify declarative settings file behavior and symlink rules.
2026-08-13 05:25:22 +02:00