Commit Graph

99 Commits

Author SHA1 Message Date
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
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
usr-bin-roygbiv b9504f65e7 feat: add native Codex computer use 2026-07-24 01:40:04 +00:00
usr_bin_roygbiv 7c6d691c10 fix(agent): recover tools after stream parse errors 2026-07-20 17:22:25 -05:00
roboomp a713b941dc fix(agent): preserved side-effecting hub outcomes
Resolved tool interruptibility from each call's raw arguments so mixed-operation tools can keep side-effecting calls non-interruptible.

Restricted the unified hub to interrupt passive waits and followed logs while preserving start, send, and lifecycle operation results.

Fixes #5995
2026-07-18 14:41:19 +00:00
roboomp ed4ddcba6c fix(session): await session.dispose() on non-interactive exit paths
Print-mode assistant-error/aborted exit, RPC pi.shutdown() and stdin-EOF
shutdowns, and the extension command-context shutdown() called
process.exit() before (or racing) session.dispose(), skipping the bounded
browser reaper (releaseTabsForOwner) installed in dispose(). An OMP-owned
Chromium could survive the parent and reparent to PID 1.

Route all four graceful paths through the idempotent, promise-memoized
session.dispose() and await it before the final exit. The RPC
performShutdown no longer emits session_shutdown directly (dispose() emits
it), avoiding a double emit.

Fixes #5643
2026-07-16 04:29:55 +02:00
can1357 e28197c694 Revert "merged PR #5602: fix(agent-loop): reclassify empty toolUse stop as retryable error"
This reverts commit 2baaea8782, reversing
changes made to 6783c3a473.
2026-07-16 04:09:44 +02:00
can1357 1df790a5d2 Revert "fix(agent-loop): discard incomplete sibling tool calls"
This reverts commit 7a2e34988b.
2026-07-16 04:08:59 +02:00
can1357 2c355102ce chore: applied biome formatting to merged sources 2026-07-16 03:52:48 +02:00
can1357 7a2e34988b fix(agent-loop): discard incomplete sibling tool calls 2026-07-16 03:31:57 +02:00
roboomp 4200dec047 fix(agent-loop): strip incomplete tool calls on empty toolUse stop
A dropped stream that emitted toolcall_start/delta but never toolcall_end
leaves an incomplete toolCall block in content. The prior guard bailed on
any toolCall block, so the outer loop dispatched empty or partially
parsed arguments instead of retrying the transport failure.

Track streamed tool-call ids (toolcall_start/delta) alongside completed
ones (toolcall_end): a call streamed but never completed is incomplete.
reclassifyEmptyToolUseStop now reclassifies unless a usable (atomic or
completed) tool call remains, stripping incomplete blocks first. Atomic
deliveries (single done/end(result) message, e.g. Cursor) emit no
granular events and stay usable.

Fixes #5600
2026-07-15 18:06:13 +00:00
roboomp 94fc54859f fix(agent-loop): reclassify empty toolUse in result-only completion
Streams finalized via end(result) with no terminal done/error event fall
through to the trailing-result branch, which returned response.result()
unchanged. An empty toolUse turn completing that way stayed a silent
success and never retried. Apply the same
retainCompletedToolCalls/recoverTransientErrorToolTurn/
reclassifyEmptyToolUseStop chain to the trailing branch.

Fixes #5600
2026-07-15 17:52:25 +00:00
roboomp f64a17c529 fix(agent-loop): reclassified empty toolUse stop as retryable error
A provider stream that closes after the thinking block but before the
tool call JSON is emitted finalizes with stopReason=toolUse and zero
toolCall content blocks. The loop treated this as a successful turn:
dispatched no tools, rendered an empty tool widget, and never retried.

reclassifyEmptyToolUseStop stamps such a turn as stopReason=error with
the Transient classifier bit set explicitly, so AgentSession's standard
retry-with-backoff path fires regardless of message-text matching.

Fixes #5600
2026-07-15 17:44:53 +00:00
can1357 b58fa6e1d3 Merge PR #5513: fix(agent): keep completed tool results from false "skipped" placeholder (@roboomp) 2026-07-14 23:11:08 +02:00
roboomp b591f3d054 fix(agent): kept completed tool results from false skipped placeholder
The interrupt-clobber branch in executeToolCalls replaced a tool's real
result with the "Skipped due to queued user message" placeholder whenever
an interrupt fired, the tool's own signal aborted, and the result was an
error. It ignored whether tool.execute() actually completed, so steering
while a tool was in flight could discard a genuine error result (e.g. a
command exiting non-zero) that the tool had already produced.

Gate the clobber on !completedToolExecution so a tool that ran to
completion keeps its real result; only tools cut off before returning are
reported as skipped. Align the aborted telemetry status the same way.

Fixes #4752
2026-07-14 19:57:38 +00:00
roboomp 8e6d26b1e8 fix(eval): honored unlimited cell timeouts
- Disabled the eval watchdog when timeout is explicitly zero.
- Classified session deadline aborts as TimeoutError while preserving their message.
- Documented and tested both timeout contracts.

Fixes #5250
2026-07-14 17:33:56 +00:00
roboomp 74c63fa6c5 fix(agent): labeled system steering skips accurately
- Carried steering queue origin through mid-batch interrupt polling.
- Preserved queued-user skip wording while labeling advisor/system steering as system advisory skips.
- Added regression coverage for advisor steering skip wording.

Fixes #5074
2026-07-10 14:00:59 +00:00
can1357 17c7c6d0f8 fix(agent): preserve external abort boundaries 2026-07-10 12:37:46 +02:00
can1357 82f3706410 Merge remote-tracking branch 'origin/farm/6f26b11c/distinguish-synthetic-tool-failure' 2026-07-02 23:42:38 +02:00
roboomp 107503d201 test(agent-loop): align tool result details type with parameter shape 2026-07-02 21:27:32 +00:00
roboomp eb64e7e5d1 fix(agent-loop): skip cursor exec-resolved toolCall blocks to avoid double-execution
Codex review on PR #4351: synthesizing toolCall content blocks for
Cursor's exec-channel native tools made the shared agent loop treat the
finalized assistant message as a fresh runnable tool turn. Because
executeToolCalls filters message.content for any toolCall block on
stop/toolUse, bash/write/delete/etc. ran a second time after Cursor
already executed them server-side via the bridge, duplicating side
effects and appending conflicting toolResults.

- packages/ai/src/utils/block-symbols.ts: add `kCursorExecResolved`
  symbol and `CursorExecResolvedCarrier` carrier type. Symbol-keyed so
  the marker never leaks into JSONL; rebuild pairs blocks with toolResult
  messages by id.
- packages/ai/src/providers/cursor.ts: stamp the marker onto every
  block `synthesizeCursorExecToolCall` emits and extend `ToolCallState`.
- packages/agent/src/agent-loop.ts: filter marked blocks out of the
  runnable-toolCall extraction in both the main runnable path and the
  error/aborted placeholder path, plus defense-in-depth inside
  `executeToolCalls`. Marked blocks stay in `assistantMessage.content`
  for persistence + rebuild rendering; they just never re-execute.
- packages/agent/test/agent-loop.test.ts: two regression tests — one
  proves a marked block yields zero `tool.execute` calls and no
  `tool_execution_*` events from the loop, the other verifies mixed
  batches still run the unmarked blocks unchanged.

Fixes #4348
2026-07-02 21:26:37 +00:00
roboomp 3d86935a5e fix(agent): distinguish synthetic placeholder tool results from real tool failures
When an assistant turn ends with stopReason="error" after a tool call
was already streamed, agent-loop synthesizes a placeholder tool result
via createAbortedToolResult() to preserve the tool_use / tool_result
pairing the provider API requires. The previous wording ("Tool
execution failed due to an error: <upstream>") and event shape
(normal tool_execution_start / tool_execution_end with empty details)
were indistinguishable from a real local tool failure — a Codex
websocket close mid-turn showed up in the CLI as a broken Edit panel,
misattributing provider-transport faults to the local tool.

Reword the "error" placeholder to state explicitly that the tool
never ran ("Tool call was not executed because the provider stream
ended with an error before the tool could run: <upstream>") and thread
a SyntheticToolResultDetails discriminator ({ __synthetic: true,
source: "assistant_stop_error" | "assistant_stop_aborted" |
"assistant_stop_skipped" | "assistant_stop_length", executed: false,
upstreamError }) through both the ToolResultMessage.details and the
tool_execution_end event's result.details, so downstream UI/telemetry/
ACP consumers can render "provider transport failed, tool not
executed" without string-matching content.

Fixes #4321
2026-07-02 15:19:30 +00:00
can1357 21f5728ef8 fix(agent): prevented consuming legacy steering queue during mid-batch interrupts
- Stopped calling the consuming `getSteeringMessages` getter during mid-batch interrupt polls to prevent stranding or dropping messages before they reach the injection boundary.
- Skip subsequent steering checks in the poll loop once an interrupt has already triggered.
- Added a regression test to ensure legacy steering remains queued until the injection boundary when no non-consuming peek exists.
2026-07-02 03:34:14 +02:00
can1357 021d4fc1e3 Merge PR #4161: fix(agent): interrupt waits for IRC delivery (@roboomp) 2026-07-01 21:53:19 +02:00
can1357 23ea5e0808 test(agent): require queued skip text content 2026-07-01 21:47:55 +02:00
roboomp 1754c108df fix(agent): scoped irc-only aborts to interruptible tools
Previously an IRC-only interrupt shared the batch-wide abort controller with
user steering, so a peer message that landed while an interruptible wait ran
alongside a foreground non-interruptible tool (e.g. bash) killed the foreground
tool too. Split the batch signal into a shared steering/external channel and an
interruptible-only IRC channel; each record picks its per-tool signal based on
the tool's interruptible flag, and only that signal is used for validation,
before/after hooks, and execute. User steering still upgrades an in-flight IRC
interrupt to a full batch abort.
2026-07-01 17:14:04 +00:00
roboomp 619bfda3eb fix(agent): interrupted irc waits
Fixes #4160
2026-07-01 16:56:08 +00:00
Wolfgang Schoenberger 0d9ef89549 fix(agent): clarify queued skipped tool results 2026-06-29 19:46:13 -07:00
ben dc17aead5f fix(agent): narrow stream recovery review fixes 2026-06-28 16:18:46 +08:00
ben cb4e68888f fix(agent): recover completed tools after stream read errors 2026-06-28 16:18:46 +08:00
can1357 0b5e2d8276 fix(ai-providers): normalized Anthropic tool call IDs
- Implemented `normalizeAnthropicTargetToolCallId` to define consistent ID validation and fallback logic.
- Integrated the normalization utility into the `transformMessages` function to ensure API compatibility.
- Refactored `transformMessages` to decouple mapping logic from message loop execution for better maintainability.
- Updated the changelog to reflect the correction of tool call ID handling for Anthropic-compatible models.
2026-06-21 06:04:49 +02:00
roboomp 19d103b708 style: bun run fix 2026-06-19 15:14:50 +00:00
can1357 67f6518e42 feat: enhanced tool robustness, improve authentication flow, and update API parameters
- Implement JSON repair and strict argument validation to sanitize raw payloads and redact sensitive information from agent event logs.
- Add automatic authentication fallback for benchmark model resolution to ensure consistent performance testing across providers.
- Refactor search tool API parameters by replacing `i` with a case-sensitive `case` boolean flag for clarity.
- Update session history formatting to ensure empty objects are consistently serialized as `{}` instead of empty strings.
2026-06-19 16:46:07 +02:00
can1357 d46bd0139b refactor(coding-agent): fixed system prompt customization path
- Fixed `SYSTEM.md` integration to correctly include custom-rendered sections like rules and skills.
- Consolidated system prompt validation by requiring `<skills>` tag presence instead of specific prose.
- Removed redundant system prompt math-formatting tests and orphaned task batch documentation tests.
2026-06-19 16:16:37 +02:00
can1357 865694df7e fix: resolved streaming stability and reference isolation issues
- Prevent object reference sharing between agent snapshots and stream events by deep-cloning tool-call arguments.
- Stabilize GFM tables and Mermaid diagrams during streaming by delaying transcript block commits until content finalization.
- Implement session resume safety to prevent crashes when working directories are missing.
- Add comprehensive test suites to verify streaming commit stability and immutable snapshot isolation.
2026-06-19 16:09:00 +02:00
can1357 4f03180ae6 refactor(deps): moved intent field constant to pi-wire
- Moved the `INTENT_FIELD` constant from `@oh-my-pi/pi-agent-core` to the specialized `@oh-my-pi/pi-wire` package to permit broader usage across the monorepo.
- Updated all references across `agent`, `ai`, `coding-agent`, `collab-web`, and `snapcompact` packages to import the constant from the new location.
- Added `@oh-my-pi/pi-wire` as a dependency to all affected packages.
2026-06-19 04:58:29 +02:00
can1357 291b3c74c2 feat: enhanced model reasoning, schema normalization, and loop guarding
- Integrated comprehensive loop guard support for DeepSeek and assistant prose patterns, including configurable stream checks.
- Implemented Moonshot Flavored JSON Schema (MFJS) normalization for improved tool compatibility and enum type inference.
- Added support for Ollama reasoning effort backfilling and Grok-specific service tier cost tracking across providers.
- Expanded model catalog with new entries and unified compatibility logic for improved OpenRouter API integration.
2026-06-18 04:51:43 +02:00
can1357 a050474af7 feat: migrated validation schemas and tool definitions from Zod to ArkType
- Migrated all wire protocol, schema definitions, and tools validation from Zod to ArkType across multiple packages.
- Updated extension runtimes, custom tools loader, and TypeBox compatibility shim to expose and use ArkType instances.
- Added a comprehensive ArkType migration guide, validation parity tests, and helper utilities.
- Removed redundant PDF asset routing and parsing implementations from the read tool.
2026-06-18 00:59:53 +02:00
can1357 0d9ec354e7 fix: fixed Gemini thinking-loop handling across streaming dispatch paths
- Added Gemini thinking-loop detection helpers for near-duplicate and verbatim output checks.
- Wrapped `stream`, `streamPiNative`, and `streamSimple` dispatches with the loop guard.
- Emitted retryable empty-content loop errors and stopped completion events on loop hits.
- Added `enableGeminiThinkingLoopGuard` options for OpenAI compatibility with Gemini defaults and overrides.
2026-06-17 13:44:33 +02:00
can1357 5157de5b16 fix(agent): enforce deadline at tool-execution, yield, and in-flight boundaries
The deadline was only checked at loop entry and the top of the inner loop,
so a provider response returning tool calls after the deadline still
executed them, and a deadline crossed during onBeforeYield could dequeue
then drop queued steering/follow-up messages.

- Re-check the deadline after streamAssistantResponse before running tools;
  pair leftover tool calls with aborted "Deadline exceeded" placeholders to
  keep the tool_use/tool_result contract valid.
- Re-check after emitTurnEnd and after onBeforeYield before draining the
  steering/aside/follow-up queues so queued messages are never dequeued and
  dropped.
- Merge a deadline AbortController into the loop signal so in-flight provider
  requests and tools are cancelled at the boundary.
2026-06-17 12:44:23 +02:00
usr_bin_roygbiv 39169c8878 feat: add max-time deadline support 2026-06-17 12:44:23 +02:00
can1357 39f866fc73 feat(agent): added interruptible tool polling for queued steering
- Added an `interruptible` field to AgentTool and documented when it is honored.
- Updated immediate-mode tool execution to poll steering during in-flight interruptible calls and abort them when steering is queued.
- Marked the coding `job` tool as interruptible and added tests covering mid-wait aborts versus boundary-only steering drain.
2026-06-15 11:53:25 +02:00
can1357 3efebf8805 fix: harden merged provider, agent-loop, eager, and autolearn paths
- agent-loop: raise repetition-detection floor to 180 chars and clear thinking
  replay anchors when collapsing a detected loop.
- providers/google: ignore empty text parts, retain terminal thoughtSignatures,
  and stop function-call signatures clobbering the prior block.
- autolearn: capture goal-mode at the turn boundary; harden managed-skill writes
  against hard-links/symlinks (O_NOFOLLOW + nlink); refuse minting managed skills
  whose name an authored skill already claims.
- eager tasks: thread agentKind through the session so a custom top-level agentId
  still gets always-mode delegation; split Eager Tasks prompt into hard vs soft.
- title-generator: race the online title model against a local tiny-model fallback.
- eager-todo: keep the soft reminder aligned with the todo init schema.
- mcp/stdio: keep close() detaching the read loop instead of awaiting it.
- stream loop: fix collapsing and tool-call thought-signature handling.
2026-06-14 17:09:59 +02:00
usr_bin_roygbiv 865d7630be fix(agent-loop): abort provider stream on repetition and restrict to Gemini models 2026-06-14 00:08:12 -05:00
usr-bin-roygbiv 48843f0ea3 fix(agent-loop): detect repetition loops during assistant stream and abort gracefully 2026-06-13 23:20:36 -05:00
can1357 64aa558e62 chore: consistency 2026-06-13 00:03:27 +02:00
can1357 28df38ed37 feat(agent): added useless-result tagging and compaction dropping of tool outputs
- Added optional `useless` flags to tool result types and payload builders.
- Added `pruneUseless` and `dropUeless` options to control uneventful result pruning.
- Changed compaction and shake passes to prune or ignore non-error useless tool results.
- Changed conversation serialization to omit useless toolCall/toolResult pairs from output.
- Added coverage for useless tagging, pruning, and serialization behavior.
2026-06-12 16:26:38 +02:00
can1357 51208e5de1 feat(coding-agent): added boundary-aware steering and idle steer-queue handling
- Added optional `hasSteeringMessages` config hook and limited steering checks to boundaries.
- Fixed interrupted tool-batch steering by keeping queued messages until boundary handling.
- Added idle text and image submissions to steer queueing when no input waiter exists.
- Auto-continued resumable sessions after queued steering and preserved submit metadata.
2026-06-12 03:30:51 +02:00
can1357 eb966cc6dc fix: handled non-terminal pause_turn stops by resampling interrupted turns
- Mapped Codex `end_turn:false` terminal events to `pause_turn` stop details in response stream parsing.
- Updated `agent-loop` to re-sample `pause_turn` turns, reset on tool calls, and cap continuations at 8.
- Added coverage for pause-turn mapping and continuation-capping in agent and AI stream tests.
2026-06-12 02:33:45 +02:00
can1357 ce4ebad726 feat(agent): added per-call tool concurrency resolver and parallel bash execution
- Extended `AgentTool.concurrency` to accept per-call resolver functions and resolved concurrency mode from each tool call, falling back to exclusive on resolver errors.
- Updated BashTool to schedule non-PTY calls as shared and PTY calls as exclusive so non-interactive bash calls can run in parallel within one message.
- Tracked in-use persistent shell sessions in the bash executor and routed overlapping calls on the same session key to isolated one-shot shells while preserving owner session availability.
2026-06-11 18:13:07 +02:00