Commit Graph
9801 Commits
Author SHA1 Message Date
roboomp e0e24efaf6 fix(tools): strip stray leading colon from tool paths
Some models intermittently prefix an otherwise-valid path with a leading
`:` (e.g. `:/abs/path`, `:../rel`). read/edit/grep hard-failed because
resolveToCwd left the colon intact and resolution missed the real file.
The #4618 literal-preferring probe cannot recover it: the literal
`:/abs/path` does not exist on disk, so the peel proceeds to an empty
path.

Strip the mangled prefix in expandPath — the shared resolution funnel for
read (resolveReadPath), grep (resolveToolSearchScope), and edit
(resolvePlanPath) — mirroring the existing @-prefix normalization. The
lookahead only fires before `/`, `~/`, `./`, or `../`, so selector-shaped
tokens like `:raw` are untouched.

Fixes #5508
2026-07-14 20:41:45 +00:00
roboomp eef79705a6 fix(eval): passed js uri selectors separately
- Kept opaque MCP resource paths unchanged during JS pagination.
- Sent JS line ranges through the read tool selector field.
- Covered the shipped JS prelude and updated the changelog.

Fixes #5353
2026-07-14 20:31:58 +00:00
roboomp 1a4c195017 fix(coding-agent): accepted silent advisor stops with output tokens
The advisor runtime rejected every content-less stop completion as a
failed turn, so a deliberate silent review (the documented verifier
behavior) triggered retries and a spurious "unavailable" warning. Only
treat a content-less stop as a failure when it produced no output signal
(zero output and reasoning tokens), so a token-bearing silent stop counts
as a successful silent review.

Fixes #5493
2026-07-14 20:31:21 +00:00
roboomp 9b8ec997b2 fix(coding-agent): reused one codex side session per guided-goal interview
- Minted the guided-goal Codex side session id once per interview in handleGuidedGoalCommand and threaded it through every turn via GuidedGoalTurnOptions.sideSessionId, so a multi-question interview shares a single websocket-only Codex socket instead of opening a fresh one each turn (which could trip websocket_connection_limit_reached and fall back to the rejected SSE path).
- Exported newGuidedGoalSessionId; runGuidedGoalTurn mints its own id only when no side session id is supplied (one-shot callers, tests).
- Added regression coverage asserting the supplied side session id is reused across turns.

Fixes #5304
2026-07-14 20:25:16 +00:00
roboomp 1be025bb72 fix(cursor): propagated returned tool error status
Cursor exec bridges derived failure state only from thrown exceptions, so structured AgentToolResult.isError failures were emitted as successes. Propagate the returned flag through standard and streaming shell execution, with regression coverage for both paths.
2026-07-14 20:20:54 +00:00
roboomp 2bfdf0ab07 fix(eval): passed uri selectors separately
- Kept opaque MCP resource paths unchanged during pagination.
- Sent line ranges through the read tool selector field.
- Covered paged artifact and MCP reads in the Python prelude test.

Fixes #5353
2026-07-14 20:20:42 +00:00
roboomp 90c4726bae fix(launch): passed Windows PTY arguments directly
Added a direct-argv PTY entry point and used it for Windows launch sessions so portable-pty no longer re-quotes cmd.exe command text.

Rejected direct .bat and .cmd applications with guidance to use cmd.exe /c.

Fixes #5416
2026-07-14 20:17:03 +00:00
roboomp 56fb4c0145 fix(tools): recover from active OpenAI image HTTP failure
Threw ProviderHttpError from generateOpenAIHostedImage so a failing active OpenAI/Codex image call records the failure and continues the provider fallback chain instead of aborting the tool call.

Fixes #5218
2026-07-14 20:16:37 +00:00
roboomp c9032e57b5 fix(session): keep explicit /compact snapcompact failing on text-only models
wantsSnapcompact is true for both the default strategy and an explicit
/compact snapcompact mode override. The prior fix downgraded both to LLM
compaction, which silently shipped the transcript to a provider for users
who deliberately requested the local-only no-LLM archive path. Only the
default-configured strategy now falls back; explicit snapcompact keeps
failing locally. Added a regression test for the explicit path.

Fixes #5064
2026-07-14 20:12:24 +00:00
roboomp 00c8e921f6 fix(agent): strip images for non-vision models mid-session
Switching from a vision model to a text-only model kept replaying
historical image content blocks to the new provider, which rejected them
with invalid_argument. The convertToLlm wrapper in sdk.ts only filtered
images when images.blockImages was set, never by model capability, so
the outbound request carried image blocks the active model could not
accept.

Add replaceLlmImagesWithText() to scrub image blocks out of the
already-converted LLM message view, and call it from the sdk wrapper
when the active model's input lacks "image". History on disk keeps its
images; only the provider request is scrubbed, and the check reads the
active model dynamically so a /model switch takes effect next turn.

Fixes #5400
2026-07-14 20:11:25 +00:00
roboomp e49638ddac fix(auth): routed enhanced paste into login prompts
Forwarded OSC 5522 text from the focused login dialog to its credential input and added regression coverage for direct API-key prompts.

Fixes #5394
2026-07-14 20:06:14 +00:00
roboomp 19674b8dfa fix(skills): reloaded runtime skill state
- Rediscovered enabled skills across TUI, ACP, and RPC plugin reloads.
- Rebuilt skill commands, system prompts, tool snapshots, and skill URL resolution.
- Hot-refreshed managed skills after manage_skill create, update, or delete.

Fixes #4996
2026-07-14 20:01:45 +00:00
roboomp a9e6e4e67e fix(bash): aborted isolated shells on cancellation
Route overlapping executions through owned Shell instances so timeout and interrupt paths can explicitly abort native child-process cleanup.

Fixes #5389
2026-07-14 19:57:59 +00:00
roboomp d1bcd5812b fix(tui): anchored kitty images through tmux
- Wrapped every Kitty graphics APC for tmux passthrough, preserved quiet mode across chunks, and enabled placeholder placement when Kitty is explicitly forced.

- Routed Agent Hub transcript images through the shared image budget and terminal image setting.

Fixes #5381
2026-07-14 19:53:12 +00:00
roboomp 5e71fac653 fix(session): retried bare Request was aborted error-stop turns
A stalled or dropped provider stream that surfaces as stopReason:"error"
carrying the bare "Request was aborted" sentinel fell through both retry
gates: #isRetryableReasonlessAbort required stopReason:"aborted", and
#isRetryableError's classifier returns no retriable kinds for the generic
sentinel. The turn died immediately despite retry.enabled.

- Relaxed #isRetryableReasonlessAbort to accept an empty generic-abort
  sentinel turn under stopReason "aborted" or "error", tagging it Abort so
  #handleRetryableError retries it without model fallback.
- Kept the deliberate-abort guards intact: user interrupts and silent aborts
  carry their own markers (not the generic sentinel), and #abortInProgress /
  #isDisposed / #streamingEditAbortTriggered still settle without retry.
- Rewrote the stale fallback test that froze the buggy no-retry behavior to
  assert retry-and-recover for the error-stop sentinel.

Fixes #5375
2026-07-14 19:39:24 +00:00
roboomp 506d0942cf feat(telemetry): added otlp log and metric export
Extended the OTLP export bootstrap beyond traces so omp emits the full
OpenTelemetry signal set from a single session.

- Registered a LoggerProvider + BatchLogRecordProcessor and a MeterProvider
  + PeriodicExportingMetricReader when their OTLP endpoints (or the shared
  endpoint) are set, each gated independently by OTEL_*_EXPORTER=none,
  OTEL_SDK_DISABLED, and http/protobuf protocol checks.
- Bridged the centralized logger through a new registerLogSink API so every
  log event also becomes an OTLP log record with severity, attributes, and
  active span context for log-trace correlation (min level via OTEL_LOG_LEVEL).
- Recorded gen_ai.client.token.usage and pi.omp.agent.* metrics from the
  agent run summary and per-chat usage hooks, and emitted a structured run
  summary log event.
- Added an out-of-process logs+metrics probe and gating tests covering the
  per-signal kill switches.

Fixes #4604
2026-07-14 19:39:11 +00:00
roboomp 2439f77e70 fix(plugins): refreshed stale bun git cache before reinstall
Fetched current heads and tags into Bun's matching cached bare clone before running bun update.

Added an isolated HTTP git regression covering a moved branch with a stale cache.

Fixes #5401
2026-07-14 19:37:06 +00:00
roboomp 6b12dd4d48 fix(prompt): restored non-linux cpu model metadata
Restored the previous best-effort os.cpus() lookup outside Linux while preserving the /proc/cpuinfo startup path on Linux.

Fixes #4755
2026-07-14 19:32:29 +00:00
roboomp 501c3592be fix(session): land tree navigation on /skill: injection node
navigateTree() treated every custom_message entry as a re-editable user
turn, setting the leaf to the injection's parent and dumping the expanded
skill body into the editor. A /skill:<name> invocation is persisted as a
skill-prompt custom_message, so selecting it in /tree dropped the skill off
the active branch. Skip the parent-leaf/editor-prefill path for
skill-prompt entries so the leaf lands on the injection node itself.

Fixes #5374
2026-07-14 19:27:04 +00:00
roboomp cad30f8c29 fix(review): fall back to per-file API when PR diff exceeds 20k lines
GitHub rejects the aggregate PR diff endpoint with HTTP 406 once the diff
exceeds 20,000 lines, which made `fetchPrDiffFresh` throw and aborted the
entire /review workflow. Detect the 406 (diff-too-large) specifically and
fall back to the paginated per-file endpoint, reassembling a synthetic
unified diff. Files whose patch is omitted (binary or too large) stay
visible with an explicit marker instead of being dropped.

Fixes #5350
2026-07-14 19:25:02 +00:00
roboomp 7881fce976 fix(plugins): preserved native commonjs helper loading
Kept synchronous require() targets on Bun’s native loader while retaining hooks for native-addon rewrites.

Added regression coverage for ESM extensions loading CommonJS helper files.

Fixes #5373
2026-07-14 19:22:00 +00:00
roboomp de72e15fa8 fix(tools): accepted empty GitHub search date placeholders
Normalized optional since and until values before enforcing code-search date restrictions.

Covered empty placeholders, real date bounds, and successful validated searches.

Fixes #5370
2026-07-14 19:19:09 +00:00
roboomp 51ab2fcf23 fix(catalog): made codex discovery authoritative
Replaced stale bundled OpenAI Codex entries after successful account-scoped discovery in both runtime resolution and catalog generation.

Fixes #5364
2026-07-14 19:17:43 +00:00
roboomp 83ed5eef1f fix(tui): guarded DynamicBorder against uninitialized module-level theme
Extensions importing legacy pi UI components (e.g. DynamicBorder from
@earendil-works/pi-coding-agent) receive a second src module graph in
npm-package installs. Host startup assigns the module-level `theme` only
inside the bundled dist copy, so the src-graph copy stays undefined and
DynamicBorder.render dereferenced `theme.boxRound` unconditionally,
throwing "undefined is not an object" and taking down the whole TUI.

Route the default color through the existing `fgOrPlain` guard and fall
back to the default rounded glyph when `theme` is undefined, matching the
`typeof theme === "undefined"` degradation already used by fgOrPlain and
getSettingsListTheme.

Fixes #5366
2026-07-14 19:14:16 +00:00
roboomp 5d6fcff2f1 fix(eval): delegated python uri reads to host resolver
- Routed non-local URI reads through the session read tool.
- Preserved offset and limit as host line selectors.
- Covered artifact delegation with the shipped Python prelude.

Fixes #5353
2026-07-14 19:12:06 +00:00
roboomp 52f9e41304 fix(tui): hand editor tap state to agent hub on double-left open
The empty-editor left-left gesture opens the Agent Hub whenever persisted
or parked subagents exist (intended since f3e372e7b), but the hub's own
close detector starts fresh at 0 with no handoff from the editor's
double-tap detector. The two taps that opened the hub were consumed by the
editor, so a single subsequent left did nothing and the user had to press
left-left again to escape while input and hotkeys stayed disabled.

Thread an armCloseTap option from the gesture through showAgentHub to the
new AgentHubOverlayComponent.armCloseTap(), which seeds the table's
#lastLeftTap so one more left (within the tap window) dismisses the hub.

Fixes #4780
2026-07-14 19:07:04 +00:00
roboomp 06095c1031 fix(models): cleared stale thinking on auto role assignment
- Persisted an explicit inherit override when auto replaces a role's concrete reasoning level.
- Covered the Model Hub DEFAULT assignment flow with a regression test.

Fixes #5326
2026-07-14 19:04:12 +00:00
roboomp 86824c94e9 fix(ttsr): registered rules with inline regex flags and malformed scope
Rules whose condition led with a PCRE-style inline flag group (e.g.
`(?i)`) never registered: `new RegExp("(?i)...")` throws in Bun/JS, so
the condition failed to compile and `TtsrManager.addRule` dropped the
rule as having zero usable conditions.

- Add `compileRuleCondition` in capability/rule.ts translating a leading
  `(?i)`/`(?m)`/`(?s)` group into native RegExp flags; wire it into the
  TtsrManager and both ttsr-cli compile sites.
- Strip surrounding quotes from scope tokens so a malformed
  `scope: "text","thinking"` recovers to canonical `text`/`thinking`.
- Reparse each value in parseFrontmatter's YAML fallback so one bad line
  can't leave sibling values wrapped in literal quotes.

Fixes #4796
2026-07-14 19:01:47 +00:00
can1357 1f619dcf18 feat(ai): enhanced Codex rate-limit header ingestion and usage-based key ranking
- Added a Codex rate-limit parser for `x-codex-*` headers and registered it with the Codex usage provider.
- Updated auth-storage to require parsed usage headers before ingesting usage data, treated exhaustion as non-throttled, and renamed ranked candidate drain fields.
- Reworked key ranking math to use `headroom / remainingHours` with a 1-minute minimum, then applied measured-usage precedence with hot-window demotion behavior.
- Updated session handling and tests to support provider-aware header ingestion with deterministic, exhaustion-aware account selection.
2026-07-14 20:54:03 +02:00
roboomp bcca907e59 fix(cli): aliased clear to new session
Added /clear as a /new alias so exact slash completion outranks /autoresearch description matches.

Fixes #5349
2026-07-14 18:46:13 +00:00
roboomp 4882c9b011 fix(auth): mount login dialog input for paste-code fallback URL
Paste-code OAuth providers (Codex, Anthropic, Gemini CLI, GitLab Duo,
Antigravity, Devin) need the user to paste the fallback redirect URL
when the loopback callback cannot complete (headless/remote/Windows).
The login dialog took focus and cleared the editor but only rendered the
auth URL plus a tip pointing at `/login <redirect URL>` — a command only
reachable through the now-hidden, unfocused editor. The dialog never
mounted an Input, so a pasted URL was silently dropped and login stalled.

Route onManualCodeInput through the focused dialog's showManualInput so
the paste lands in a visible, submittable field. Make showManualInput
idempotent so the OAuth callback retry loop reuses the mounted input
instead of stacking duplicate prompts.

Fixes #5339
2026-07-14 18:44:01 +00:00
roboomp 6467a3119e fix(discovery): rooted relative plugin mcp command and cwd at config dir
Discovered plugin .mcp.json stdio servers launched relative command/cwd
values against the session cwd instead of the plugin's config directory,
breaking bundled ChatGPT/Codex plugins (e.g. Computer Use) with ENOENT
when spawning ./... from an unrelated cwd.

The claude-plugins and omp-plugins providers now resolve relative cwd and
path-like command (./ or ../) against the .mcp.json directory via a shared
resolvePluginStdioPaths helper; bare executables such as npx are left
untouched so PATH lookup still works.

Fixes #5330
2026-07-14 18:36:21 +00:00
roboomp c97449c51d fix(web-search): stop perplexity oauth token leaking to api-key endpoint
The consumer ask endpoint (/rest/sse/perplexity_ask) intermittently closes
its socket before responding. getApiConfigs emitted the OAuth session JWT
(returned by getApiKey while OAuth is the active origin) as a direct
api.perplexity.ai api-key config, so a transient transport failure on the
ask endpoint fell through and sent the session token as a Bearer to the
direct API, whose 401 masked the real error.

- Suppress the direct api-key config when getCredentialOrigin reports the
  active perplexity credential as oauth.
- Give the OAuth ask request one transport-only retry; HTTP responses
  (including 401/429) are final and never retried.
- Add regression coverage for both legs.

Fixes #5315
2026-07-14 18:28:43 +00:00
roboomp 68f84d7c20 fix(tui): prevented stale-buffer flicker
- Kept fullscreen replacement overlays mounted through asynchronous transcript rebuilds.
- Fused alternate-screen exit with destructive repaint and removed resize-time buffer switches.
- Preserved statically detected synchronized output when DECRQM probing is inconclusive.

Fixes #5319
2026-07-14 18:23:45 +00:00
roboomp d77a3e154a fix(tui): aligned ask "Other" custom-input chrome to prompt gutter
The prompt-style HookEditorComponent (used by the ask tool's "Other"
custom-input flow) rendered its title, option list, and hint via
Text(padX=1) while the borderless editor beneath renders its `> ` gutter
at column 0, leaving the input row one column left of everything else.
Pad the prompt-style chrome at column 0 to match the gutter; hook-style
(bordered) chrome keeps its 1-column indent that lines up with the
bordered editor body.

Fixes #5313
2026-07-14 18:23:30 +00:00
roboomp 8b179ffc3b fix(coding-agent): routed guided-goal oneshot through codex websocket transport
- Passed the session provider transport (providerSessionState + preferWebsockets) and an isolated session id to the /guided-goal interview completion so websocket-only Codex models (gpt-5.6-luna/sol/terra) get a websocket session instead of an SSE fallback the Codex /responses endpoint rejects with "Model not found".
- Added regression coverage asserting the guided-goal request inherits the session transport with an isolated session id.

Fixes #5304
2026-07-14 18:09:59 +00:00
roboomp 3fa5ffd0b1 fix(tui): handled Kitty vim navigation sequences
Routed vim-style h/j/k/l navigation through the protocol-aware key matcher across custom coding-agent selectors and overlays.

Fixes #5314
2026-07-14 18:08:23 +00:00
roboomp df7aa6d01f fix(cli): awaited config JSON stdout flush
- Waited for the stdout write callback before the config command exits.
- Covered JSON output larger than the 64 KiB pipe buffer.

Fixes #5309
2026-07-14 18:06:40 +00:00
roboomp 5878ed8f49 fix(tools): gate generate_image behind setting and tool whitelist
generate_image was registered as a custom tool and force-activated via the alwaysInclude list in createAgentSession, so it survived --no-tools (empty toolNames) and any explicit whitelist that omitted it. There was also no generate_image.enabled setting, so /settings had no toggle.

Add a generate_image.enabled setting and only register the tool when enabled and either no whitelist is given or it names generate_image.

Fixes #5305
2026-07-14 18:06:10 +00:00
roboomp 5303c3852e fix(extensions): let tool_result rewrite thrown failure content
ExtensionToolWrapper caught a thrown tool exception, emitted tool_result
with the modifiable result, then rethrew the original executionError whenever
the effective error state stayed true. This discarded any replacement content
or details a handler returned, so an extension could only surface modified
content by returning isError: false, which wrongly converted the failure into
a success.

Return the (possibly modified) result carrying isError instead of rethrowing.
The agent loop already honors AgentToolResult.isError (coerceToolResult) and
surfaces it as a tool error on the wire, so replacement failure content now
reaches the model while the call remains an error. No-modification, error->success, and success->error paths keep their existing semantics.

Fixes #5302
2026-07-14 18:01:02 +00:00
roboomp cc9977cce4 fix(advisor): anchored context maintenance on provider usage
- Anchored advisor compaction on provider-reported context usage (cached
  input + generated output) floored by a full local estimate including the
  advisor system prompt and tool schemas, so a near-full cached context is no
  longer undercounted by the per-message estimate.
- Rejected stale provider usage retained across advisor compaction via a
  runtime-only usage-anchor boundary recorded on the summary message.
- Recovered provider overflow by clearing only the advisor's own context at
  the current primary cursor, retrying the bounded failing batch once against
  a fresh context without replaying old primary history, and keeping later
  updates eligible.
- Threaded the selected dashboard range through the stats Recent Errors UI,
  API, and database timestamp filter before ordering and the 50-row limit.

Fixes #5282
2026-07-14 17:58:19 +00:00
roboomp 4bc68b45e2 fix(coding-agent): persisted vibe sessions across restarts
Vibe worker roster lived only in a process-local Map, so a resumed parent
session started with an empty registry and vibe_send failed with
"Unknown vibe session". Persist a versioned, parent-scoped lifecycle
journal (spawn/turn/tombstone events), rehydrate validated idle workers
through the persisted-subagent reviver on resume, and gate the flow with
generation/CAS protection so stale finalizers cannot clobber a
replacement worker. Killed transcripts stay readable but non-revivable;
mode-exit commits tombstones atomically with the mode change and rolls
back cleanly on storage failure.

Ported from @mastertyko's fork branch fix/vibe-session-persistence.

Fixes #5303
2026-07-14 17:58:14 +00:00
roboomp 8c6b2fb450 fix(coding-agent): resolved agent:// slash form for nested subagent output
The agent:// path segment was always treated as a jq JSON-extraction key
against <parent>.md, so agent://Parent/Child loaded Parent.md and applied
.Child instead of resolving the nested child capsule Parent.Child.md. A
precise-planner reading its own scout child therefore got Not found.

The slash is now a hierarchy separator first: agent://Parent/Child resolves
Parent.Child.md (subagent children are allocated as dot-qualified ids). It
falls back to JSON extraction only when no nested output matches the path;
the ?q= query form is always extraction.

Fixes #5238
2026-07-14 17:52:04 +00:00
roboomp 33e87d5930 fix(browser): bound headless browser close to unblock tab cleanup
disposeBrowserHandle awaited Puppeteer's browser.close() for the headless
kind with no timeout. browser.close() resolves only once Chromium fully
exits, so a wedged process (a Windows failure mode) left releaseTab stuck
in the "Closing tab" phase forever.

Cap the close at 5s and force-kill the Chromium process tree on timeout so
the tool call always releases.

Fixes #5260
2026-07-14 17:48:18 +00:00
roboomp 3666cb93d2 fix(coding-agent): rejected prose thinking session titles
Rejected markerless prose thinking preambles while preserving marked titles and plain markerless title responses.

Fixes #5252
2026-07-14 17:48:15 +00:00
roboomp fb98465923 fix(mcp): preserved discovered registration endpoint
Threaded the authorization server's advertised registration endpoint through OAuth discovery, add, reauth, and the client flow instead of deriving metadata from the authorization endpoint.

Added pathful-issuer discovery and end-to-end DCR regression coverage.

Fixes #5267
2026-07-14 17:46:24 +00:00
roboomp e29fbce55c fix(internal-urls): serve history:// transcripts from disk fallback
history:// resolve/complete/index queried the in-memory AgentRegistry
exclusively, so transcripts of unregistered one-shot helpers
(keepAlive: false), released agents, or any subagent after a session
resume threw "Unknown agent" despite their .jsonl session file
persisting on disk — unlike agent://, which reads .md outputs off disk.

Added sessionFilesFromDisk() to registry-helpers: a recursive scan of
the artifacts dirs keyed by agent id, excluding advisor transcripts
(__advisor*.jsonl) and EPERM-rewrite backups (.bak). HistoryProtocolHandler
now falls back to it on a registry miss (resolve and the else branch),
merges on-disk agents into the index, and unions them into completions.
Documented history:// in the system prompt's Internal URLs section.

Fixes #5261
2026-07-14 17:41:26 +00:00
roboomp 3abade7256 fix(tui): trigger internal-url autocomplete inside slash args
The allowArgs branch in PromptActionAutocompleteProvider.getSuggestions
returned CombinedAutocompleteProvider's result verbatim, so a null from
the base provider short-circuited before getInternalUrlSuggestions.
Internal URL schemes (agent://, skill://, omp://, ...) never completed
inside slash command arguments.

Fall through to internal-url completion when the base provider yields no
argument match. `#` prompt-action tokens stay literal inside slash args.

Fixes #5263
2026-07-14 17:37:55 +00:00
roboomp 7b399b32a2 fix(browser): bounded tab teardown waits
- Applied close deadlines to cmux surfaces, orphan targets, and browser handles.
- Surfaced the backend, tab name, and pending cleanup resource on timeout.
- Forced stuck headless browser processes down after Browser.close timed out.

Fixes #5259
2026-07-14 17:37:01 +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