Commit Graph

9239 Commits

Author SHA1 Message Date
roboomp 922e7a58ef fix(coding-agent): re-export compact from legacy pi shim
Legacy pi extensions import `compact` from the `@earendil-works/pi-coding-agent`
package root (aliased to the legacy shim). It lives in
`@oh-my-pi/pi-agent-core/compaction` (same module as the already-bridged
`estimateTokens`) and the coding-agent barrel does not forward it, so the shim's
`export * from "../index"` left it off the surface and a named import failed
Bun's static export check during plugin validation
(`omp plugin install npm:pi-claude-bridge`).

`keyHint` (also named in the report) already resolves via the modes/components
barrel, so only `compact` needed bridging.

Fixes #7174
2026-07-31 12:07:44 +00: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 9856f904d7 feat(typescript-edit-benchmark): introduced empirical edit mutation planning
- Add new structural, multi-edit, and block-level mutation classes with updated category mappings.
- Introduce hunk extraction, placement, rendering, and solver utilities along with unit tests.
- Implement size-based mutation planning, prompt validation logic, and new prompt markdown templates.
- Update benchmark generation scripts and package configurations to support empirical edit shape statistics.
2026-07-30 07:45:01 +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 b9ae2a3f9b docs(hashline): condensed and clarified instructions in prompt documentation
- Condensed instructions and rule descriptions in `packages/hashline/src/prompt.md`.
- Streamlined formatting examples and anti-patterns for clarity.
- Clarified block operation boundaries and markdown heading section rules.
2026-07-30 07:21:44 +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
can1357 a6001c04a3 fix(coding-agent): prevented race condition in concurrent createAgentSession calls
- Export AgentRegistry from the SDK to allow passing a private registry instance.
- Provide a dedicated AgentRegistry per in-process client in the benchmark runner.
2026-07-30 06:03:32 +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 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 09545697ee fix(advisor): capture model identity lazily and drop duplicated release notes 2026-07-30 02:01:03 +02: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 27cb968359 Merge PR #7007: feat(tools): add a browser.cdpUrl setting for the default automation target (@terrxo) 2026-07-30 01:48:50 +02:00
can1357 34d7f2fb38 fix(cursor): reported full file size for ranged reads 2026-07-30 01:45:41 +02:00
can1357 65ef740003 fix(coding-agent): preserved Codex quota identity 2026-07-30 01:43:54 +02:00
Diogo Soares Rodrigues 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 Rodrigues 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 Rodrigues 5ab98cded8 fix(cursor): persist resource listings, wire advisor MCP resources, reject unavailable pi edit/write
Three remaining review findings:

- `list_mcp_resources` frames a handler answered now synthesize a
  `list_mcp_resources` block and pair a result derived from the same
  answer sent on the wire; the streamed `ListMcpResourcesToolCall` /
  `ReadMcpResourceToolCall` announcements join the exec-owned set so
  they cannot double-render. No-handler frames still synthesize
  nothing, since nothing ran.

- Advisors receive the same `MCPManager`-backed resource adapter as the
  primary bridge, so their `list_mcp_resources` no longer reports every
  server as empty and `read_mcp_resource` no longer answers `not_found`
  against live connections the advisor shares.

- An unavailable `pi_edit`/`pi_write` answers with the protocol's
  `rejected` variant instead of `error`: refusal and failure are
  separate oneof cases, and a denial reported as an execution error
  invites a retry of an operation that was never permitted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSWZTe6YA2PX1cqtukZvYi
(cherry picked from commit 47ce936c8df05d6970504af19e5ef7d2e8c38d7b)
2026-07-30 01:43:07 +02:00
Diogo Soares Rodrigues 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 Rodrigues 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 Rodrigues 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 Rodrigues 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-roygbiv 64234e05c9 fix: align manual native compaction fallback
(cherry picked from commit 2d5397a52f6feaeee4136fe4e7d8271309043b75)
2026-07-30 01:42:53 +02:00
usr-bin-roygbiv 9dd8d3c6ce fix: preserve native compaction failures
(cherry picked from commit d13e9f30a06cad347226d2fa377cab8c086debc3)
2026-07-30 01:42:53 +02:00
usr-bin-roygbiv 7fff8869a0 fix: skip unauthenticated compaction candidates
(cherry picked from commit fa5f7d73ec1f169f9b9952648195057caa24657e)
2026-07-30 01:42:53 +02:00
usr-bin-roygbiv 4d3f2e32b3 fix(compaction): preserve native timeout boundaries
(cherry picked from commit 2a5950036f6c671004f2ddf1d2054a481a53cfe8)
2026-07-30 01:42:34 +02:00