Commit Graph

3900 Commits

Author SHA1 Message Date
can1357 724ef3784a chore: fix mentions of read tool in backticks causing confusing against bash read 2026-05-13 05:22:41 +02:00
can1357 b513fee874 docs(coding-agent/prompts): adjusted system prompt wording to soften hardline constraints
- Revised the system prompt wording in collaboration guidance from absolute prohibitions to explicit "avoid" directives.
- Adjusted multiple policy lines to reduce rigid phrasing around handling difficult user proposals, harness docs, and unnecessary file reads.
- Kept the behavioral intent intact while making the instructions more nuanced in the high-reliability prompt text.
2026-05-13 05:13:18 +02:00
can1357 c53c63e96d fix(coding-agent/internal-urls): patched numeric host diff path parsing
- Extended short-form diff URL parsing to treat `<scheme>://N/diff` as a diff path across schemes, so `issue://N/diff` now follows the issue no-diff rejection path.
- Kept repository listing behavior unchanged for `<scheme>://owner/diff` by limiting diff short-form disambiguation to numeric hosts.
- Added regression coverage asserting `issue://9/diff`, `issue://9/diff/all`, and `issue://9/diff/3` now reject with the issue no-diff error.
2026-05-13 04:52:27 +02:00
can1357 1ccc56aca6 fix(coding-agent/eval): routed JS import calls through session-aware import helper
- Updated JS import rewriting to route top-level `import` declarations through `__omp_import__` with support for import attributes.
- Added AST traversal to replace `import(...)` call callee nodes with `__omp_import__` so dynamic imports resolve via session-aware helper.
- Updated runtime `__omp_import__` to accept an optional options object and pass it through to `import(target, options)`.
2026-05-13 04:47:49 +02:00
can1357 e7b4b4c20d fix(coding-agent): fixed read tool streaming routing and result expansion behavior
- Updated event-controller read-tool streaming handling to wait for a parseable target before routing tool calls, avoiding early component binding for unresolved arguments.
- Allowed internal-URL read calls to bypass the regular read grouping path and fall through to direct tool execution.
- Adjusted read tool rendering to honor the computed `expanded` flag for completed output instead of forcing expanded output.
2026-05-13 04:42:43 +02:00
can1357 e70084976b fix(coding-agent): corrected issue-pr diff URL parsing to list outputs
- Fixed `issue://owner/diff` and `pr://owner/diff` parsing so they resolve to issue and PR list outputs.
- Fixed `pr` short-form parsing by requiring `scheme==='pr'` and a numeric host before `diff` matching.
- Fixed PR unified-diff parsing to decode quoted header paths and count `----`/`++++` hunk lines as one deletion/addition.
- Fixed `read` error rendering to emit status blocks with cleaned, range-aware, tab-normalized lines.
- Stopped `github-cache` from chmod-ing existing parent directories, preserving pre-existing permission modes.
2026-05-13 04:39:16 +02:00
can1357 e1589bb137 fix(coding-agent/modes): parsed selection from path before language detection
- Updated read entry syntax highlighting to derive language from a path split from selection suffixes.
2026-05-13 04:34:08 +02:00
can1357 ed64b3bd64 fix(coding-agent): hardened URL and repo default-resolution cleanup
- Guarded session manager lookup in internal URL cwd resolution to handle missing managers safely.
- Replaced `Promise.finally` cleanup with explicit `then` handlers so default-repo in-flight entries are removed on both success and failure.
2026-05-13 04:32:51 +02:00
can1357 322095dd78 fix(coding-agent/tools): used split file path when determining read tool language
- Updated language detection to use the base file path from splitPathAndSel before calling getLanguageFromPath.
2026-05-13 04:32:47 +02:00
can1357 64b4aa1ae0 feat(coding-agent): implemented PR diff URL parsing for pr://<N>/diff
- Replaced `op: pr_diff` with `pr://<N>/diff` URL variants and routed PR diffs through URL parsing.
- Added `readArgsHaveTarget` checks to gate read-call tracking on `path`/`file_path` targets.
- Added auth-key-aware GitHub caching with scoped rows, default auth resolution, and hard-TTL invalidation.
- Added markdown output rendering for read with markdown-cell layout, ANSI-aware truncation, and expand-width cache reuse.
- Updated PR diff and cache tests, replacing deprecated `pr_diff` cases with `/diff` and auth/TLL coverage.
2026-05-13 04:32:16 +02:00
can1357 c888a9fa36 docs(coding-agent/prompts): strengthened coding-agent prompts with stricter directive wording
- Updated system and subagent prompts to replace soft prohibitions with stricter NEVER/IMMEDIATE wording where behaviors were previously expressed as DO NOT.
- Added a dedicated system-conventions block to the main system prompt to formalize RFC-2119 and tag-authority guidance.
- Reworded multiple tool prompt guides (AST, file lookup, search/read, browser, hashline) to tighten behavioral constraints and clarify invalid command usage.
2026-05-13 04:10:39 +02:00
can1357 d483531b6b fix(coding-agent): decoupled internal URL read calls from read tool grouping
- Added readArgsTargetInternalUrl in the read tool group component to detect targets handled by InternalUrlRouter from path or file_path arguments.
- Updated event-controller and UI helper read rendering paths to skip grouping read tool calls when those arguments target internal URLs.
- Passed session cwd and settings into internal URL resolution in read.ts and added tests for internal versus non-internal target detection.
2026-05-13 04:05:23 +02:00
can1357 a733390462 feat: added issue:// and pr:// handlers with sqlite cache ttl refresh
- Added issue:// and pr:// URL handlers for single lookups and list queries with query filters.
- Added a SQLite-backed GitHub cache with soft/hard TTLs, stale hits, and background stale refresh.
- Removed issue_view and pr_view tool operations, inputs, and docs, requiring reads via issue:// and pr:// URLs.
- Added github-cache and issue-pr-protocol tests with temporary cache DB setup and OMP_GITHUB_CACHE_DB teardown.
2026-05-13 04:04:45 +02:00
can1357 569438fdc5 test: drop stale inspect_image guidance assertion 2026-05-13 03:26:05 +02:00
can1357 c27d007828 feat(docs): added NEVER/AVOID guidance to agent/tool/system prompts
- Standardized prompt templates across agents, tools, system, memory, and compaction to NEVER/AVOID wording.
- Reinforced policy language to ban edits/builds, state changes, and unsolicited JSON/code or filler output.
- Renamed stripRfc2119Bold to normalizeRfc2119, mapped NEVER/AVOID aliases, and skipped inline-code replacements.
- Updated the unreleased changelog to document the prompt-terminology migration.
2026-05-13 03:10:39 +02:00
can1357 1d4ea04769 fix(coding-agent): honor path-scoped enabledModels in default fallback
The SDK default-model fallback used `modelRegistry.getAll()` and only
filtered by stored credentials, ignoring the path-scoped `enabledModels`
allow-list. When the configured `modelRoles.default` was filtered out by
`disabledProviders`, the fallback could pick a model from a provider that
`enabledModels` did not permit for the current path.

Add `resolveAllowedModels(modelRegistry, settings, prefs)` which returns
`getAvailable()` intersected with the path-scoped `enabledModels`
patterns (or just `getAvailable()` when no patterns are configured), and
use it for both the default-role resolution and the fallback scan. When
`enabledModels` is set but no allowed model has usable credentials, the
fallback now surfaces a message instead of silently picking a disallowed
provider.

Fixes #1022.
2026-05-13 03:06:22 +02:00
can1357 b8d238b4ee docs(docs): documented RFC2119 terms to stay uppercase without bold
- Removed markdown bold from RFC 2119 MUST/SHOULD/REQUIRED across agent, tool, system, compaction, and memory prompts.
- Updated SKILL guidance to require uppercase RFC 2119 terms without bold emphasis.
- Renamed `boldRfc2119Keywords` to `stripRfc2119Bold` and made prompt formatting strip `**keyword**` markers.
- Preserved substantive prompt instruction wording while switching emphasis-only formatting in markdown templates.
2026-05-13 03:05:32 +02:00
can1357 2654859712 fix(coding-agent): wire ctx.shutdown() to InteractiveMode.shutdownRequested
The extension shutdown context action installed by
ExtensionUiController.initializeHookRunner was an empty stub, so
ctx.shutdown() in interactive mode silently did nothing while extensions
fell back to process.exit(0), bypassing session flush and terminal
restore. Flip InteractiveModeContext.shutdownRequested so the main
loop's existing checkShutdownRequested() drives the graceful path.

Fixes #1020.
2026-05-13 02:58:02 +02:00
can1357 a376cf8205 fix(tools): corrected github tool search parsing for /search/issues responses
- Switched issue and PR search handlers to `gh api /search/issues` with `is:issue`/`is:pr` queries.
- Added REST search response models and mapped issue/code/commit/repo payloads to normalized results.
- Updated code, commit, and repo search parsing to read `{items}` envelopes and convert snake_case fields.
- Fixed merged-PR output state by deriving it from `pull_request.merged_at` in test fixtures.
2026-05-13 02:55:30 +02:00
Can Bölük f72e7ddbea Merge branch 'main' into feat/plan-mode-approve-compact-context 2026-05-13 02:46:59 +02:00
can1357 efad62e808 Merge PR #1033: feat(skill-command): route /skill:* through the submission keybinding
Slash skill invocations bypassed the Enter / Ctrl+Enter contract that
every other slash command honors. Now Enter steers, Ctrl+Enter queues
a follow-up, sharing one #invokeSkillCommand helper between the editor
submit handler and handleFollowUp. Compaction short-circuit ordering
preserved.

Closes #1033
2026-05-13 02:32:52 +02:00
can1357 74b65957c0 fix(coding-agent): restore CHANGELOG historical sections clobbered by #998 merge
PR #998's branch was rebased on stale main and its CHANGELOG conflict
resolution dropped the immutable [14.9.8] and parts of [14.9.7]
released sections. Restore them and keep only the new credential_disabled
bullet PR #998 actually contributes under [Unreleased]/Added.
2026-05-13 02:31:12 +02:00
can1357 3fc8cfc444 Merge PR #998: feat(ai,coding-agent): credential_disabled extension event via multi-subscriber AuthStorage
Converts AuthStorage from a single-subscriber to multi-subscriber model
so the SDK and extensions can both observe credential changes without
clobbering each other, and emits a new credential_disabled event when
storage permanently rejects a credential. Lets extensions prompt
re-auth instead of silently failing the next call.

Reconciliation + mismatch rejection covered for both the SDK and
runSubprocess paths.

Closes #998
2026-05-13 02:29:03 +02:00
can1357 b0f115a56f Merge PR #1026: fix(tools): resolve internal URLs in find tool before filesystem path lookup
Mirrors the existing InternalUrlRouter pre-pass from search/ast-edit/
ast-grep so the find tool resolves session-scoped scheme URLs (local,
skill, agent, memory, etc.) to their backing filesystem paths before
fast-grep runs. Without this, the model passing literal scheme URLs as
paths to find hit ENOENT.

Glob patterns mixed with scheme URLs and URLs without a backing file
raise explicit ToolError instead of silently failing.

Closes #1026
2026-05-13 02:28:54 +02:00
can1357 34af4e9c95 Merge PR #994: feat(coding-agent): add rpc-ui mode with tool UI context over RPC protocol
Adds an rpc-ui mode that shuttles tool-UI context over the existing RPC
channel, sharing one RpcExtensionUIContext between the tool store and
the extension runner so extension_ui_response routing stays correct.
Forces PI_NO_PTY=1 in this mode to avoid PTY bash crashes.

Closes #994
2026-05-13 02:26:28 +02:00
can1357 a6f80d6a86 Merge PR #1024: feat(coding-agent): return JS eval final expressions
Rewrites the final top-level expression statement to a runtime hook so
its value surfaces without an explicit return/display, while preserving
top-level binding lifetime across cells. Promise-valued and thenable
finals are awaited exactly once; import-only cells stay silent.

Closes #1024
2026-05-13 02:25:04 +02:00
jiwangyihao 56428618c2 fix(js-eval): 不捕获改写后的 import 表达式 2026-05-13 02:24:10 +02:00
jiwangyihao 370fda14ff fix(js-eval): 使用私有最终表达式槽 2026-05-13 02:24:10 +02:00
jiwangyihao 7855028814 fix(js-eval): 仅在重写后读取最终表达式标记 2026-05-13 02:24:10 +02:00
jiwangyihao 51234ad929 fix(js-eval): 忽略继承的最终表达式标记 2026-05-13 02:24:10 +02:00
jiwangyihao 1b0ed01d32 fix(coding-agent): 解析所有最终 Promise 表达式 2026-05-13 02:24:10 +02:00
jiwangyihao efbf6b3833 fix(coding-agent): 等待最终 Promise 表达式 2026-05-13 02:24:10 +02:00
jiwangyihao 3af9369536 fix(coding-agent): 保留 JS eval 顶层绑定 2026-05-13 02:24:10 +02:00
jiwangyihao c270e966ba feat(coding-agent): 返回 JS eval 最终表达式 2026-05-13 02:24:10 +02:00
David Marshall 6872a73977 feat(ai,coding-agent): credential_disabled extension event via multi-subscriber AuthStorage
Adds `pi.on("credential_disabled", handler)` so extensions can react to
soft-disabled credentials (e.g. OAuth invalid_grant) without regex-matching
`agent_end` errorMessages.

`AuthStorage.onCredentialDisabled(listener)` returns an unsubscribe function;
multiple listeners fire for every event with per-listener exception isolation
and FIFO buffer-and-replay (cap 32) when none are attached. The constructor
option from #991 stays as sugar for an immediate permanent subscription.

`createAgentSession()` subscribes the per-session extension runner to
`modelRegistry.authStorage` immediately after resolution and unsubscribes on
dispose / startup failure. Events are forwarded via
`ExtensionRunner.emitCredentialDisabled(event)`, which buffers (cap 32,
drop-oldest) until `runner.initialize(...)` runs in the mode controller so
extension handlers see real UI/runtime context, not the constructor no-op
defaults.

Supersedes #997. Builds on #991.

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-13 02:18:57 +02:00
Miroslav Drbal 11dbfafd44 fix(coding-agent): disable PTY bash in rpc-ui mode
rpc-ui sets hasUI=true which causes the bash tool to take the
runInteractiveBashPty path when pty=true. RpcExtensionUIContext.custom()
is a stub returning undefined, so result.cancelled dereferences undefined
and throws. PTY bash requires a live TUI overlay; rpc-ui only provides
dialog-style UI. Set PI_NO_PTY for rpc-ui so the usePty guard in
bash.ts stays false.
2026-05-13 02:18:57 +02:00
Miroslav Drbal 68627b0857 feat(coding-agent): add rpc-ui mode with tool UI context over RPC protocol
Adds a new `rpc-ui` mode that extends the existing headless RPC mode with
interactive tool support (ask tool, extension UI dialogs, etc.).

In plain `rpc` mode the session has `hasUI=false` and no UI context is
wired, so interactive tools are disabled. `rpc-ui` mode sets `hasUI=true`
and wires a single shared `RpcExtensionUIContext` instance into both the
tool context store and the extension runner. Both consumers share the same
`pendingExtensionRequests` map and output closure, so `extension_ui_response`
messages received on stdin are routed to the correct waiting promise
regardless of which code path (tool or extension) created the request.

Changes:
- `args.ts`: add `rpc-ui` to the `Mode` union and the parse guard
- `launch.ts`: expose `rpc-ui` in the OCLIF flag definition and help text
- `main.ts`: propagate `rpc-ui` through all RPC-mode guard conditions and
  pass `setToolUIContext` to `runRpcMode` when the mode is `rpc-ui`
- `rpc-mode.ts`: accept optional `setToolUIContext` callback; create one
  shared `RpcExtensionUIContext` instance and pass it to both the tool
  context store and the extension runner
2026-05-13 02:18:57 +02:00
jiwangyihao 0f73414d3b fix(coding-agent): 识别顶层工具错误标记 2026-05-13 02:18:56 +02:00
jiwangyihao e043125e11 fix(coding-agent): 标记 JS eval 工具错误结果 2026-05-13 02:18:56 +02:00
metaphorics a4258cfc2c feat(skill-command): route /skill:* through the submission keybinding
Makes `/skill:<name> [args]` work identically under both submission
keybindings, mirroring how free text is already routed during streaming:

- `/skill:foo` + Enter, streaming     -> steer queue (interrupt)
- `/skill:foo` + Ctrl+Enter, streaming -> followUp queue
- `/skill:foo` + Enter, idle           -> idle prompt
- `/skill:foo` + Ctrl+Enter, idle      -> idle prompt (was: literal text)

A single private helper `#invokeSkillCommand(text, streamingBehavior)`
on `InputController` handles the dispatch; the Enter submit handler
calls it with "steer", and `handleFollowUp` calls it with "followUp"
after the compaction short-circuit so a skill typed during compaction
rides the same `queueCompactionMessage` queue as free text.

Behavior deltas vs upstream/main:
- Enter on `/skill:foo` during streaming now steers (was: queued as
  followUp). Users who relied on the followUp default can press
  Ctrl+Enter -- the same key they already use for free-text follow-ups.
- Ctrl+Enter on `/skill:foo` is new capability; previously the
  literal string `/skill:foo ...` was sent as plain followUp text and
  the skill was never invoked.

Op: extend
2026-05-13 02:18:55 +02:00
Miroslav Drbal d43300250d fix(tools): resolve internal URLs in find tool before filesystem path lookup 2026-05-13 02:18:55 +02:00
can1357 6d16e93b86 test(coding-agent): align issue-1011 test with isCompiledBinary hybrid contract
The asset-emission assertion was the false positive flagged in
tab-supervisor.ts: the new pattern intentionally does not bundle the
worker as an asset of the supervisor — it is added as a separate
`--compile` entrypoint in build-binary.ts, and runtime is covered by
`omp --smoke-test` (sync worker).

Replaces it with two cheap static checks that defend the two halves
that actually make the worker survive `bun build --compile`:
1. tab-supervisor.ts branches on `isCompiledBinary()` and uses the
   exact `--root`-relative literal at the `new Worker(...)` site
   that Bun's `--compile` analyzer can discover, while keeping the
   `new URL("./tab-worker-entry.ts", import.meta.url)` branch for
   dev/source spawns.
2. scripts/build-binary.ts lists the same worker as an explicit
   additional `--compile` entrypoint so Bun emits it into bunfs.
2026-05-13 01:56:18 +02:00
cognitive 29213228ef chore(coding-agent): note compact-context approval choice in changelog
[Unreleased] → Added entries for both the new "Approve and compact
context" ExitPlanMode selector choice and the underlying typed
`CompactionCancelledError` + `CompactionOutcome` plumbing.

Op: extend
2026-05-12 23:01:41 +00:00
cognitive 736ec807a5 test(coding-agent/plan-mode): cover compact-then-execute approval path
- Extend the existing selector-list assertion to include the new
  "Approve and compact context" entry in the expected five-choice array.
- Add three new cases that mock `handleCompactCommand` at the
  CompactionOutcome boundary (the contract `#approvePlan` consumes):
  - "ok" → asserts compactSpy called with the planning-specific
    custom instruction rendered from `plan-mode-compact-instructions.md`
    (matched by content: "Preparing to execute the approved plan" +
    the final plan file path); plan-approved synthetic prompt dispatched
    (discriminated by the `{ synthetic: true }` option flag);
    `markPlanReferenceSent` called once.
  - "cancelled" → no synthetic dispatch; `showWarning` surfaces the
    deferred-dispatch message; `setPlanReferencePath` IS called with the
    final path so the session knows the plan was approved; but
    `markPlanReferenceSent` is NOT called so the next operator turn
    re-injects the reference via #buildPlanReferenceMessage. This last
    assertion is the load-bearing regression guard for the asymmetric
    cancel/fail contract.
  - "failed" → plan-approved synthetic prompt IS dispatched
    (best-effort); markPlanReferenceSent fires.

Per AGENTS.md the tests use `vi.spyOn` + `vi.restoreAllMocks()` in
the existing afterEach; no `mock.module()`.

Op: extend
2026-05-12 23:01:31 +00:00
cognitive 0eb8d0fdcd feat(coding-agent/plan-mode): add "Approve and compact context" approval choice
A fifth ExitPlanMode approval choice — sits between the existing
"Approve and execute" (purge session) and "Approve and keep context"
(full transcript). Runs `handleCompactCommand` against the plan-mode
transcript with a planning-specific custom instruction rendered from
`plan-mode-compact-instructions.md`, then dispatches the plan-approved
synthetic prompt so it lands as the first entry in the freshly-
summarized transcript — giving execution a fresh cache anchor with
the rationale carried over.

Cancel/fail contract:
- ok       → bookkeeping runs, plan-approved synthetic prompt dispatched.
- cancelled → bookkeeping runs (tools restored, plan reference path
              recorded), warning surfaced, dispatch skipped.
              `markPlanReferenceSent` is intentionally deferred past
              the cancel guard so `AgentSession.#buildPlanReferenceMessage`
              re-injects the plan on the operator's next prompt() call.
              If we marked it sent on cancel, the executor's first turn
              would have no plan context.
- failed   → bookkeeping runs, error already surfaced by executeCompaction,
             dispatch proceeds best-effort. Approval intent stands.

Cancel vs. fail is discriminated via `instanceof CompactionCancelledError`
at the session/compaction error boundary (introduced in the previous
commit), so any abort source — operator Esc, extension hook, programmatic
abort — classifies uniformly without input-modality or message-string
coupling.

Op: extend
2026-05-12 23:01:06 +00:00
cognitive bad4c133e7 feat(coding-agent/session): typed CompactionCancelledError sentinel and CompactionOutcome
Introduce `CompactionCancelledError` and `CompactionOutcome` ("ok" |
"cancelled" | "failed") so callers can discriminate user-driven aborts
from generic failures via `instanceof`, instead of inspecting error
messages or `AbortError`-name strings.

`AgentSession.compact()`'s two abort-rejection sites now throw the
typed sentinel; the model-call wrapper normalizes AbortError-shaped
rejections to the sentinel only when the compaction's abort signal
is actually set, preserving every other exception unchanged so real
compaction bugs are not silently relabeled as cancellations.

`CommandController.executeCompaction` and `handleCompactCommand`
return `Promise<CompactionOutcome>`; the catch classifies via
`instanceof CompactionCancelledError`. Existing callers (`/compact`,
loop runner, auto-compact) ignore the return value — non-breaking.

Op: extend
2026-05-12 22:58:27 +00:00
can1357 ce045f02a2 chore: bump version to 14.9.9 2026-05-12 16:42:51 +02:00
can1357 b468bd5abd feat(stats): show input and output token totals 2026-05-12 16:40:43 +02:00
can1357 1cb451a071 fix(workers): replaced file-URL import pattern with compiled-binary-aware spawn
- Replaced `with { type: "file" }` worker imports with `isCompiledBinary()` hybrid: literal string for `--compile` static analysis, `new URL(import.meta.url)` for dev portability.
- Added worker entrypoints as explicit `--compile` args in `build-binary.ts` so Bun emits them into bunfs.
- Added `smokeTestSyncWorker` and `omp --smoke-test` to catch silent worker-load failures in compiled binaries (fixes #1011, #1027).
- Added `isCompiledBinary()` utility to `@oh-my-pi/pi-utils` detecting bunfs path markers.
2026-05-12 16:40:15 +02:00
can1357 6fbb93b017 fix(coding-agent): allowed hashline parsing to accept flexible @@ section headers
- Updated hashline section parsing to accept headers with any leading `@` characters, normalizing them to the path before validation.
- Updated the hashline grammar and fallback errors to use canonical `@@ PATH` section headers.
- Added coverage for mixed `@@` and `@@@` headers across multiple file sections in hashline parsing tests.
2026-05-12 14:40:42 +02:00