Commit Graph
10871 Commits
Author SHA1 Message Date
Diogo Soares Rodrigues cc210094ef fix(cursor): refuse todo dependency graphs and sanitize failure text
Two review findings on the native todo sync.

- TodoItem.dependencies is a graph the local model cannot store: rows
  are keyed by content, carry no id, and hold no edges. An imported
  dependent row files as plain pending and nextActionableTask then
  offers work the server considers blocked. Refuse snapshots with an
  edge pointing at an unfinished row; edges whose blockers already
  finished constrain nothing and still mirror.

- The todo failure warning interpolated the provider error verbatim.
  Collapse and truncate it at the render boundary.

Also documents two known, unfixed defects: an async cursorOnToolResult
transformer resolving after the buffer drain, and the todo card
lifecycle race. Emitting a synthetic tool_execution_start for the
latter was measured and rejected -- the completion deletes the entry it
creates, so the late streamed block adds a second card.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues 0ab0aa6331 fix(cursor): refuse empty read_todos and say when a snapshot is not mirrored
An empty `read_todos` with `total_count=0` (proto3 unset or genuinely
empty) was accepted and mirrored as an authoritative wipe. Refuse empty
reads; clearing the list stays on `update_todos`.

Benign refusal text is now "Todo snapshot not mirrored" instead of
"No todo changes", which falsely described a server-accepted update that
only the local mirror declined.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues 3f2b45662e docs(cursor): list the unrepresentable snapshot among benign refusals
`CursorTodoSyncHandler`, `buildTodoToolResult`, `extractTodoError`, and
the host `todoSync` each enumerate why a snapshot may be `null`. All
four listed only filtered and truncated reads, so a duplicate-content
refusal read as undocumented -- easy to mistake for an error, or to
"fix" by mirroring it again.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues 0639246d27 fix(cursor): settle refused and failed native todo calls
Only a successful snapshot settled a native todo block. A `read_todos`
narrowed by a filter and a server `UpdateTodosError` both went
unanswered: no `tool_execution_end`, so the card animated forever, and
no `toolResult`, so `buildSessionContext` stripped the block on rebuild.

Every completed native todo call now settles. The refusal path carries
no `details.phases` -- `event-controller` feeds that straight into
`setTodos`, so echoing the current list back would let a call that
changed nothing overwrite live panel state. A server error is carried
through as a failed result instead of collapsing into the benign no-op.

Each regression is covered by a test verified to fail without its fix.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues c67a99f02f test(cursor): assert the replayed todo result through the real renderer
The replay test inspected `details.phases` directly and claimed renderer
coverage it did not have. It now calls `todoToolRenderer.renderResult`
and asserts on the rendered text.

Dropping `details.phases` from the persisted result makes it print
"Todo 0 tasks" above the summary line -- the exact regression the test
is meant to catch, and one the previous field assertion described but
never exercised.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues ea023c380a fix(cursor): persist the phase-bearing todo result and close a buffer race
The previous commit paired every server-resolved todo block with a
result, but built that result in the provider from the flat snapshot.
`todoToolRenderer.renderResult` reconstructs the list exclusively from
`details.phases`, so the block survived the dangling-strip only to replay
as `Todo 0 tasks`.

Only the host computes that grouping -- the provider sees a flat list --
so `todoSync` now returns the result it already assembled and the
provider persists it verbatim. A refused snapshot never reaches the host,
so the provider's summary-only fallback still covers that path, and
exactly one result is emitted either way.

Separately, `Agent`'s Cursor buffering wrapper pushed its entry only
after awaiting the optional `cursorOnToolResult` transformer. The
provider dispatches decoded messages with `void handleServerMessage(...)`,
so a `message_end` from the same chunk could drain the buffer while a
transformer was still pending, dropping the result. The entry is now
reserved synchronously and patched in place when the transformer
resolves, keeping buffer order and still applying the customization.
Production is unaffected -- `sdk.ts` sets no transformer -- but the
option is supported and its contract returns a Promise.

Tests: a delayed-transformer case that loses the result without the
buffering change, and a replay case driving the persisted result through
`buildSessionContext` and asserting `details.phases` rebuilds a non-empty
list -- the id-pair assertion alone did not catch the empty render.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues 29e64ce608 fix(cursor): resolve and persist server-owned todo blocks
Review follow-up on two defects in the native todo bridge.

`tool_execution_end` was emitted under a freshly generated UUID, but the
interactive transcript files the visible block under the streamed
`callId` and only clears it when the ids match. The card therefore stayed
pending and animating for the rest of the session. The settled call id is
now passed to `todoSync`, making the parameter required so no caller can
silently reintroduce a mismatch.

Nothing produced a `toolResult` for these blocks either: `todoSync` only
appended a custom entry and emitted a transient event. Since
`buildSessionContext` strips any `toolCall` with no matching result, the
interaction vanished from every rebuilt transcript -- reload, branch
switch, or Ctrl+L -- leaving a "tool call elided" placeholder. A paired
result now travels the same `onToolResult` channel the other
server-resolved Cursor calls already use, including when the snapshot is
refused: the call happened, it just changed no local state.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues 7214951ead fix(cursor): sync native todo list from server-resolved tool calls
Cursor resolves its native `update_todos`/`read_todos` tools server-side,
so the todo list never followed the model's intent locally.

Two defects, both silent:

- `agent.v1.ToolCall` is a protobuf oneof. A decoded message exposes the
  selected variant as `tool: { case, value }` and has no flattened
  `updateTodosToolCall` property, so the bridge recognized no native todo
  call at all on the wire path.
- The synthesized `todo` block was emitted as locally runnable carrying a
  `{todos}` payload the local tool's schema rejects, turning every update
  into a validation error and driving a spurious continuation turn.

Todo calls are now read through the oneof, both native blocks are stamped
resolved, and local state is mirrored only from the server's confirmed
success snapshot. Partial `read_todos` responses -- narrowed by
`status_filter`/`id_filter`, or short of the server's own `total_count` --
are subsets, not the list, and are refused rather than deleting the tasks
they omit. `TODO_STATUS_CANCELLED` maps to `abandoned` instead of
reverting the task to `pending`.

The exec bridge mirrors each snapshot into session state, refreshes the
interactive panel via a synthetic `tool_execution_end`, and persists to
the session branch so the list survives reloads, rewinds, compaction, and
session switches. Existing phase grouping is preserved.

Regression tests drive the bridge with wire-encoded protobuf, which is
the only shape production ever sees; all six fail without this change.
2026-07-26 09:29:13 -03:00
can1357 667111575e feat: implemented credential lifecycle tracking and management APIs
- Added `listDisabledCredentials` and `refreshSnapshot` methods to credential stores along with API endpoints and wire schemas.
- Added `authorizedAt` timestamps and Anthropic OAuth grant TTL constants to track credential lifecycles.
- Updated the usage CLI to render auto-disabled credential tombstones and grant expiration warnings.
- Added comprehensive unit and broker integration tests covering the new credential management features.
2026-07-25 18:02:43 +02:00
can1357 0491f2961a chore: bump version to 17.1.3 2026-07-25 01:10:32 +02:00
can1357 bef97a69bb Merge PR #6529: fix(coding-agent): guard retain renderer streaming args (@roboomp) 2026-07-25 00:59:14 +02:00
can1357 8851e93d21 Merge PR #6551: fix(coding-agent): use session settings in file guards (@roboomp) 2026-07-25 00:59:14 +02:00
roboomp 144043ad48 fix(coding-agent): used session settings in file guards
Passed session-scoped settings through Edit and Write generated-file checks and fell back to schema defaults when no global singleton exists.

Guarded inline image sizing against an uninitialized global settings proxy and added isolated-session regression coverage.

Fixes #6549
2026-07-24 22:42:38 +00:00
can1357 f23bc266a8 feat(natives): enabled per-language rewrite rules for mixed-language paths
- Remove uniform language inference requirement, allowing mixed-language paths to rewrite each file in its own language.
- Update `ast_edit_blocking` in `crates/pi-natives/src/ast.rs` to compile rewrite rules per language and skip unsupported languages gracefully.
- Update `ast-edit.md` prompt documentation to reflect mixed-language path support.
- Add test coverage verifying mixed-language tree rewrites.
2026-07-24 21:52:29 +02:00
can1357 a569385b8e fix(shell): captured find -exec child stdio into scope streams
- find -exec/-execdir children inherited the omp process's real
  stdout/stderr, spamming output into the TUI terminal and bypassing
  shell redirects; they also inherited the host env instead of the
  shell's exported environment.
- Added pi_uutils_ctx::run_captured (moved from uu-xargs' private
  helper): stdin null, stdout streamed into scope stdout, stderr
  drained on a helper thread and forwarded after exit.
- uu-find exec matchers now use env_clear + env_snapshot and
  run_captured; MultiExecMatcher rebuilds a std Command from the
  argmax command's accumulated state (argmax only Derefs immutably).
- uu-xargs reuses the shared helper; added pi-shell regression test
  asserting -exec child stdout flows through the shell redirect with
  the exported env.
2026-07-24 20:06:29 +02:00
roboomp d7c7ca033d fix(coding-agent): guarded retain renderer streaming args
- Treated transient non-array retain items as absent during TUI streaming.
- Added regression coverage for malformed partial renderer arguments.
- Documented the fix in the coding-agent changelog.

Fixes #6528
2026-07-24 15:52:01 +00:00
can1357 a38cd95d7d chore: bump version to 17.1.2
- fixed eval preview windowing fixture to use valid identifiers so the display formatter's operator spacing does not rewrite the asserted lines
2026-07-24 17:23:19 +02:00
can1357 7ebf141743 chore: bump version to 17.1.2
- fixed rustfmt drift and clippy errors in pi-shell moreutils builtins (combine, errno, ifne, isutf8, sponge, ts) that blocked the release check gate
2026-07-24 16:53:52 +02:00
can1357 c55b28a26d chore(coding-agent): format eval display helpers 2026-07-24 16:49:31 +02:00
can1357 3c80e6f9cd fix(coding-agent): expose live tool rebuild options 2026-07-24 16:29:27 +02:00
can1357 e0509d5d62 fix(coding-agent): preserve bench catalog-first resolution 2026-07-24 16:26:59 +02:00
can1357 68e76c6243 fix(coding-agent): preserve shared live tools across rebuilds 2026-07-24 16:26:59 +02:00
can1357 b0f1b5c0c5 Merge PR #6496: fix(ai): preserve Anthropic server-tool history (@roboomp) 2026-07-24 16:26:52 +02:00
can1357 457d735475 Merge PR #6509: fix(coding-agent): honor modelRoles.default over cursor/default catalog id (@roboomp) 2026-07-24 16:26:48 +02:00
can1357 2bc26d3d4c Merge PR #6519: fix(coding-agent): avoid duplicate tools in transcript rebuilds (@roboomp) 2026-07-24 16:26:42 +02:00
can1357 ff49b986d5 feat(coding-agent/tools): introduced language-specific code formatters for display rendering
- Added language-specific code formatters for JavaScript, Julia, Python, and Ruby to improve display rendering.
- Integrated display formatting into browser run and eval render tools while preserving verbatim execution.
- Added comprehensive test suites verifying formatting stability, lexical safety, and streaming behavior.
2026-07-24 16:26:03 +02:00
can1357 5acdefc7b3 feat(coding-agent/web): introduced structured web-search query parsing module
- Implemented a structured web-search query parsing module supporting directives, tokenization, date parsing, and syntax serialization.
- Updated search providers to map query directives and date bounds to native provider parameters and filters.
- Added lenient result constraint post-filtering and configuration settings for enhanced engine routing.
- Added comprehensive unit and integration tests covering query parsing, constraint filtering, and provider-specific request mapping.
2026-07-24 16:05:14 +02:00
roboomp 484fa319eb fix(coding-agent): keep running async task handles during rebuild dedup
The rebuild dedup dropped any preserved pendingTools component whose toolCallId
had a persisted toolResult. A background task's initial async.state=="running"
result is persisted while EventController#handleToolExecutionEnd deliberately
keeps its component in pendingTools so a later tool_execution_update/_end can
settle it. Dropping that still-live handle stranded those updates on the running
snapshot. Only terminal results are now owned by the replay; running async
handles stay preserved. Added a regression covering the running-task case.
2026-07-24 13:53:43 +00:00
can1357 db937bd149 feat(coding-agent): added coarse effort parameter to task tool
- Add `effort` (`lo`/`med`/`hi`) parameter to task spawn parameters and prompts.
- Implement `resolveTaskEffortLevel` to map coarse task effort onto model-supported thinking ranges.
- Pass effort configuration through executor options and structured subagent requests.
2026-07-24 15:51:34 +02:00
roboomp 759e551e8c fix(coding-agent): dropped resolved tools from mid-stream rebuild preservation
rebuildChatFromMessages preserves the live pendingTools components across its
clear+replay so streaming keeps routing into them. That preservation assumed
every pending-tool component was still dangling (its result outside
state.messages). Once a tool's result had landed in the session entries while
its component still lingered in pendingTools (a rebuild racing the
tool-completion event, or a background/displaceable snapshot), the replay
reconstructed the completed block from the persisted toolResult AND the
preserved live component was re-appended, so the same tool block rendered twice.

Resolved tool calls are now dropped from the preserved live set and owned by the
replay; only genuinely in-flight (dangling, replay-stripped) calls are preserved.

Fixes #6516
2026-07-24 13:40:57 +00:00
can1357 83b39454a1 Merge PR #6518: fix(launch): surface active daemons ahead of exited history in ps (@roboomp) 2026-07-24 15:39:32 +02:00
roboomp 677c35852d test(launch): exercised broker list contract through rpc
Replaced direct assertions on internal ordering and recovery helpers with an isolated broker integration test. The test seeds recovered terminal metadata, starts an active daemon, sends the authenticated list RPC, and asserts active-first ordering, true exit-time recency, the terminal cap, and protocol serialization/parsing.

Made the ordering and recovery helpers internal again because production wiring now supplies their coverage.

Fixes #6517
2026-07-24 13:35:00 +00:00
roboomp b05226e755 fix(launch): preserve real exit time on broker recovery
Recovery unconditionally restamped every non-detached record's exitedAt with the restart timestamp, including already-exited/failed ones, so after an idle-broker restart the list history cap could keep arbitrary directory-order entries and drop the genuinely most-recently-exited process.

Reap only records that were still alive at recovery; terminal records keep their real exitedAt/exitReason. Extract reapRecoveredSnapshot() and cover it with tests.

Fixes #6517
2026-07-24 13:30:52 +00:00
can1357 e7bb0556a8 feat(coding-agent/prompts): updated task prompt with concurrent edit instructions
- Added guidelines stating that concurrent edits to the same files are safe.
- Specified prerequisites for safe overlap including skipping validation and defining contracts up front.
2026-07-24 15:28:23 +02:00
roboomp f57f388c37 fix(launch): surface active daemons ahead of exited history in ps
The broker `list`/ps op sorted every daemon record by createdAt ascending and never pruned, so in a long-lived project the active (newest) daemon rendered behind all exited ones and the response grew without bound.

List non-terminal daemons first (oldest to newest) and cap exited/failed history at the 10 most recently exited; truncated records stay addressable by name via describe/logs/restart.

Fixes #6517
2026-07-24 13:22:09 +00:00
can1357 3676b5d97f feat: implemented client usage tracking and reporting in the auth broker
- Add usage history, reporting, and client summary endpoints to the auth broker.
- Implement SQLite persistence, batching, and periodic flushing for observed client usage.
- Integrate usage reporting into the coding agent session for completed assistant messages.
- Update stats aggregator and dashboard to retrieve usage history snapshots from the broker.
2026-07-24 15:20:46 +02:00
can1357 c6dcfa4137 feat(coding-agent): compacted oversized sse payloads in debug buffer
- Added tool schema and description compaction for oversized data payloads in `packages/coding-agent/src/debug/raw-sse-buffer.ts`.
- Implemented head-tail trimming to preserve leading and trailing event fields when events exceed character budgets.
- Added test coverage verifying SSE debug event truncation, elision markers, and JSON-safe tool compaction behavior.
2026-07-24 15:20:36 +02:00
can1357 27e019981a feat(coding-agent/tools): updated bash tool prompt to list available shell builtins
- Added available shell builtins list to the bash tool prompt template.
- Added helper to check if shell builtins are disabled via settings or environment.
2026-07-24 15:02:00 +02:00
can1357 5d4f1cf6b5 feat(pi-shell/moreutils): implemented six moreutils-inspired shell builtins
- Added six builtin commands: ts, sponge, ifne, isutf8, combine, and errno to pi-shell.
- Created moreutils module with independent implementations for all tools.
- Added jiff dependency for timestamp and timezone functionality.
- Integrated builtins into shell execution pipeline with in-process execution.
- Added integration tests verifying pipe chains like ts | sponge with isutf8.
2026-07-24 14:52:16 +02:00
can1357 9f8aa87dbf feat(task): removed per-call model override from task tool
- Removes `model` field from task item/schema, TaskParams, and TaskItem types.
- Removes model selector validation, formatting, and approval display logic.
- Updates task tool priority docs to reflect that model is no longer per-call overridable.
- Updates eval agent() helper docs and prompt templates to remove model parameter.
- Updates tests to reflect removal of model override capability.
2026-07-24 14:51:48 +02:00
roboomp 8191cf41d3 fix(coding-agent): used authenticated registry models by default
Required CLI model registries to expose getAvailable() and used that authenticated
set whenever callers omit availableModels. Deferred SDK and bench/dry-balance
resolution now lets configured roles beat unauthenticated catalog id collisions.

Updated resolver test registries and made the #6508 regression omit the explicit
availableModels option, covering the deferred-caller path from the review.

Fixes #6508
2026-07-24 11:41:58 +00:00
roboomp df0e77c584 fix(coding-agent): honor modelRoles.default over cursor/default catalog id
`resolveCliModel` ran findExactCliModel's unauthenticated catalog fallback
before configured-role resolution, so the bundled `cursor/default` model (bare
id `default`) shadowed a configured `modelRoles.default`. On machines without
Cursor credentials `--model default` failed with `No API key found for cursor`
instead of resolving the configured, authenticated default role.

Defer the catalog fallback: explicit provider/id references and authenticated
bare ids still win over roles, a configured role now beats an unauthenticated
catalog-only id, and the catalog id is still recovered via the trailing fuzzy
fallback when no role matches.

Fixes #6508
2026-07-24 11:30:51 +00:00
can1357 de00e7f136 feat(tui): renamed large-paste local refs to paste-N.md
- Large-paste menu now saves pastes as local://paste-N.md instead of
  local://attachment-N, giving the artifact a markdown extension and a
  clearer name.
2026-07-24 12:25:40 +02:00
can1357 c780662881 feat(agent): added resolveFallbackTool option for routing unadvertised tool calls
- Add `resolveFallbackTool` callback to `AgentOptions` and `AgentLoopConfig` that resolves tool calls not found in the advertised set.
- Use the callback as a third lookup step after `name` and `customWireName` match, enabling side transports like `xd://` device mounts.
- Add test coverage verifying the fallback resolves known devices and preserves "not found" errors for unknown names.
- Wire the coding agent's device registry as `resolveFallbackTool` in both `createAgentSession` and `streamAgentSession` paths.
2026-07-24 12:18:17 +02:00
can1357 fdf921a3c4 fix(coding-agent): marked ast_edit previews as staged proposals
- Prepended a model-visible PREVIEW_PENDING_NOTICE to ast_edit preview
  results; the TUI-only proposed badge never reached the model, so
  preview diffs read as already-applied edits.
- Rendered the resolve reminder with the source tool name via
  Handlebars instead of a generic 'This is a preview'.
- Documented the xd://resolve / xd://reject two-phase flow in the
  ast_edit tool prompt.
2026-07-24 12:03:49 +02:00
can1357 d4792ed38b fix(tools): leniently inferred missing todo op from unambiguous payloads
- Kept op required in the todo schema; lenientArgValidation now routes raw args to execute(), where resolveTodoParams re-validates and repairs an omitted op (list -> init, phase+items -> append, bare items on empty list -> init).
- Ambiguous op-less calls surface the schema error as a retryable tool error instead of a hard validation failure.
2026-07-24 12:03:06 +02:00
roboomp d868519149 fix(coding-agent): dropped Anthropic server-tool blocks from shares
Redacted assistant anthropicServerTool blocks alongside redactedThinking and providerPayload so /share never uploads raw server_tool_use input or web_search_tool_result encrypted_content.
2026-07-24 09:12:53 +00:00
roboomp 07fcec1e68 fix(ai): preserved Anthropic server-tool history
Persisted native server-tool calls and web-search results in assistant content, replayed them only to the issuing Anthropic provider, and retained Umans gateway filtering.

Fixes #6495
2026-07-24 08:49:43 +00:00
can1357 6ac5879858 feat(live): rendered visualizer across entire container width
- Removed max width cap of 120 columns in LiveVisualizer.

- Added unit test to verify full width rendering for wider viewports.
2026-07-24 09:28:42 +02:00
can1357 c36826cbac chore: bump version to 17.1.1 2026-07-24 09:18:41 +02:00