Commit Graph
6635 Commits
Author SHA1 Message Date
Wolfgang Schoenberger 26e422a00a fix(coding-agent): suppress WIP advisor non-blockers 2026-07-30 15:18:06 -07:00
can1357 4c1793b9b7 fix(security): hardened cloud import attribution and comparison honesty
- Failed closed when cloud pulls could not verify the project origin.
- Re-verified configuration attribution on every cloud finding detail.
- Rejected non-repository-relative Codex bundle locations.
- Refused lineage comparisons against incomplete after-scans.
- Preserved diff and working-tree targets when adding path scopes.
- Logged post-publication output failures and recovered persisted status.
- Used Bun.SHA256 directly and reused pi-ai JWT decoding.
- Shortened exported paths in interactive output.
2026-07-30 17:24:07 +02:00
can1357 ab572106cd Merge PR #7048: feat(security): add OMP-native security scan subsystem (@kmccleary3301) 2026-07-30 17:11:06 +02:00
can1357 3803219716 Merge PR #7095: fix(coding-agent): add createEditTool/createWriteTool to legacy pi shim (@roboomp) 2026-07-30 17:05:16 +02:00
can1357 fe33685f55 Merge PR #7090: fix(coding-agent): honor remote llama.cpp/ollama discovery base urls (@roboomp) 2026-07-30 17:05:15 +02:00
roboomp 766ccbf24a fix(coding-agent): add createEditTool/createWriteTool to legacy pi shim
The legacy @oh-my-pi/pi-coding-agent shim exported the read/bash/grep/find/ls
tool factories but omitted the edit and write ones. pi extensions importing
createEditTool or createWriteTool (e.g. gentle-pi) failed Bun's static export
check during extension validation, blocking omp install.

Added createEditTool/createEditToolDefinition and createWriteTool/
createWriteToolDefinition, mirroring the upstream pi surface and the existing
sibling factories. The unsupported operations seam throws a descriptive error
like createGrepTool does.

Fixes #7094
2026-07-30 14:36:10 +00:00
can1357 14dc5d4fcc fix(coding-agent/eval): bypassed environment proxies for python bridge calls
- Configure the python eval prelude to use a custom urllib opener that ignores environment proxies.
- Add test coverage verifying parallel tool bridge calls succeed when proxy variables are set.
2026-07-30 16:19:48 +02:00
roboomp fad7e97d53 fix(catalog): scoped Ollama model caches by endpoint
Ollama's online-if-uncached path keyed every endpoint under the same
provider namespace. Changing OLLAMA_BASE_URL or OLLAMA_HOST therefore
reused fresh models routed to the previous endpoint until cache expiry.

Centralize an endpoint-normalized Ollama cache namespace and apply it to
both configured coding-agent discovery and the catalog model manager.
Add coverage proving a default refresh discovers the new endpoint even
while the previous endpoint has a fresh row.

Fixes #7087
2026-07-30 13:31:08 +00:00
roboomp ec2caea840 fix(coding-agent): honor remote llama.cpp/ollama discovery base urls
llama.cpp and Ollama model discovery probed /models and /props with a
250ms timeout tuned for a loopback server. That cap also applied to a
host reached over the network, so a remote or LAN LLAMA_CPP_BASE_URL
(or OLLAMA_BASE_URL/OLLAMA_HOST) with normal round-trip latency timed
out, discovery returned no models, and the picker fell back to stale
127.0.0.1:8080 entries.

Select the probe timeout by host: strictly-loopback base URLs keep the
fast fail so a busy or foreign service on the default port never stalls
startup; every non-loopback host gets a generous discovery budget.

Fixes #7087
2026-07-30 13:19:41 +00:00
Kyle McCleary 4337797565 Merge remote-tracking branch 'origin/main' into feat/security-native
# Conflicts:
#	packages/coding-agent/src/tools/index.ts
2026-07-29 23:26:22 -07:00
Kyle McCleary 0b968bbb49 feat(security): integrate Codex Security cloud scans 2026-07-29 23:24:26 -07:00
can1357 38ebd30337 chore: update stale tests 2026-07-30 07:49:43 +02:00
can1357 e05f229f43 refactor: standardized editing syntax by removing copy and delete operations
- Removed copy and delete operations across tokenizer, parser, grammar, and clipboard logic.
- Standardized line-editing operations and block resolvers to use cut exclusively.
- Updated documentation, prompts, and test suites to reflect the removal of copy and delete syntax.
2026-07-30 07:42:48 +02:00
can1357 9aada058ee feat(hashline): implemented clipboard operations in hashline engine
- Implemented clipboard register management, parsing, and execution rules for CUT, COPY, and PASTE operations in the hashline engine.
- Added session-persistent clipboard state and integration across agent session execution, diff previews, and streaming tools.
- Added comprehensive validation, error messages, recovery handling, and test coverage for clipboard and block operations.
2026-07-30 07:21:43 +02:00
can1357 6b4efa896f feat(coding-agent): implemented oauth credential pin persistence and seeding
- Added hashing utilities and session entry definitions for OAuth credential pins.
- Added session manager methods to append and retrieve credential pins with backdated timestamp support.
- Added credential pin recording after assistant turns and seeding during session restoration.
- Added comprehensive unit tests covering credential pin recording, persistence, and seeding.
2026-07-30 07:21:08 +02:00
Kyle McCleary dba303e2e0 Merge remote-tracking branch 'origin/main' into feat/security-native 2026-07-29 20:31:08 -07:00
Kyle McCleary 13ed773855 fix(coding-agent): correlate producer-neutral findings 2026-07-29 20:30:54 -07:00
Kyle McCleary d90e54fb09 fix(coding-agent): harden native security workflow 2026-07-29 20:05:57 -07:00
can1357 ccd3bb9565 chore: reformat 2026-07-30 04:25:32 +02:00
can1357 2905a23fc1 fix(coding-agent): prevented duplicate rows in task execution scrollback
- Updated task tool execution to pin live regions and drop partial snapshots once rows commit.
- Tracked background task frozen styled rows and render timestamps to prevent clock drift on committed history.
- Added tests verifying detached and blocking task progress do not duplicate rows in scrollback.
2026-07-30 04:01:06 +02:00
Kyle McCleary 9314e200fe fix(security): harden scan runtime boundaries 2026-07-29 18:47:51 -07:00
Kyle McCleary 80bdfdcbd4 fix(security): stabilize imported finding identities 2026-07-29 18:47:51 -07:00
Kyle McCleary b708b39915 fix(security): harden native scan contracts 2026-07-29 18:47:51 -07:00
Kyle McCleary 089a9963f8 feat(security): OMP-native security subsystem (planner handoff) 2026-07-29 18:47:51 -07:00
can1357 92014ab605 fix: align merged branches with current type contracts 2026-07-30 02:01:03 +02:00
can1357 1b25ff01a2 style: apply biome formatting to merged changes 2026-07-30 02:01:03 +02:00
can1357 c9a5605b5b fix(advisor): degraded reasoning on provider refusals
(cherry picked from commit 776f244d810ac152eb0bd130b36c8474201d0b85)
2026-07-30 02:01:02 +02:00
can1357 7ccbe51b2d fix(session): preserved Codex commentary on empty stops
(cherry picked from commit 0b4887a4098e6296ac72ea2837db22be18dc9894)
2026-07-30 02:01:02 +02:00
can1357 43e5df012e Merge PR #6791: feat(ai): handle Cursor's modern exec wire protocol (@quantmind-br) 2026-07-30 01:48:52 +02:00
can1357 0728a55b8a Merge PR #6731: fix: preserve provider-native compaction semantics (@usr-bin-roygbiv) 2026-07-30 01:48:51 +02:00
can1357 020af06099 Merge PR #6535: feat(mcp): expose server-initiated notifications to extensions via mcp_notification event (@asteriskSF) 2026-07-30 01:48:51 +02:00
can1357 c9c890c49a Merge PR #6858: feat: add opt-in Codex reset fireworks (@joshrzemien) 2026-07-30 01:48:51 +02:00
can1357 2395848f7c Merge PR #6857: feat(coding-agent): add startup changelog display modes (@wolfiesch) 2026-07-30 01:48:51 +02:00
can1357 70e6d2c7dc Merge PR #6680: feat(coding-agent): add opt-in max ceiling for auto thinking (@everton-dgn) 2026-07-30 01:48:51 +02:00
can1357 31e7e19aa3 test(cursor): updated extension runner fixture 2026-07-30 01:47:13 +02:00
can1357 28b33dd858 test(compaction): aligned provider isolation assertion 2026-07-30 01:45:03 +02:00
can1357 65ef740003 fix(coding-agent): preserved Codex quota identity 2026-07-30 01:43:54 +02:00
Diogo Soares Rodriguesandcan1357 be5292bffd fix(coding-agent): gave the primary Cursor bridge the session's live cwd
The bridge is constructed once, at session creation, and was handed the
startup `cwd` by value. The session's own cwd moves under it — `/cd`,
resume, branch restore all call `sessionManager.moveTo` — and the two
frames that confine a path themselves (the native `delete`, and a
`read_mcp_resource` carrying `download_path`) resolve against whichever cwd
the bridge holds. So after a move the primary deleted or overwrote the
relative path in the workspace the session had left, and reported success
for the path the server actually named.

The advisor bridge already passed a live resolver; this is the same
resolver on the path that was missed. Locked by a wiring test: the seam is
the session handing its handlers to the provider, so the test captures them
there, moves the session, and asserts the frame acts on the new workspace
and leaves the old file alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014oA3H7aHUL85ydp9PJ3ryF
(cherry picked from commit 079c7ac61104d017eecbf781aa1c58eebd39b0b1)
2026-07-30 01:43:28 +02:00
Diogo Soares Rodriguesandcan1357 7f97581d0a fix(ai,coding-agent): closed two ways an exec answer misdescribed its own work
A `download_path` naming a FIFO hung the turn outright. The target is
opened write-only, which on POSIX blocks until a reader attaches, so the
`isFile()` refusal sitting behind that open was unreachable — the open
never returned. The path comes from the server, so this needed no planted
file to reach, only a named pipe where a download was aimed. Opening
non-blocking turns a readerless pipe into an immediate refusal and leaves
the existing guard to reject one that has a reader; the flag is inert on
regular files, which is every legitimate target. (The repo already fixed
this shape once, for discovery context-file reads, by stat-gating; the
flag closes the same hole without the stat's TOCTOU window.)

A `pi_grep` that hit the native backend's own match ceiling answered as an
unqualified success. `GrepTool` folds that cap into the flat
`details.truncated` and sets neither `details.truncation` nor
`perFileLimitReached` — the two fields the Pi result reads — so the one
truncation a caller can neither detect nor page around was the one it was
never told about. The flat flag now translates into a `PiTruncation`, and
only once the specific counters came back empty, so a cap that already
reported itself is never restated.

Both regressions are locked: the FIFO test detects a relapse by timing out
rather than by a failed assertion, since a relapse never reaches the
assertion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014oA3H7aHUL85ydp9PJ3ryF
(cherry picked from commit 20438ff68cf9c8aaaec30703f5b9972c7bda205e)
2026-07-30 01:43:28 +02:00
Diogo Soares Rodriguesandcan1357 53408d0412 test(coding-agent): pinned the advisor approval-gate test to a resolvable model
`runs advisor tools through the approval gate` built its advisor from the
`advisor` role chain, which resolves against `modelRegistry.getAvailable()`
— the models the host holds auth for. On a developer box whose environment
carries provider keys the roster resolved and the test passed; in CI, where
the suite's isolated auth storage is empty, every advisor resolved to
`no_model` and `getAdvisorAgent()` returned undefined ("expected an advisor
agent").

The advisor now names `gpt-4o-mini` outright and runs inside the file's
`withProviderAuth` helper, so the roster resolves from the granted key
rather than from whatever the machine happens to have configured.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014oA3H7aHUL85ydp9PJ3ryF
(cherry picked from commit ef2054da5dbe3d3d1cca4025e12e5c350f47173d)
2026-07-30 01:43:27 +02:00
Diogo Soares Rodriguesandcan1357 f6f2bab02e fix(cursor): mirror executed pagination in synthesized calls, resolve approval probes from policy
Forwarding the legacy read/grep frames' range and page fixed only the
execution: the transcript block was built from a second translation and
still showed a bare path and an unskipped search. That block is what a
reloaded session replays, so a slice read as the whole file and a later
window presented as page one. Both now come from the shared helpers,
`limit: 0` included -- recorded as the zero lines it returns.

The approval probe answered `approved` unconditionally, which laundered a
configured `deny` into a server-side blessing. It now resolves through a
bridge preflight against the same policy the wrapper applies at execution
time: approved only for a definite allow, refused for a deny, for a mode
demanding a prompt this frame cannot raise, and for an unknown tool.
Still never executes.

Comments and changelog no longer assert server-side semantics for
`range_applied`/`offset_applied`; they describe what the client did,
which is all the proto establishes.

(cherry picked from commit 5ac1870f6d67bf365c84b1affae63c89de32d1cb)
2026-07-30 01:43:06 +02:00
Diogo Soares Rodriguesandcan1357 4a946ad8c0 fix(cursor): gate advisor tools, echo grep offset_applied
Advisor tools are built straight from the builtin table, outside the
loop that wraps every registry tool in `ExtensionToolWrapper` - which is
where the approval mode, per-tool `tools.approval.<tool>` policies and
`autoApprove` are enforced. Both the advisor's own agent loop and its
Cursor exec bridge (`pi_write`, `pi_bash`) run those instances directly,
so an advisor granted `write` or `bash` executed them regardless of a
configured `ask` or `deny`. Verified before the fix: a raw `write`
instance created the file under `tools.approval.write: deny`; the
wrapped one refuses. `bridgeToolMap` and the grep factory only ever
wrapped the two tools they build themselves.

The grep answer also now echoes `offset_applied`. Forwarding the offset
without acknowledging it leaves the server unable to distinguish a
honored page from a client that ignored the field, so it re-paginates
from the same place. Set on all three result variants (files, count,
content); absent when the frame requested no offset.

(cherry picked from commit 13c2ed565f30ff86e31c8dc9896f940faf3aa088)
2026-07-30 01:43:06 +02:00
Diogo Soares Rodriguesandcan1357 4414ee4b0d fix(cursor): honor legacy read range and grep offset
Modern Cursor builds paginate the legacy `read` and `grep` frames with
fields this branch modeled in the proto but never wired.

`read` composed no range, so every page returned the whole file (or its
own truncation) and a model walking a large file never advanced past the
first window. It now goes through `piReadPath`, the same helper the Pi
frame uses, so both translate a range identically - including the
`limit: 0` case, which asks for zero lines and has no selector. The
answer reports `range_applied`, left false for an unranged read since
that is precisely the server's "this is the whole file".

`grep` dropped its `offset`. The local tool paginates by file through
`skip` and advertises exactly that unit in its own "use skip=N" advice,
so an unforwarded offset re-ran the identical search and answered page
one forever. A present `0` stays unset: it means "start at the
beginning", which is the un-skipped search.

(cherry picked from commit 4f647d86b6e4a507d57fb4d247f19db8240e51cf)
2026-07-30 01:43:06 +02:00
Diogo Soares Rodriguesandcan1357 d9bc1e80b6 fix(cursor): handle the resource-read refusal variant, unblock lint
`ReadMcpResourceExecResult` has a `rejected` variant carrying `reason`,
not `error`, so the pairing text's collapsed error branch did not
typecheck against the full union. Each variant is now switched
explicitly; the refusal is unreachable today (the handler answers
content or `null`) but a collapsed default would have read `undefined`
if the client ever builds one.

`bun check` type-checks the workspace projects; the union error only
surfaced through `ci:check:full`, which is what CI runs.

Also renames a loop variable that shadowed the global `escape`, which
was failing `biome check` on the full tree.

(cherry picked from commit f5dca418d91983a14492f51f2873514781a9e066)
2026-07-30 01:43:06 +02:00
Diogo Soares Rodriguesandcan1357 6254b6e81b fix(cursor): build the pi_edit bridge independently of the session's provider
Every native `pi_edit` failed after a session switched onto Cursor. The
replace-mode `edit` instance the frame needs was built only for sessions
CREATED on Cursor, and the tool roster is built once, at creation - a
session that started elsewhere kept its configured-mode `edit` in the
registry, which `executeTool` resolves before its fallback, so the
frame's `old_text`/`new_text` pairs failed validation against a
`hashline` schema.

The instance is now built from the `edit` grant regardless of the
initial provider, lazily so a session that never reaches Cursor never
constructs one, and `pi_edit` asks for it through a dedicated
`getEditReplaceTool` accessor rather than relying on Cursor sessions
having deleted `edit` from the registry. A session that was never
granted `edit` is still refused.

That accessor also closes an escalation the previous wiring opened up.
The session's device resolver is handed to the bridge as `getTool` and
installed as the agent loop's `resolveFallbackTool`, which runs for ANY
call outside the advertised set - so serving `edit` from it let a
hallucinated call, or one naming a tool the session deselected after
startup, execute a replace-mode edit the model was never offered. It is
device-only again.

Regressions cover both directions at the SDK level, driving a real
unadvertised `edit` through the loop and asserting the surfaced
`Tool edit not found`: an unchanged file alone would also pass if the
fallback had resolved the tool and the edit then failed validation.

(cherry picked from commit 11a28dcf7b995a9e94913269733b3199d6f4790d)
2026-07-30 01:43:02 +02:00
usr-bin-roygbivandcan1357 64234e05c9 fix: align manual native compaction fallback
(cherry picked from commit 2d5397a52f6feaeee4136fe4e7d8271309043b75)
2026-07-30 01:42:53 +02:00
usr-bin-roygbivandcan1357 9dd8d3c6ce fix: preserve native compaction failures
(cherry picked from commit d13e9f30a06cad347226d2fa377cab8c086debc3)
2026-07-30 01:42:53 +02:00
usr-bin-roygbivandcan1357 7fff8869a0 fix: skip unauthenticated compaction candidates
(cherry picked from commit fa5f7d73ec1f169f9b9952648195057caa24657e)
2026-07-30 01:42:53 +02:00
usr-bin-roygbivandcan1357 4d3f2e32b3 fix(compaction): preserve native timeout boundaries
(cherry picked from commit 2a5950036f6c671004f2ddf1d2054a481a53cfe8)
2026-07-30 01:42:34 +02:00
usr-bin-roygbivandcan1357 d084697fae fix(compaction): retry transient native failures
(cherry picked from commit 293c96dfa479de13995d581caec33b3c90b5b3ca)
2026-07-30 01:42:33 +02:00