Commit Graph
8105 Commits
Author SHA1 Message Date
Mathews-Tom febcd8e488 fix(secrets): redact matching prefix before a cut placeholder
A regex match that starts in outside text and ends inside a previously
generated `#…#` placeholder's expanded value was skipped wholesale by
resuming the scan past the placeholder. An independently-matching outside
prefix was therefore left provider-visible — e.g. `[A-Z0-9]{8,12}` greedily
spanning `SECRETUV` into an `ABCDEFGH` placeholder returned `SECRETUV#…#`
even though `SECRETUV` satisfies the regex on its own.

The cut handling now re-runs the regex bounded to just before the
placeholder (full left context kept, so lookbehind still evaluates) and, when
the prefix forms a standalone match, redacts it — to its own reversible
placeholder in obfuscate mode, or a one-way redaction in replace mode — while
the cut secret stays as its existing placeholder. The replace default
redaction's fixed point is now verified against the placeholder-expanded view
re-obfuscation actually scans, so it does not drift when the adjacent
placeholder expands and connects to the redaction's trailing bytes.

Refs #2465
2026-06-30 06:34:58 +05:30
Mathews-Tom d07f539a44 fix(secrets): evaluate replace-regex fixed point against full context
The deterministic-replacement collision search truncated the surrounding
text to a 512-byte window before testing whether a candidate redaction
would be re-matched in place. A replace-mode regex whose lookbehind or
lookahead reaches beyond that window (e.g. `(?<=A{600})[AZ]`) then had its
assertion context dropped, so the check falsely accepted a candidate the
pattern DOES re-match once the full prefix is present. The redaction
oscillated back to the raw matched value on alternating obfuscate() passes,
leaking it to the provider every other turn.

The probe now substitutes the candidate into the full text so lookbehind /
lookahead always evaluate against complete context, and the scan starts a
bounded distance left of the span and stops once a match begins at/after the
span end, keeping per-candidate cost independent of total text length.

Refs #2465
2026-06-30 06:03:31 +05:30
Mathews-Tom d6a8534eab fix(secrets): derive replace-remainder marker from key and length for restart stability 2026-06-30 05:15:35 +05:30
Mathews-Tom 0c34b79a52 fix(secrets): evaluate replace-regex fallback redactions in surrounding context 2026-06-30 04:51:17 +05:30
Mathews-Tom 1620d6e456 Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names 2026-06-30 04:28:22 +05:30
can1357 0ba736f5bc chore: bump version to 16.2.6 2026-06-29 20:14:08 +02:00
can1357 d03ea52891 refactor(ai): improved provider in-flight lease signal routing
- Update `releaseProviderInFlightLease` to signal into the specific directory path associated with the lease rather than recomputing it from the root.
- Introduce `signalProviderInFlightWaitersInDir` to decoupling waking waiters from global provider path resolution.
- Remove redundant tests from `coding-agent`.
2026-06-29 20:04:24 +02:00
can1357 1c7172f7c8 chore: update changelogs 2026-06-29 19:48:18 +02:00
can1357 ffa8519801 Merge remote-tracking branch 'origin/farm/3f9e6955/mcp-reauth-force-fresh-login' 2026-06-29 19:47:23 +02:00
roboomp 4ce9d659c9 fix(mcp/oauth): align prompt behavior with mcp sdk
The initial PR update changed the MCP OAuth default prompt to 'login consent'.
The reporter verified Cloudflare's flow actually matches the reference MCP SDK
when no prompt parameter is sent: Cloudflare then reuses the existing account
grant and opens the scope/permission picker first. Forcing any prompt keeps the
flow on Cloudflare's account/consent page instead.

Match the reference SDK behavior: omit prompt by default and send
'prompt=consent' only when the requested scope contains offline_access, where
OIDC Core requires re-consent for offline access. Explicit oauth.prompt values,
including the empty-string omit escape hatch, still take precedence.

Also rename the dynamically registered MCP OAuth client from Codex to oh-my-pi
so Cloudflare consent screens show the current product name.

Fixes #3817
2026-06-29 17:32:58 +00:00
roboomp a49c7027bf fix(mcp/oauth): force login screen before consent on /mcp reauth
The MCP OAuth flow defaulted the authorization-request prompt parameter
to 'consent'. Per OpenID Connect Core 1.0 §3.1.2.1 that asks the
authorization server to re-prompt for consent only while reusing the
existing browser authentication session. Cloudflare's MCP OAuth server
(and other strict OIDC providers) honor that literally, so /mcp reauth
landed on the consent screen attached to whichever account the browser
cookie was for, leaving no way to switch the signed-in account.

Default to 'login consent' instead so the provider first re-prompts for
authentication (the page Claude Code shows on its reauth flow) and then
re-confirms consent, preserving the original intent of always
re-displaying the authorize screen. RFC 6749 §3.1 requires providers to
ignore prompt values they do not support, so the two-value form is safe
for non-OIDC servers. Existing per-server overrides via mcp.json's
`oauth.prompt` (including the empty-string escape hatch) are unchanged.

Fixes #3817
2026-06-29 17:21:28 +00:00
can1357 6e166274cb fix(web-search,mcp): reused gemini oauth helper and formatted npx shim 2026-06-29 16:56:43 +02:00
can1357 faf2b4111e chore(changelog): normalize unreleased spacing after merge sweep 2026-06-29 16:51:16 +02:00
can1357 b4f75abb30 fix(cli): strip Windows worker fallback executable 2026-06-29 16:45:47 +02:00
can1357 64be11e289 Merge PR #3806: fix(cli): preserve Windows extension paths (@roboomp) 2026-06-29 16:45:47 +02:00
can1357 6f8f76be43 Keep DuckDuckGo result cap unchanged 2026-06-29 16:45:47 +02:00
can1357 579b4f3f10 Merge PR #3800: fix(web-search): scrape DuckDuckGo HTML frontend instead of Instant Answer API (@roboomp) 2026-06-29 16:45:46 +02:00
can1357 45df90bdac fix(mcp): preserve non-npx cmd-shim direct launch 2026-06-29 16:45:46 +02:00
can1357 c90bef647e Merge PR #3796: fix(mcp): preserve npx cmd shim launching (@roboomp) 2026-06-29 16:45:46 +02:00
can1357 6259792bd7 Merge PR #3811: fix(providers): support Gemini API key web search (@roboomp) 2026-06-29 16:45:46 +02:00
can1357 17c4aa0391 Merge PR #3795: fix(cli): honor web search provider settings in omp search (@roboomp) 2026-06-29 16:45:45 +02:00
can1357 5d2f972edd Merge PR #3790: fix(session): avoid ctrl-c rewrites for compacted sessions (@roboomp) 2026-06-29 16:45:45 +02:00
can1357 48add4fc7e Merge PR #3787: fix(coding-agent): bound edit-tool oldText/newText snapshots in tool-result details (@roboomp) 2026-06-29 16:45:45 +02:00
can1357 1eb32a5df1 feat(coding-agent/bench-cli): tracked and close provider session states
- Added management of provider session states during benchmark execution.
- Implemented a teardown process to close and clear session states after request completion.
2026-06-29 16:31:21 +02:00
roboomp 530113eb71 fix(providers): supported gemini api key search
Enabled the Gemini web search provider to use standard Google developer API credentials when Cloud Code Assist OAuth is absent.

Added developer API request coverage for native Google Search grounding and preserved existing OAuth request serialization.

Fixes #3810
2026-06-29 13:51:42 +00:00
roboomp 777b609e63 fix(cli): preserved windows extension paths
Rejoined split Windows extension module paths before launch parsing finishes and stripped extended-length Win32 prefixes before Bun import and worker spawn APIs see them.

Fixes #3804
2026-06-29 11:50:36 +00:00
roboomp 75db042744 style: bun run fix 2026-06-29 09:49:49 +00:00
roboomp 755a61de07 fix(web-search): scrape DuckDuckGo HTML frontend instead of Instant Answer API
The DuckDuckGo provider hit api.duckduckgo.com (the Instant Answer API),
which only serves Wikipedia / Wolfram-Alpha-style topics — empty
AbstractText / Results / RelatedTopics for the vast majority of agent
queries. The orchestrator then rejected the empty response and surfaced
'DuckDuckGo returned no renderable search content', leaving users with
no working free fallback.

Switch the provider to POST html.duckduckgo.com/html/ (the no-JS HTML
frontend) with a browser User-Agent, parse the result blocks (unwrapping
//duckduckgo.com/l/?uddg=… redirect URLs), and map recency to the df
form field (d/w/m/y). When DuckDuckGo serves the bot-detection modal
(HTTP 200/202 with anomaly-modal body) we surface a clear
SearchProviderError so the orchestrator can fall through to the next
provider with cause attached.

Fixes #3799
2026-06-29 09:48:46 +00:00
roboomp 67730e50e1 test(search): restored profile env after cli provider tests
Restored OMP_PROFILE and PI_PROFILE after the search CLI provider-settings tests override the agent dir, then rebuilt the directory resolver from env.

Fixes #3793
2026-06-29 09:19:47 +00:00
roboomp 3a9eed6194 style: bun run fix 2026-06-29 09:12:36 +00:00
roboomp e29792afea fix(mcp): preserved npx cmd shim launching
Kept PATH-resolved Windows npx.cmd shims on the cmd.exe wrapper path so npm owns subprocess stdio exactly like the reporter's working cmd /c configuration.

Fixes #3794
2026-06-29 09:12:16 +00:00
roboomp ba6b64bf89 fix(search): honored explicit --provider auto override
Distinguished an absent provider (use configured preferred provider) from an explicit `--provider auto` (one-shot bypass that still respects exclusions) in executeSearch.

Fixes #3793
2026-06-29 09:08:37 +00:00
roboomp 3560d108db fix(cli): applied search provider settings
Initialized standalone search commands with configured web-search provider globals before resolving the implicit provider chain.

Fixes #3793
2026-06-29 08:55:53 +00:00
roboomp cc2cf5c7d0 fix(session): scope compaction elision to active branch
Restrict the supersede sweep to compactions on the path from the current leaf so a newer compaction never rewrites a sibling branch's still-current summary or drops its preserveData. Streaming load now collects the active-branch ids before eliding instead of trampling sibling compactions encountered in file order.

Refs #3789
2026-06-29 06:22:04 +00:00
roboomp e8b2c5d058 fix(session): avoid ctrl-c rewrites for compacted sessions
Stream large session loads, elide superseded compaction payloads, skip synchronous rewrites when the append-only file is already current, and provide usable picker previews for developer-started forks.

Fixes #3789
2026-06-29 06:13:43 +00:00
can1357 ec873fa397 test(auth): validated websocket preference and session state propagation
- Added test assertions for `preferWebsockets` parity in `advisor-provider-options-parity.test.ts`.
- Introduced a benchmark test to verify propagation of `providerSessionState` and `preferWebsockets` in `bench-auth-fallback.test.ts`.
2026-06-29 08:05:02 +02:00
can1357 312b71b0a5 feat(sdk): enabled websocket transport configuration for sdk and cli
- Added `preferWebsockets` option to `AgentSessionConfig` to expose transport preferences.
- Updated `AgentSession` to manage and forward websocket preferences to sub-sessions.
- Enabled websocket transport by default for benchmark CLI requests.
2026-06-29 08:05:02 +02:00
roboomp c21cb6325a fix(coding-agent): wrap hashline multi-section aggregate in shared snapshot cap
The hashline multi-section path in `executeHashlineSingle` returned
`perFileResults: rendered.map(r => r.perFileResult)` directly. Each
per-section result had already been individually pruned by
`renderSection`, but the whole array bypassed the shared aggregate
budget added in 3987969 — a single hashline payload touching many files
with sub-32 KB snapshots each could still serialize unbounded snapshot
bytes into one session JSONL line.

Wrap the multi-section return in `pruneOversizedEditSnapshots`, which
delegates to `capPerFileSnapshots` and enforces the shared cap walking
left-to-right; early sections keep their ACP diff visualization, later
sections in a many-file batch degrade to text-only.

End-to-end regression test seeds five real on-disk files (~10 KB
combined snapshots each), runs a multi-section hashline SWAP via
`executeHashlineSingle`, and asserts the aggregate result holds the
cumulative kept snapshot bytes under `MAX_EDIT_SNAPSHOT_TEXT_CHARS`
with at least one section pruned.
2026-06-29 05:37:35 +00:00
can1357 ba2add1374 Merge remote-tracking branch 'origin/farm/fe3a4a33/prune-edit-snapshots' 2026-06-29 07:33:01 +02:00
roboomp 398796949f fix(coding-agent): cap perFileResults snapshots with shared aggregate budget
The per-entry 32 KB cap let a many-file batch (apply_patch / hashline
touching N files) accumulate unbounded snapshot bytes because each
`perFileResults` entry was checked independently. 100 files × 30 KB
each kept everything (~3 MB) even though the whole array still
serializes into one session JSONL line.

`capPerFileSnapshots` walks entries left-to-right with one shared
`MAX_EDIT_SNAPSHOT_TEXT_CHARS` budget. Each per-entry payload is still
capped individually by `pruneSnapshot`; if an entry's surviving bytes
would push the running aggregate past the cap, the entry is stripped
and stamped with `snapshotsPruned: true`. Early entries keep their ACP
diff visualization; later entries in a large batch degrade to text-only
exactly like over-sized single edits.

Regression test exercises five equal-size entries that each fit the
per-entry budget but bust it cumulatively, asserting only the first two
keep snapshots and the trailing three carry the pruned marker.
2026-06-29 05:28:29 +00:00
roboomp 3ced3a923e fix(coding-agent): preserve pruned-snapshot marker through single-path aggregation
When a multi-entry single-path edit prunes the first entry's snapshots
(large pre-image) and keeps a later entry's snapshots (file shrunk
between entries), the aggregator at `executeSinglePathEntries` recorded
the later entry's small `oldText`/`newText` as the whole-file
transition. ACP clients would then render a misleading partial diff
instead of degrading to text-only for the over-budget edit.

Add an explicit `snapshotsPruned` marker on `EditToolDetails` /
`EditToolPerFileResult`, set by `pruneSnapshot` whenever it strips a
payload. `executeSinglePathEntries` tracks the flag across child
results and suppresses aggregate `oldText`/`newText` (re-stamping the
marker on the aggregate) the moment any child was pruned;
`executeApplyPatchPerFile` propagates the flag onto each per-file entry.

Regression test exercises the exact scenario the reviewer raised on
#3787: replace mode where entry 1 collapses a >1 MB file to a single
line (pruned) and entry 2 trivially renames the now-tiny result; the
aggregate result now carries `snapshotsPruned: true` with both
snapshot fields omitted.
2026-06-29 05:22:18 +00:00
roboomp 9e4e0f6691 fix(coding-agent): bounded edit-tool oldText/newText snapshots in tool-result details
Edit-tool results carried the full pre/post file content in
`details.oldText` / `details.newText`. For large files this bloated each
per-turn JSONL line by hundreds of KB even though the snapshots are
never sent to the LLM (provider serializers send only `content`) and
only consumed by the ACP event mapper for diff visualization.

Add `pruneOversizedEditSnapshots` and apply it at every site that
constructs an `EditToolDetails` / `EditToolPerFileResult`:
`executePatchSingle`, `executeReplaceSingle`, hashline `renderSection`
(delete + update branches), and both aggregators in `edit/index.ts`.
When combined `oldText` + `newText` exceeds 32 KB the helper returns a
shallow copy with both fields omitted; smaller edits pass through
unchanged. The diff, path, firstChangedLine, op, move, and diagnostics
fields are preserved, and ACP returns no diff content for over-budget
files (the text content still flows — graceful degradation).

Fixes #3786
2026-06-29 05:12:15 +00:00
can1357 68285aa9d5 fix(coding-agent): throttled tui tool argument parsing and updates
- Optimized TUI tool argument previews by throttling JSON re-parsing to prevent frame starvation during high-frequency streaming.
- Suppressed redundant component updates for unchanged parsed fields while maintaining raw preview integrity for bash and patch renderers.
- Added adaptive parsing logic to `ToolArgsRevealController` that distinguishes between renderers requiring continuous raw JSON streams and those consuming parsed arguments.
- Updated `EventController` to dynamically determine exposure requirements based on tool type and wire-format metadata.
2026-06-29 07:11:18 +02:00
can1357 2a53caccd4 Merge remote-tracking branch 'origin/farm/3f9fc9ab/llama-cpp-output-limit' 2026-06-29 06:54:15 +02:00
can1357 2fad95b5cf test(bench): validated service tier resolution for benchmark commands
- Added test suite to validate service tier resolution logic in benchmark commands.
- Verified that command-line flags correctly override application setting values.
- Confirmed default behavior when neither flags nor configuration settings are provided.
2026-06-29 06:51:13 +02:00
can1357 51ce5a87f9 feat(prompt): standardized tool instruction and communication flow
- Optimized instruction sets for core agent tools including task, lsp, job, and irc.
- Standardized tool documentation structure by replacing parameter listings with structural instruction blocks.
- Mandated new communication and technical workflows for subagent results, symbol-aware code intelligence, and background task management.
- Refined messaging and coordination guidelines to prioritize inter-agent communication and direct operations.
2026-06-29 06:51:13 +02:00
can1357 c8c24b0888 feat(bench): enabled concurrent execution and service tier selection
- Added --par flag to execute benchmark runs concurrently with a default degree of 4.
- Added --service-tier flag to allow overriding the provider service tier per benchmark.
- Increased default benchmark run count from 1 to 10 to provide more robust averaging.
- Updated benchmarking logic to process requests in a concurrency-limited pool while preserving output order.
- Implemented pre-flight credential checks to prevent unnecessary worker spawning when authentication is missing.
2026-06-29 06:51:13 +02:00
Mathews-Tom ac16eff49b Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names
# Conflicts:
#	packages/coding-agent/test/agent-session-snapcompact-auto-fallback.test.ts
2026-06-29 10:00:29 +05:30
roboomp a2f8b3915e fix(providers): treated positive llama.cpp props defaults as per-request
llama.cpp /props.default_generation_settings.params.{max_tokens,n_predict} are per-request defaults the server applies when a client omits the field, not a hard model cap. Only the -1 unlimited sentinel is promoted to the runtime context window now; positive values fall back to the discovery default so client-side per-request overrides remain unconstrained.

Fixes #3781
2026-06-29 04:10:54 +00:00
roboomp 00a41749e4 fix(providers): clamped llama.cpp refreshed output cap
Resolved selected-model refresh maxTokens against the effective context window, including live contextWindow overrides, so unlimited llama.cpp caps cannot exceed the configured context.

Fixes #3781
2026-06-29 04:03:56 +00:00