@oh-my-pi/pi-coding-agent 15.10.3 → 15.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/dist/types/capability/rule-buckets.d.ts +1 -1
  3. package/dist/types/capability/rule.d.ts +6 -1
  4. package/dist/types/cli/update-cli.d.ts +11 -1
  5. package/dist/types/config/model-registry.d.ts +18 -1
  6. package/dist/types/discovery/at-imports.d.ts +15 -0
  7. package/dist/types/edit/diff.d.ts +3 -2
  8. package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +1 -0
  9. package/dist/types/eval/__tests__/js-context-manager.test.d.ts +1 -0
  10. package/dist/types/eval/backend.d.ts +7 -0
  11. package/dist/types/eval/bridge-timeout.d.ts +1 -1
  12. package/dist/types/eval/{llm-bridge.d.ts → completion-bridge.d.ts} +8 -8
  13. package/dist/types/eval/idle-timeout.d.ts +1 -1
  14. package/dist/types/eval/js/context-manager.d.ts +1 -0
  15. package/dist/types/eval/js/executor.d.ts +2 -0
  16. package/dist/types/eval/js/index.d.ts +1 -1
  17. package/dist/types/eval/js/shared/helpers.d.ts +6 -0
  18. package/dist/types/eval/js/shared/runtime.d.ts +5 -0
  19. package/dist/types/eval/js/worker-protocol.d.ts +6 -0
  20. package/dist/types/eval/py/executor.d.ts +7 -0
  21. package/dist/types/eval/py/index.d.ts +1 -1
  22. package/dist/types/export/ttsr.d.ts +14 -0
  23. package/dist/types/extensibility/extensions/types.d.ts +8 -1
  24. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +1 -1
  25. package/dist/types/internal-urls/local-protocol.d.ts +10 -0
  26. package/dist/types/mcp/oauth-flow.d.ts +2 -2
  27. package/dist/types/modes/components/custom-editor.d.ts +3 -0
  28. package/dist/types/modes/components/{status-line.d.ts → status-line/component.d.ts} +2 -32
  29. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  30. package/dist/types/modes/components/status-line/types.d.ts +31 -2
  31. package/dist/types/modes/image-references.d.ts +8 -3
  32. package/dist/types/modes/interactive-mode.d.ts +1 -1
  33. package/dist/types/modes/theme/theme.d.ts +2 -1
  34. package/dist/types/modes/types.d.ts +2 -1
  35. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  36. package/dist/types/session/agent-session.d.ts +0 -2
  37. package/dist/types/tools/ask.d.ts +1 -0
  38. package/dist/types/tools/browser/tab-worker.d.ts +15 -0
  39. package/dist/types/tools/index.d.ts +17 -0
  40. package/dist/types/tools/render-utils.d.ts +1 -1
  41. package/dist/types/tools/tool-timeouts.d.ts +1 -1
  42. package/dist/types/utils/block-context.d.ts +35 -0
  43. package/dist/types/utils/image-loading.d.ts +12 -0
  44. package/package.json +29 -9
  45. package/src/capability/rule-buckets.ts +4 -2
  46. package/src/capability/rule.ts +10 -1
  47. package/src/cli/auth-broker-cli.ts +6 -7
  48. package/src/cli/auth-gateway-cli.ts +1 -1
  49. package/src/cli/list-models.ts +5 -0
  50. package/src/cli/update-cli.ts +138 -16
  51. package/src/config/model-registry.ts +81 -2
  52. package/src/debug/index.ts +4 -8
  53. package/src/discovery/at-imports.ts +273 -0
  54. package/src/discovery/builtin-rules/index.ts +4 -0
  55. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  56. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  57. package/src/discovery/helpers.ts +2 -1
  58. package/src/edit/diff.ts +114 -4
  59. package/src/edit/hashline/diff.ts +1 -1
  60. package/src/edit/hashline/execute.ts +1 -1
  61. package/src/edit/modes/patch.ts +6 -2
  62. package/src/edit/modes/replace.ts +1 -1
  63. package/src/edit/renderer.ts +12 -2
  64. package/src/eval/__tests__/agent-bridge.test.ts +13 -0
  65. package/src/eval/__tests__/{llm-bridge.test.ts → completion-bridge.test.ts} +60 -54
  66. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  67. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  68. package/src/eval/agent-bridge.ts +6 -1
  69. package/src/eval/backend.ts +15 -0
  70. package/src/eval/bridge-timeout.ts +1 -1
  71. package/src/eval/{llm-bridge.ts → completion-bridge.ts} +30 -27
  72. package/src/eval/idle-timeout.ts +1 -1
  73. package/src/eval/js/context-manager.ts +70 -8
  74. package/src/eval/js/executor.ts +3 -0
  75. package/src/eval/js/index.ts +7 -1
  76. package/src/eval/js/shared/helpers.ts +53 -6
  77. package/src/eval/js/shared/prelude.txt +4 -4
  78. package/src/eval/js/shared/runtime.ts +8 -0
  79. package/src/eval/js/tool-bridge.ts +3 -3
  80. package/src/eval/js/worker-core.ts +1 -0
  81. package/src/eval/js/worker-entry.ts +6 -0
  82. package/src/eval/js/worker-protocol.ts +6 -0
  83. package/src/eval/py/executor.ts +12 -0
  84. package/src/eval/py/index.ts +7 -1
  85. package/src/eval/py/prelude.py +46 -7
  86. package/src/eval/py/runner.py +1 -0
  87. package/src/exa/render.ts +1 -1
  88. package/src/export/ttsr.ts +122 -1
  89. package/src/extensibility/extensions/types.ts +8 -1
  90. package/src/extensibility/legacy-pi-ai-shim.ts +1 -1
  91. package/src/extensibility/plugins/doctor.ts +1 -1
  92. package/src/extensibility/plugins/legacy-pi-compat.ts +6 -5
  93. package/src/goals/tools/goal-tool.ts +1 -1
  94. package/src/internal-urls/docs-index.generated.ts +8 -6
  95. package/src/internal-urls/local-protocol.ts +13 -0
  96. package/src/lsp/render.ts +8 -6
  97. package/src/mcp/oauth-flow.ts +3 -3
  98. package/src/mcp/render.ts +7 -1
  99. package/src/modes/components/custom-editor.ts +12 -6
  100. package/src/modes/components/login-dialog.ts +1 -1
  101. package/src/modes/components/oauth-selector.ts +4 -4
  102. package/src/modes/components/read-tool-group.ts +10 -3
  103. package/src/modes/components/{status-line.ts → status-line/component.ts} +18 -40
  104. package/src/modes/components/status-line/index.ts +1 -0
  105. package/src/modes/components/status-line/types.ts +23 -8
  106. package/src/modes/components/tips.txt +1 -1
  107. package/src/modes/components/tool-execution.ts +1 -1
  108. package/src/modes/components/transcript-container.ts +17 -10
  109. package/src/modes/components/user-message.ts +6 -3
  110. package/src/modes/components/welcome.ts +1 -1
  111. package/src/modes/controllers/extension-ui-controller.ts +143 -127
  112. package/src/modes/controllers/input-controller.ts +36 -10
  113. package/src/modes/controllers/mcp-command-controller.ts +28 -12
  114. package/src/modes/controllers/selector-controller.ts +4 -11
  115. package/src/modes/controllers/ssh-command-controller.ts +2 -2
  116. package/src/modes/image-references.ts +13 -7
  117. package/src/modes/interactive-mode.ts +2 -2
  118. package/src/modes/rpc/rpc-mode.ts +1 -1
  119. package/src/modes/setup-wizard/scenes/sign-in.ts +3 -11
  120. package/src/modes/theme/theme.ts +95 -1
  121. package/src/modes/types.ts +2 -1
  122. package/src/modes/utils/ui-helpers.ts +14 -5
  123. package/src/prompts/system/tiny-title-system.md +1 -1
  124. package/src/prompts/system/title-system.md +16 -3
  125. package/src/prompts/system/workflow-notice.md +1 -1
  126. package/src/prompts/tools/bash.md +1 -1
  127. package/src/prompts/tools/eval.md +6 -6
  128. package/src/sdk.ts +31 -14
  129. package/src/session/agent-session.ts +213 -155
  130. package/src/session/session-manager.ts +1 -1
  131. package/src/slash-commands/builtin-registry.ts +1 -1
  132. package/src/system-prompt.ts +15 -9
  133. package/src/task/render.ts +20 -8
  134. package/src/tools/ask.ts +14 -5
  135. package/src/tools/bash-interactive.ts +1 -1
  136. package/src/tools/bash.ts +14 -2
  137. package/src/tools/browser/render.ts +5 -2
  138. package/src/tools/browser/tab-worker.ts +211 -91
  139. package/src/tools/debug.ts +5 -2
  140. package/src/tools/eval-render.ts +8 -5
  141. package/src/tools/eval.ts +2 -2
  142. package/src/tools/gh-renderer.ts +29 -15
  143. package/src/tools/index.ts +32 -0
  144. package/src/tools/inspect-image-renderer.ts +12 -5
  145. package/src/tools/job.ts +9 -6
  146. package/src/tools/memory-render.ts +19 -5
  147. package/src/tools/read.ts +165 -18
  148. package/src/tools/render-utils.ts +3 -1
  149. package/src/tools/resolve.ts +1 -1
  150. package/src/tools/review.ts +1 -1
  151. package/src/tools/ssh.ts +4 -1
  152. package/src/tools/todo.ts +8 -1
  153. package/src/tools/tool-timeouts.ts +1 -1
  154. package/src/tools/write.ts +1 -1
  155. package/src/tui/code-cell.ts +1 -1
  156. package/src/utils/block-context.ts +312 -0
  157. package/src/utils/image-loading.ts +31 -1
  158. package/src/utils/title-generator.ts +2 -2
  159. package/src/web/search/providers/codex.ts +1 -1
  160. package/src/web/search/render.ts +14 -6
  161. /package/dist/types/eval/__tests__/{llm-bridge.test.d.ts → completion-bridge.test.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,78 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.5] - 2026-06-08
6
+
7
+ ### Added
8
+
9
+ - Added Homebrew and mise package-manager update paths to the self-update command so installations launched from those tools are updated through their native workflows
10
+ - Added detection of Homebrew and mise install locations so self-update chooses the manager-specific updater when the active `omp` binary comes from a package-manager-managed path
11
+ - Added `astCondition` to TTSR rule frontmatter as a syntax-aware alternative to regex `condition`, enabling AST-based matching for edit/write tool snapshots
12
+ - Added a built-in `ts-redundant-clear-guard` rule that flags redundant guards around `clearTimeout`, `clearInterval`, and `clearImmediate` calls
13
+ - Added a built-in `ts-no-test-timers` rule that flags real timers (`Bun.sleep`, `setTimeout`, `setInterval`) in `*.test.ts` files, steering toward fake timers (`vi.useFakeTimers()` / `vi.advanceTimersByTime()`)
14
+ - Added support for paste marker highlighting with accent styling (`[Paste #N, +X lines]`/`[Paste #N, Y chars]`) in the prompt editor, matching the visual treatment of image references
15
+ - Added pixel dimensions to pasted/loaded image placeholders in the prompt — the marker now reads `[Image #N, WxH]` (falling back to `[Image #N]` when the header can't be decoded).
16
+ - The bundled shell now treats `nohup` as a builtin: `nohup … &` runs the command without masking `SIGHUP` or detaching it, so agent-started daemons stay tied to this agent's lifetime instead of leaking as orphans when the agent exits. Updated the bash tool prompt's daemon guidance to match (dropped the `nohup … & / setsid … & / disown` detach recommendation in favor of a large `timeout` plus the persistent session).
17
+ - Added per-tool `tool.*` theme symbol keys (nerd/unicode/ascii presets) plus a quiet `status.done` glyph, so each tool's result header can carry a signature icon instead of a generic status mark
18
+
19
+ ### Changed
20
+
21
+ - Updated pi-ai OAuth imports to the renamed `@oh-my-pi/pi-ai/oauth` subpath (was `@oh-my-pi/pi-ai/utils/oauth`) across the login UI, MCP OAuth flow, model registry, setup wizard, and web-search Codex auth. The legacy-plugin specifier shim drops its `pi-ai/oauth` → `pi-ai/utils/oauth` subpath rewrite, since the canonical `@oh-my-pi/pi-ai/oauth` export now resolves directly.
22
+ - Changed forced self-updates for Homebrew installs to run `brew reinstall` and for mise installs to run `mise install --force` after `mise upgrade` when `--force` is requested
23
+ - Changed TTSR rule bucketing and matching so rules with only `astCondition` are treated as TTSR rules and evaluated in the interrupt flow using reconstructed edit/write source snapshots
24
+ - Normalized image content before it enters model context so attached images are downscaled and preprocessed for prompts, steering messages, follow-ups, and custom agent messages
25
+ - Changed image marker format to include pixel dimensions when available (`[Image #N, WxH]`), falling back to bare `[Image #N]` when header cannot be decoded
26
+ - Changed the prompt editor to highlight large-paste placeholders (`[Paste #N, +X lines]`/`[Paste #N, Y chars]`) with the same accent styling as image references (bold, no hyperlink), and to delete image/paste markers atomically: a single backspace or forward-delete removes the whole marker instead of leaving a broken `[Paste #N, +X lines` behind.
27
+ - Browser tool helpers (`tab.*`) are now individually tracked and time-bounded: when a `run` cell hits its budget, the timeout error names the still-running helper(s) and how long each has been stalled (e.g. `... (stalled on tab.screenshot({ selector: ".x" }) (29.9s))`) instead of the opaque `Browser code execution timed out after 30000ms`. Page-coupled helpers that should resolve quickly (`observe`, `screenshot`, `extract`) also fail fast with a named per-op error at `min(cellBudget, 20s)`, leaving budget for the rest of the cell, rather than silently consuming the whole budget.
28
+ - Derived the auth-broker OAuth callback ports (`CALLBACK_PORTS`) and the paste-code login-provider set from the `@oh-my-pi/pi-ai` provider registry, removing the duplicated `CALLBACK_SERVER_PROVIDERS` tables in the model selector and the setup-wizard sign-in scene.
29
+ - Raised the `eval` tool's per-cell `timeout` ceiling from 600s to 3600s (matching `bash`), in both the Zod schema and the `TOOL_TIMEOUTS.eval` runtime clamp, so heavy local-compute cells can request budgets above 10 minutes.
30
+ - Derived the auth-broker OAuth callback ports (`CALLBACK_PORTS`) and the paste-code login-provider set from the `@oh-my-pi/pi-ai` provider registry, removing the duplicated `CALLBACK_SERVER_PROVIDERS` tables in the model selector and the setup-wizard sign-in scene.
31
+ - Reworked tool result-header glyphs to cut the overused success checkmark/dot: each tool now shows its own signature icon on success (terminal for bash, pencil for edit, magnifier/globe for search, plug for MCP, etc.; read keeps the read-group status dot), tools without a custom renderer fall back to a quiet `status.done` dot, and error/warning/pending states keep the universal cross/warning/spinner
32
+ - Changed steady-state health indicators (LSP server ready, OAuth logged-in, plugin-doctor checks) from a success checkmark to a colored `status.enabled` dot, so failures stand out instead of every line reading as a check
33
+ - Changed one-shot MCP/SSH/debug confirmation messages from a generic checkmark to contextual action glyphs (add/remove, connect/enable/disable toggles, reload, job-completed), reflecting what happened rather than just "success"
34
+ - Derived the auth-broker OAuth callback ports (`CALLBACK_PORTS`) and the paste-code login-provider set from the `@oh-my-pi/pi-ai` provider registry, removing the duplicated `CALLBACK_SERVER_PROVIDERS` tables in the model selector and the setup-wizard sign-in scene.
35
+
36
+ ### Fixed
37
+
38
+ - Fixed package subpath exports for status-line, setup-wizard, tool-discovery, and gallery fixture modules so rewritten test imports resolve through `@oh-my-pi/pi-coding-agent`.
39
+ - Fixed runtime model provider discovery so extension-registered providers are now refreshed after extension load and extension-supplied models appear without restarting
40
+ - Fixed task-row shimmer timing so every running description starts its highlight on the first character together and reaches the last character together, regardless of text length.
41
+ - Fixed the `eval` tool's `read`/`write`/`append` helpers (both Python and JS backends) treating `local://` (and other internal-URL) paths as plain filesystem paths. `pathlib.Path`/`path.resolve` collapse `local://x.md` to `local:/x.md`, so `write("local://x.md", …)` created a junk `local:` directory under the cwd instead of writing where `read local://x.md` resolves. The helpers now substitute injected on-disk roots for known schemes (currently `local://`, pinned to the session's own `local://` root), reject path traversal and unknown `scheme://` paths, and leave plain paths resolving against the cwd.
42
+ - Fixed read and edit previews to surface the enclosing syntactic block's off-window boundary line (behind an ellipsis) when a shown line opens or closes a block whose other end falls outside the displayed range. Powered by a new tree-sitter `enclosingBlockBoundaries` native, so it covers brace languages and indentation languages (Python) using real syntactic spans, with a lexical bracket scan as fallback for unparseable sources.
43
+ - Fixed `tab.screenshot({ selector })` hanging for the entire cell budget on continuously-animating pages (WebGL / `backdrop-filter` "glass" effects). The element-screenshot path no longer routes through puppeteer's `scrollIntoViewIfNeeded()`, whose `IntersectionObserver` promise can stall indefinitely under heavy rendering; it now does a single instant `scrollIntoView` and captures with `scrollIntoView: false` (relying on `captureBeyondViewport`), so off-screen elements are still captured without the stall.
44
+ - Fixed follow-up message submissions to forward pending clipboard-pasted images to `session.prompt` in both streaming and non-streaming flows
45
+ - Fixed follow-up handling to clear consumed clipboard image state after submission so pasted images are not silently carried into later messages
46
+ - Fixed clipboard-pasted images being rejected when steering or following up during compaction. Instead of bailing with "Retry after it completes to send images", the message and its images are now queued via `queueCompactionMessage` and forwarded to the session (steer/follow-up/prompt) when the compaction queue flushes.
47
+ - Fixed edit tool result previews to show only current-file lines and collapse long inserted blocks instead of echoing removed content.
48
+ - Fixed `generateDiffString` to omit the mid-skip `...` placeholder between two nearby edits, conveying the elided gap via the jump in line numbers instead (consistent with how leading/trailing context skips already render). The placeholder row was indistinguishable from a genuine `...` context line and wasted a row in compact previews.
49
+ - Fixed concurrent interactive dialogs clobbering each other on the shared editor surface. `ExtensionUiController` presents the selector / input / editor modals by swapping a component into the single `editorContainer` and stealing focus, with no serialization — so a second `select`/`input`/`editor` request (from a hook, extension, the `ask` tool, or an internal flow) opened while one was already up would clear the container and re-focus, orphaning the first dialog. Its promise then hung until the caller's signal aborted (surfacing a stray `Ask input was cancelled` on top of the answered call). These modals are now serialized through `#presentDialog`: at most one shows at a time and the rest queue (FIFO); a queued request whose signal aborts before its turn resolves `undefined` and is never shown. The first dialog is still presented synchronously, so single-dialog timing is unchanged.
50
+ - Fixed the `ask` tool potentially hanging when the model emitted two `ask` calls in one tool batch. `ask` now declares `concurrency: "exclusive"`, so the agent loop serializes the batch and each question's selector runs to completion before the next starts, instead of racing for the shared selector surface.
51
+ - Expanded `@path/to/file` import references in CLAUDE.md / AGENTS.md / GEMINI.md (and the other discovered context-file flavors) when loading them into the system prompt, matching the convention used by Claude Code, Goose, and other agents. Imports resolve relative to the importing file's directory, support `~/...`, recurse up to 5 hops, and are skipped inside fenced code blocks and inline code spans so technical examples like `npm install @types/node` survive intact ([#2111](https://github.com/can1357/oh-my-pi/issues/2111)).
52
+
53
+ ### Removed
54
+
55
+ - Removed the special Anthropic `claude-opus-4-8` tool-call batch cap; sessions no longer abort an in-flight provider stream after a fixed number of completed tool calls.
56
+
57
+ ## [15.10.4] - 2026-06-08
58
+
59
+ ### Added
60
+
61
+ - macOS release binaries are now signed with a Developer ID Application identity (hardened runtime + secure timestamp + JIT/library-validation entitlements) and notarized in CI when the `APPLE_*` signing secrets are configured; releases auto-fall back to ad-hoc signing until then. This makes the shipped binaries Gatekeeper-acceptable, unblocking an official Homebrew submission ([#776](https://github.com/can1357/oh-my-pi/issues/776)). See `docs/macos-signing-notarization.md`.
62
+ - Added a Homebrew install path: `brew install can1357/tap/omp`. The [can1357/homebrew-tap](https://github.com/can1357/homebrew-tap) formula installs the prebuilt release binary, and a `release_brew` CI job regenerates it (version + per-asset sha256) from each published release via `scripts/ci-update-brew-formula.ts` ([#776](https://github.com/can1357/oh-my-pi/issues/776)).
63
+
64
+ ### Changed
65
+
66
+ - Adjusted `completion()` model resolution so the `default` tier now prefers the session’s active model and falls back to the configured default role when needed
67
+ - Rewrote the session auto-title prompt (`prompts/system/title-system.md`) and the `set_title` tool description to ask for a concise, sentence-case title (3-7 words) that captures the session's topic/goal, with good/bad examples and explicit guidance to treat the first message as data (no following embedded links/instructions, no refusals, describe URL/reference asks). The local on-device title prompt (`tiny-title-system.md`) was aligned to the same 3-7 word, sentence-case convention. The deterministic greeting/low-signal filter and the `none` deferral sentinel are unchanged.
68
+ - Renamed the eval oneshot helper from `llm()` to `completion()` in both JavaScript and Python preludes, including status events, prompt docs, and runtime tests.
69
+
70
+ ### Fixed
71
+
72
+ - Fixed `completion()` to always send a non-empty default system prompt when `system` is omitted so providers that require instructions no longer reject requests
73
+ - Fixed structured `completion()` mode to return parsed JSON from plain text output when the model skips the forced `respond` tool call
74
+ - Fixed slow-tier `completion()` reasoning requests to avoid unsupported effort settings by only enabling reasoning on reasoning-capable models and capping effort to supported levels
75
+ - Fixed JS eval worker reset/dispose to close workers gracefully before forced termination, avoiding Bun 1.3.14 N-API teardown crashes with native modules such as `canvas`.
76
+
5
77
  ## [15.10.3] - 2026-06-08
6
78
 
7
79
  ### Added
@@ -6,7 +6,7 @@
6
6
  * manager, and splits the rest into the always-apply and rulebook buckets.
7
7
  *
8
8
  * Bucket precedence (matches docs/rulebook-matching-pipeline.md §5):
9
- * 1. TTSR — non-empty `condition` that `TtsrManager.addRule` accepts
9
+ * 1. TTSR — non-empty `condition`/`astCondition` that `TtsrManager.addRule` accepts
10
10
  * 2. always — `alwaysApply === true`
11
11
  * 3. rulebook — has a `description`
12
12
  */
@@ -15,6 +15,8 @@ export interface RuleFrontmatter {
15
15
  alwaysApply?: boolean;
16
16
  /** New key for TTSR match conditions. */
17
17
  condition?: string | string[];
18
+ /** TTSR match condition(s) expressed as ast-grep patterns (edit/write streams only). */
19
+ astCondition?: string | string[];
18
20
  /** New key for TTSR stream scope. */
19
21
  scope?: string | string[];
20
22
  /** Per-rule TTSR interrupt mode override. */
@@ -39,6 +41,8 @@ export interface Rule {
39
41
  description?: string;
40
42
  /** Regex condition(s) that can trigger TTSR interruption. */
41
43
  condition?: string[];
44
+ /** ast-grep pattern condition(s) that can trigger TTSR interruption (edit/write streams only). */
45
+ astCondition?: string[];
42
46
  /** Optional stream scope tokens (for example: text, thinking, tool:edit(*.ts)). */
43
47
  scope?: string[];
44
48
  /** Per-rule TTSR interrupt mode override (falls back to global ttsr.interruptMode). */
@@ -54,8 +58,9 @@ export interface Rule {
54
58
  * - legacy `ttsr_trigger` / `ttsrTrigger` are accepted as a `condition` fallback
55
59
  * - condition tokens that look like file globs become scope shorthands:
56
60
  * `*.rs` => `tool:edit(*.rs)`, `tool:write(*.rs)` and a catch-all condition `.*`
61
+ * - `astCondition` holds ast-grep patterns and is kept verbatim (no glob inference)
57
62
  */
58
- export declare function parseRuleConditionAndScope(frontmatter: RuleFrontmatter): Pick<Rule, "condition" | "scope">;
63
+ export declare function parseRuleConditionAndScope(frontmatter: RuleFrontmatter): Pick<Rule, "condition" | "astCondition" | "scope">;
59
64
  /**
60
65
  * Process-global snapshot of rules the active session loaded.
61
66
  * Read by internal URL protocol handlers (rule://).
@@ -20,7 +20,13 @@ export declare function parseUpdateArgs(args: string[]): {
20
20
  force: boolean;
21
21
  check: boolean;
22
22
  } | undefined;
23
- export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: string | undefined): "bun" | "binary";
23
+ type UpdateMethod = "brew" | "mise" | "bun" | "binary";
24
+ interface UpdateMethodResolutionOptions {
25
+ homebrewPrefix?: string;
26
+ miseBinDirs?: readonly string[];
27
+ miseDataDir?: string;
28
+ }
29
+ export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: string | undefined, options?: UpdateMethodResolutionOptions): UpdateMethod;
24
30
  /**
25
31
  * Atomically replace the installed binary and roll back if version verification fails.
26
32
  */
@@ -56,6 +62,9 @@ export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions
56
62
  * See #1824.
57
63
  */
58
64
  export declare function buildBunInstallArgs(expectedVersion: string, nativeTag?: string): string[];
65
+ export declare function buildHomebrewUpdateArgs(force: boolean): string[];
66
+ export declare function buildMiseUpgradeArgs(): string[];
67
+ export declare function buildMiseForceInstallArgs(expectedVersion: string): string[];
59
68
  /**
60
69
  * Run the update command.
61
70
  */
@@ -67,3 +76,4 @@ export declare function runUpdateCommand(opts: {
67
76
  * Print update command help.
68
77
  */
69
78
  export declare function printUpdateHelp(): void;
79
+ export {};
@@ -2,7 +2,7 @@ import { type ModelRefreshStrategy } from "@oh-my-pi/pi-ai/model-manager";
2
2
  import type { Api, Context, Model, SimpleStreamOptions, ThinkingConfig } from "@oh-my-pi/pi-ai/types";
3
3
  import type { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
4
4
  import type { ApiKeyResolver } from "@oh-my-pi/pi-ai";
5
- import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
5
+ import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
6
6
  import { type ThemeColor } from "../modes/theme/theme";
7
7
  import type { AuthStorage } from "../session/auth-storage";
8
8
  import { type ApiKeyResolverOptions } from "./api-key-resolver";
@@ -284,6 +284,16 @@ export declare class ModelRegistry {
284
284
  refresh(strategy?: ModelRefreshStrategy): Promise<void>;
285
285
  refreshInBackground(strategy?: ModelRefreshStrategy): void;
286
286
  refreshProvider(providerId: string, strategy?: ModelRefreshStrategy): Promise<void>;
287
+ /**
288
+ * Discover models for providers registered at runtime via `fetchDynamicModels`
289
+ * (extension providers). Merges the discovered catalog into the existing model
290
+ * set without reloading static models, so dynamically-discovered models from
291
+ * other providers are preserved. No-op when no runtime providers are registered.
292
+ *
293
+ * Drives the same SQLite model cache as built-in providers, so the default
294
+ * `online-if-uncached` strategy fetches at most once per cache TTL (24 h).
295
+ */
296
+ refreshRuntimeProviders(strategy?: ModelRefreshStrategy): Promise<void>;
287
297
  /**
288
298
  * Get any error from loading models.json (undefined if no error).
289
299
  */
@@ -399,6 +409,13 @@ export interface ProviderConfigInput {
399
409
  getApiKey?(credentials: OAuthCredentials): string;
400
410
  modifyModels?(models: Model<Api>[], credentials: OAuthCredentials): Model<Api>[];
401
411
  };
412
+ /**
413
+ * Async factory that fetches the live model list from the provider endpoint.
414
+ * When present, the result is run through the same SQLite model-cache as
415
+ * built-in providers (keyed by provider name, default 24 h TTL).
416
+ * The factory receives the resolved API key (undefined when unauthenticated).
417
+ */
418
+ fetchDynamicModels?: (apiKey: string | undefined) => Promise<readonly NonNullable<ProviderConfigInput["models"]>[number][]>;
402
419
  models?: Array<{
403
420
  id: string;
404
421
  name: string;
@@ -0,0 +1,15 @@
1
+ /** Maximum number of recursive `@`-import hops. Matches Claude Code's documented cap. */
2
+ export declare const MAX_AT_IMPORT_DEPTH = 5;
3
+ export interface ExpandAtImportsOptions {
4
+ /** Maximum hop depth (default: {@link MAX_AT_IMPORT_DEPTH}). */
5
+ maxDepth?: number;
6
+ /** Override the home directory used to resolve `~/...` (default: `os.homedir()`). */
7
+ home?: string;
8
+ }
9
+ /**
10
+ * Expand `@path/to/file` references in `content` against `filePath`'s directory.
11
+ *
12
+ * Returns the expanded text. When no imports match, the original string is
13
+ * returned unchanged.
14
+ */
15
+ export declare function expandAtImports(content: string, filePath: string, options?: ExpandAtImportsOptions): Promise<string>;
@@ -1,3 +1,4 @@
1
+ import { type BlockContextSource } from "../utils/block-context";
1
2
  export interface DiffResult {
2
3
  diff: string;
3
4
  firstChangedLine: number | undefined;
@@ -25,7 +26,7 @@ export declare class ApplyPatchError extends Error {
25
26
  * Generate a unified diff string with line numbers and context.
26
27
  * Returns both the diff string and the first changed line number (in the new file).
27
28
  */
28
- export declare function generateDiffString(oldContent: string, newContent: string, contextLines?: number): DiffResult;
29
+ export declare function generateDiffString(oldContent: string, newContent: string, contextLines?: number, source?: BlockContextSource): DiffResult;
29
30
  export interface ReplaceOptions {
30
31
  /** Allow fuzzy matching */
31
32
  fuzzy: boolean;
@@ -44,7 +45,7 @@ export interface ReplaceResult {
44
45
  * Generate a unified diff string without file headers.
45
46
  * Returns both the diff string and the first changed line number (in the new file).
46
47
  */
47
- export declare function generateUnifiedDiffString(oldContent: string, newContent: string, contextLines?: number): DiffResult;
48
+ export declare function generateUnifiedDiffString(oldContent: string, newContent: string, contextLines?: number, source?: BlockContextSource): DiffResult;
48
49
  export declare function normalizeDiff(diff: string): string;
49
50
  export declare function normalizeCreateContent(content: string): string;
50
51
  export declare function parseDiffHunks(diff: string): DiffHunk[];
@@ -53,3 +53,10 @@ export interface ExecutorBackend {
53
53
  /** Execute one cell. Caller invokes once per cell and aggregates results. */
54
54
  execute(code: string, opts: ExecutorBackendExecOptions): Promise<ExecutorBackendResult>;
55
55
  }
56
+ /**
57
+ * Resolve the on-disk roots that the eval helpers substitute for internal-URL
58
+ * schemes (currently `local://`). Prefers the session's own
59
+ * {@link LocalProtocolOptions} — the exact mapping `read local://…` uses — so an
60
+ * eval `write("local://x")` and a later `read local://x` agree on the location.
61
+ */
62
+ export declare function resolveEvalUrlRoots(session: ToolSession): Record<string, string>;
@@ -2,7 +2,7 @@
2
2
  * Timeout suspension for in-flight host-side eval bridge calls.
3
3
  *
4
4
  * The eval watchdog caps a cell's `timeout` as a budget on the cell runtime's
5
- * own work. Host-side `agent()` / `parallel()` / `llm()` bridge calls hand
5
+ * own work. Host-side `agent()` / `parallel()` / `completion()` bridge calls hand
6
6
  * control to the outer TypeScript process, where the Python kernel or JS VM is
7
7
  * only waiting for a result. While that delegated work is in flight, the cell
8
8
  * timeout must be ignored completely; once the bridge returns and the runtime is
@@ -1,25 +1,25 @@
1
1
  import type { ToolSession } from "../tools";
2
2
  import type { JsStatusEvent } from "./js/shared/types";
3
- /** Synthetic bridge name reserved for the `llm()` helper across both runtimes. */
4
- export declare const EVAL_LLM_BRIDGE_NAME = "__llm__";
5
- type LlmTier = "smol" | "default" | "slow";
6
- export interface EvalLlmBridgeOptions {
3
+ /** Synthetic bridge name reserved for the `completion()` helper across both runtimes. */
4
+ export declare const EVAL_COMPLETION_BRIDGE_NAME = "__completion__";
5
+ type CompletionTier = "smol" | "default" | "slow";
6
+ export interface EvalCompletionBridgeOptions {
7
7
  session: ToolSession;
8
8
  signal?: AbortSignal;
9
9
  emitStatus?: (event: JsStatusEvent) => void;
10
10
  }
11
- export interface EvalLlmResult {
11
+ export interface EvalCompletionResult {
12
12
  text: string;
13
13
  details: {
14
14
  model: string;
15
- tier: LlmTier;
15
+ tier: CompletionTier;
16
16
  structured: boolean;
17
17
  };
18
18
  }
19
19
  /**
20
- * Run a single stateless completion on behalf of an eval cell's `llm()` call.
20
+ * Run a single stateless completion on behalf of an eval cell's `completion()` call.
21
21
  * Returns a `{ text, details }` value shaped like a {@link callSessionTool}
22
22
  * result so the existing bridge transport carries it to either runtime.
23
23
  */
24
- export declare function runEvalLlm(args: unknown, options: EvalLlmBridgeOptions): Promise<EvalLlmResult>;
24
+ export declare function runEvalCompletion(args: unknown, options: EvalCompletionBridgeOptions): Promise<EvalCompletionResult>;
25
25
  export {};
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * A cell's `timeout` bounds time while the Python kernel or JS VM is in control.
5
5
  * Host-side bridge calls can {@link pause} the watchdog so delegated
6
- * `agent()`/`parallel()`/`llm()` work is ignored completely, then {@link resume}
6
+ * `agent()`/`parallel()`/`completion()` work is ignored completely, then {@link resume}
7
7
  * starts a fresh timeout window once the runtime gets control back.
8
8
  *
9
9
  * The active timer self-reschedules instead of being torn down on every
@@ -12,6 +12,7 @@ export declare function executeInVmContext(options: {
12
12
  sessionId: string;
13
13
  cwd: string;
14
14
  session: ToolSession;
15
+ localRoots?: Record<string, string>;
15
16
  reset?: boolean;
16
17
  code: string;
17
18
  filename: string;
@@ -20,6 +20,8 @@ export interface JsExecutorOptions {
20
20
  artifactPath?: string;
21
21
  artifactId?: string;
22
22
  session: ToolSession;
23
+ /** On-disk roots the helpers substitute for internal-URL schemes (e.g. `local://`). */
24
+ localRoots?: Record<string, string>;
23
25
  }
24
26
  export interface JsResult {
25
27
  output: string;
@@ -1,5 +1,5 @@
1
1
  import type { ToolSession } from "../../tools";
2
- import type { ExecutorBackendExecOptions, ExecutorBackendResult } from "../backend";
2
+ import { type ExecutorBackendExecOptions, type ExecutorBackendResult } from "../backend";
3
3
  declare const _default: {
4
4
  id: "js";
5
5
  label: string;
@@ -17,6 +17,12 @@ export interface HelperOptions {
17
17
  export interface HelperContext {
18
18
  cwd(): string;
19
19
  env: Map<string, string>;
20
+ /**
21
+ * On-disk roots for internal-URL schemes the helpers accept (e.g.
22
+ * `{ local: "/…/artifacts/local" }`). A path like `local://x.md` is rewritten
23
+ * to `<root>/x.md` before any filesystem op; unknown schemes are rejected.
24
+ */
25
+ localRoots(): Record<string, string>;
20
26
  emitStatus(event: JsStatusEvent): void;
21
27
  }
22
28
  /**
@@ -25,6 +25,11 @@ export interface RuntimeOptions {
25
25
  * via `setRunScope()` instead.
26
26
  */
27
27
  extraGlobals?: Record<string, unknown>;
28
+ /**
29
+ * On-disk roots the helpers substitute for internal-URL schemes (e.g.
30
+ * `{ local: "/…/artifacts/local" }`). Stable for the worker's lifetime.
31
+ */
32
+ localRoots?: Record<string, string>;
28
33
  }
29
34
  /**
30
35
  * Shared JS runtime for the eval worker and the browser tab worker. Owns the prelude,
@@ -3,6 +3,12 @@ export type { JsDisplayOutput } from "./shared/types";
3
3
  export interface SessionSnapshot {
4
4
  cwd: string;
5
5
  sessionId: string;
6
+ /**
7
+ * On-disk roots the helpers substitute for internal-URL schemes
8
+ * (e.g. `{ local: "/…/artifacts/local" }`). Lets `read`/`write`/`append`
9
+ * accept `local://…` paths instead of writing a literal `local:/` directory.
10
+ */
11
+ localRoots?: Record<string, string>;
6
12
  }
7
13
  export interface RunErrorPayload {
8
14
  name?: string;
@@ -39,6 +39,13 @@ export interface PythonExecutorOptions {
39
39
  /** Artifact path/id for full output storage */
40
40
  artifactPath?: string;
41
41
  artifactId?: string;
42
+ /**
43
+ * On-disk roots the prelude helpers (`read`/`write`/`append`) substitute for
44
+ * internal-URL schemes (e.g. `{ local: "/…/artifacts/local" }`). Exported to
45
+ * the kernel as `PI_EVAL_LOCAL_ROOTS` (JSON) so `write("local://x")` lands
46
+ * where `read local://x` resolves instead of a literal `local:/` directory.
47
+ */
48
+ localRoots?: Record<string, string>;
42
49
  /**
43
50
  * ToolSession used to resolve host-side `tool.<name>(args)` calls made from
44
51
  * the Python prelude's bridge proxy. When omitted, the bridge env vars are
@@ -1,5 +1,5 @@
1
1
  import type { ToolSession } from "../../tools";
2
- import type { ExecutorBackendExecOptions, ExecutorBackendResult } from "../backend";
2
+ import { type ExecutorBackendExecOptions, type ExecutorBackendResult } from "../backend";
3
3
  export declare function namespaceSessionId(sessionId: string): string;
4
4
  declare const _default: {
5
5
  id: "python";
@@ -32,6 +32,18 @@ export declare class TtsrManager {
32
32
  * of being appended to it.
33
33
  */
34
34
  checkSnapshot(snapshot: string, context: TtsrMatchContext): Rule[];
35
+ /**
36
+ * Evaluate ast-grep `astCondition` rules against a reconstructed tool snapshot.
37
+ *
38
+ * Only edit/write tool streams reach here (AST conditions need a language, which
39
+ * we infer from the file extension on the tool's path argument). The snapshot is
40
+ * matched in memory by the native engine (`astMatch`), so this is async and
41
+ * intentionally throttled: identical consecutive snapshots (the common case when
42
+ * only non-source arguments change between deltas) are skipped.
43
+ */
44
+ checkAstSnapshot(snapshot: string, context: TtsrMatchContext): Promise<Rule[]>;
45
+ /** True when any registered rule carries ast-grep conditions. */
46
+ hasAstRules(): boolean;
35
47
  /** Mark rules as injected (won't trigger again until conditions allow). */
36
48
  markInjected(rulesToMark: Rule[]): void;
37
49
  /** Mark rule names as injected (won't trigger again until conditions allow). */
@@ -44,6 +56,8 @@ export declare class TtsrManager {
44
56
  resetBuffer(): void;
45
57
  /** Check if any TTSR rules are registered. */
46
58
  hasRules(): boolean;
59
+ /** All rules currently registered for TTSR monitoring, in registration order. */
60
+ getRules(): Rule[];
47
61
  /** Increment message counter (call after each turn). */
48
62
  incrementMessageCount(): void;
49
63
  /** Get current message count. */
@@ -10,7 +10,7 @@
10
10
  import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel, ToolApproval } from "@oh-my-pi/pi-agent-core";
11
11
  import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
12
12
  import type { Api, AssistantMessageEvent, AssistantMessageEventStream, Context, ImageContent, Model, ProviderResponseMetadata, SimpleStreamOptions, Static, TextContent, TSchema } from "@oh-my-pi/pi-ai";
13
- import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
13
+ import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
14
14
  import type * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
15
15
  import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
16
16
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
@@ -727,6 +727,13 @@ export interface ProviderConfig {
727
727
  /** Optional model rewrite hook for credential-aware routing (e.g., enterprise URLs). */
728
728
  modifyModels?(models: Model<Api>[], credentials: OAuthCredentials): Model<Api>[];
729
729
  };
730
+ /**
731
+ * Async factory that fetches the live model list from the provider endpoint.
732
+ * Runs through the same SQLite model-cache as built-in providers (keyed by
733
+ * provider name, default 24 h TTL). Receives the resolved API key (undefined
734
+ * when unauthenticated). Mutually exclusive with `models`.
735
+ */
736
+ fetchDynamicModels?: (apiKey: string | undefined) => Promise<readonly ProviderModelConfig[]>;
730
737
  }
731
738
  /** Configuration for a model within a provider. */
732
739
  export interface ProviderModelConfig {
@@ -8,7 +8,7 @@
8
8
  * entrypoint. Legacy extensions still author parameter schemas as
9
9
  * `Type.Object({ ... })`, so this file is served by `legacy-pi-compat.ts` in
10
10
  * place of the real pi-ai entrypoint whenever a legacy extension imports the
11
- * bare package root. Subpath imports (`@oh-my-pi/pi-ai/utils/oauth`, etc.)
11
+ * bare package root. Subpath imports (`@oh-my-pi/pi-ai/oauth`, etc.)
12
12
  * continue to resolve directly against the bundled pi-ai package.
13
13
  *
14
14
  * The `Type` runtime is borrowed from the Zod-backed TypeBox shim that
@@ -5,6 +5,16 @@ export interface LocalProtocolOptions {
5
5
  }
6
6
  export declare function resolveLocalRoot(options: LocalProtocolOptions): string;
7
7
  export declare function resolveLocalUrlToPath(input: string | InternalUrl, options: LocalProtocolOptions): string;
8
+ /**
9
+ * On-disk roots the eval helpers (`read`/`write`/`append`) substitute for
10
+ * internal-URL schemes so e.g. `write("local://x.md")` lands where a later
11
+ * `read local://x.md` resolves — instead of a literal `local:/` directory under
12
+ * the cwd (a stdlib `pathlib.Path`/`path.resolve` collapses `local://` to
13
+ * `local:/`). Keyed by scheme without the `://`. Currently only `local`, but the
14
+ * shape is a map so additional file-backed schemes can be added without
15
+ * re-plumbing the worker boundary.
16
+ */
17
+ export declare function buildEvalUrlRoots(options: LocalProtocolOptions): Record<string, string>;
8
18
  /**
9
19
  * Protocol handler for local:// URLs.
10
20
  *
@@ -4,8 +4,8 @@
4
4
  * Allows users to authenticate with any OAuth-compatible MCP server
5
5
  * by providing authorization URL, token URL, and client credentials.
6
6
  */
7
- import { OAuthCallbackFlow } from "@oh-my-pi/pi-ai/utils/oauth/callback-server";
8
- import type { OAuthController, OAuthCredentials } from "@oh-my-pi/pi-ai/utils/oauth/types";
7
+ import { OAuthCallbackFlow } from "@oh-my-pi/pi-ai/oauth/callback-server";
8
+ import type { OAuthController, OAuthCredentials } from "@oh-my-pi/pi-ai/oauth/types";
9
9
  export interface MCPOAuthConfig {
10
10
  /** Authorization endpoint URL */
11
11
  authorizationUrl: string;
@@ -8,6 +8,9 @@ export declare function extractBracketedImagePastePath(data: string): string | u
8
8
  export declare class CustomEditor extends Editor {
9
9
  #private;
10
10
  imageLinks?: readonly (string | undefined)[];
11
+ /** Treat image/paste markers as indivisible: a stray backspace deletes the whole token
12
+ * instead of corrupting `[Paste #1, +30 lines]` into plain text. */
13
+ atomicTokenPattern: RegExp;
11
14
  /** Gradient-highlight the "ultrathink" / "orchestrate" / "workflowz" keywords as the user types
12
15
  * them, skipping any occurrence inside code spans, fenced blocks, or XML sections. Also make
13
16
  * pasted image placeholders visually distinct and hyperlink them once their blob file exists. */
@@ -1,36 +1,6 @@
1
1
  import { type Component } from "@oh-my-pi/pi-tui";
2
- import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../config/settings-schema";
3
- import type { AgentSession } from "../../session/agent-session";
4
- export interface StatusLineSegmentOptions {
5
- model?: {
6
- showThinkingLevel?: boolean;
7
- };
8
- path?: {
9
- abbreviate?: boolean;
10
- maxLength?: number;
11
- stripWorkPrefix?: boolean;
12
- };
13
- git?: {
14
- showBranch?: boolean;
15
- showStaged?: boolean;
16
- showUnstaged?: boolean;
17
- showUntracked?: boolean;
18
- };
19
- time?: {
20
- format?: "12h" | "24h";
21
- showSeconds?: boolean;
22
- };
23
- }
24
- export interface StatusLineSettings {
25
- preset?: StatusLinePreset;
26
- leftSegments?: StatusLineSegmentId[];
27
- rightSegments?: StatusLineSegmentId[];
28
- separator?: StatusLineSeparatorStyle;
29
- segmentOptions?: StatusLineSegmentOptions;
30
- showHookStatus?: boolean;
31
- sessionAccent?: boolean;
32
- }
33
- export type EffectiveStatusLineSettings = Required<Pick<StatusLineSettings, "leftSegments" | "rightSegments" | "separator" | "segmentOptions">> & StatusLineSettings;
2
+ import type { AgentSession } from "../../../session/agent-session";
3
+ import type { EffectiveStatusLineSettings, StatusLineSettings } from "./types";
34
4
  export declare class StatusLineComponent implements Component {
35
5
  #private;
36
6
  private readonly session;
@@ -1,3 +1,4 @@
1
+ export * from "./component";
1
2
  export * from "./presets";
2
3
  export * from "./segments";
3
4
  export * from "./separators";
@@ -1,7 +1,36 @@
1
1
  import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../../config/settings-schema";
2
2
  import type { AgentSession } from "../../../session/agent-session";
3
- import type { StatusLineSegmentOptions, StatusLineSettings } from "../status-line";
4
- export type { StatusLinePreset, StatusLineSegmentId, StatusLineSegmentOptions, StatusLineSeparatorStyle, StatusLineSettings, };
3
+ export type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle };
4
+ export interface StatusLineSegmentOptions {
5
+ model?: {
6
+ showThinkingLevel?: boolean;
7
+ };
8
+ path?: {
9
+ abbreviate?: boolean;
10
+ maxLength?: number;
11
+ stripWorkPrefix?: boolean;
12
+ };
13
+ git?: {
14
+ showBranch?: boolean;
15
+ showStaged?: boolean;
16
+ showUnstaged?: boolean;
17
+ showUntracked?: boolean;
18
+ };
19
+ time?: {
20
+ format?: "12h" | "24h";
21
+ showSeconds?: boolean;
22
+ };
23
+ }
24
+ export interface StatusLineSettings {
25
+ preset?: StatusLinePreset;
26
+ leftSegments?: StatusLineSegmentId[];
27
+ rightSegments?: StatusLineSegmentId[];
28
+ separator?: StatusLineSeparatorStyle;
29
+ segmentOptions?: StatusLineSegmentOptions;
30
+ showHookStatus?: boolean;
31
+ sessionAccent?: boolean;
32
+ }
33
+ export type EffectiveStatusLineSettings = Required<Pick<StatusLineSettings, "leftSegments" | "rightSegments" | "separator" | "segmentOptions">> & StatusLineSettings;
5
34
  export type RGB = readonly [number, number, number];
6
35
  export interface SegmentContext {
7
36
  session: AgentSession;
@@ -1,16 +1,21 @@
1
1
  import type { ImageContent } from "@oh-my-pi/pi-ai";
2
2
  import { type BlobPutResult } from "../session/blob-store";
3
+ /** Matches `[Image #N]`/`[Image #N, WxH]` and `[Paste #N, +X lines]`/`[Paste #N, Y chars]` tokens.
4
+ * Group 1 is the kind (`Image`/`Paste`), group 2 the 1-based index. The optional metadata
5
+ * tail (`, …`) is captured loosely (no `]`/newline) so future label tweaks keep matching. */
6
+ export declare const PLACEHOLDER_REGEX: RegExp;
3
7
  type ImageBlobWriter = (data: Buffer, options?: {
4
8
  extension?: string;
5
9
  }) => Promise<BlobPutResult>;
6
10
  type ImageBlobWriterSync = (data: Buffer, options?: {
7
11
  extension?: string;
8
12
  }) => BlobPutResult;
9
- export interface ImageReferenceRenderers {
13
+ export type PlaceholderKind = "image" | "paste";
14
+ export interface PlaceholderRenderers {
10
15
  renderText: (text: string) => string;
11
- renderReference: (label: string, index: number) => string;
16
+ renderReference: (label: string, kind: PlaceholderKind, index: number) => string;
12
17
  }
13
- export declare function renderImageReferences(text: string, renderers: ImageReferenceRenderers): string;
18
+ export declare function renderPlaceholders(text: string, renderers: PlaceholderRenderers): string;
14
19
  export declare function imageReferenceHyperlink(label: string, index: number, imageLinks: readonly (string | undefined)[] | undefined, renderLabel: (text: string) => string): string;
15
20
  export declare function materializeImageReferenceLinks(images: readonly ImageContent[] | undefined, putBlob: ImageBlobWriter): Promise<(string | undefined)[] | undefined>;
16
21
  export declare function materializeImageReferenceLinksSync(images: readonly ImageContent[] | undefined, putBlob: ImageBlobWriterSync): (string | undefined)[] | undefined;