@oh-my-pi/pi-coding-agent 17.2.10 → 17.2.12

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 (247) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/{CHANGELOG-rhwzpexa.md → CHANGELOG-k9ghy5sn.md} +53 -0
  3. package/dist/cli.js +10775 -10762
  4. package/dist/types/advisor/runtime.d.ts +1 -1
  5. package/dist/types/capability/mcp.d.ts +11 -0
  6. package/dist/types/capability/skill.d.ts +6 -0
  7. package/dist/types/cli/command-help.d.ts +3 -0
  8. package/dist/types/commands/share.d.ts +25 -0
  9. package/dist/types/commit/agentic/index.d.ts +3 -1
  10. package/dist/types/commit/execute.d.ts +32 -0
  11. package/dist/types/commit/index.d.ts +2 -1
  12. package/dist/types/commit/pipeline.d.ts +7 -1
  13. package/dist/types/config/custom-models.d.ts +31 -0
  14. package/dist/types/config/model-config-values.d.ts +19 -0
  15. package/dist/types/config/model-patch.d.ts +93 -0
  16. package/dist/types/config/model-provider-discovery.d.ts +51 -0
  17. package/dist/types/config/model-registry.d.ts +9 -52
  18. package/dist/types/config/settings-schema.d.ts +1 -34
  19. package/dist/types/config/settings.d.ts +5 -3
  20. package/dist/types/debug/raw-sse-buffer.d.ts +9 -0
  21. package/dist/types/discovery/agent-plugin-format.d.ts +136 -0
  22. package/dist/types/discovery/agent-plugins.d.ts +1 -0
  23. package/dist/types/discovery/contained-path.d.ts +33 -0
  24. package/dist/types/discovery/index.d.ts +1 -0
  25. package/dist/types/eval/executor-base.d.ts +8 -2
  26. package/dist/types/eval/kernel-session-registry.d.ts +60 -0
  27. package/dist/types/export/share.d.ts +1 -1
  28. package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +7 -0
  30. package/dist/types/extensibility/extensions/types.d.ts +11 -0
  31. package/dist/types/extensibility/shared-events.d.ts +3 -2
  32. package/dist/types/extensibility/skills.d.ts +5 -0
  33. package/dist/types/lsp/diagnostics.d.ts +96 -0
  34. package/dist/types/lsp/index.d.ts +7 -128
  35. package/dist/types/lsp/servers.d.ts +72 -0
  36. package/dist/types/lsp/tool.d.ts +42 -0
  37. package/dist/types/lsp/workspace-diagnostics.d.ts +12 -0
  38. package/dist/types/lsp/writethrough.d.ts +33 -0
  39. package/dist/types/mcp/transports/header-policy.d.ts +46 -0
  40. package/dist/types/mcp/types.d.ts +15 -0
  41. package/dist/types/modes/components/agent-hub-projection.d.ts +2 -7
  42. package/dist/types/modes/components/agent-hub-renderer.d.ts +0 -7
  43. package/dist/types/modes/components/agent-hub.d.ts +2 -0
  44. package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
  45. package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
  46. package/dist/types/modes/components/custom-editor.d.ts +1 -2
  47. package/dist/types/modes/components/status-line/types.d.ts +2 -0
  48. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  49. package/dist/types/modes/theme/color.d.ts +19 -0
  50. package/dist/types/modes/theme/loader.d.ts +19 -0
  51. package/dist/types/modes/theme/schema.d.ts +175 -0
  52. package/dist/types/modes/theme/symbols.d.ts +28 -0
  53. package/dist/types/modes/theme/theme-class.d.ts +244 -0
  54. package/dist/types/modes/theme/theme.d.ts +9 -280
  55. package/dist/types/modes/theme/tui-adapters.d.ts +13 -0
  56. package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
  57. package/dist/types/registry/agent-registry.d.ts +1 -3
  58. package/dist/types/secrets/index.d.ts +26 -2
  59. package/dist/types/secrets/message-transform.d.ts +40 -0
  60. package/dist/types/secrets/obfuscator.d.ts +0 -108
  61. package/dist/types/secrets/placeholder-scan.d.ts +95 -0
  62. package/dist/types/secrets/placeholder.d.ts +94 -0
  63. package/dist/types/secrets/replacement.d.ts +82 -0
  64. package/dist/types/session/agent-session-events.d.ts +2 -2
  65. package/dist/types/session/agent-session-types.d.ts +6 -0
  66. package/dist/types/session/agent-session.d.ts +2 -2
  67. package/dist/types/session/messages.d.ts +1 -0
  68. package/dist/types/session/prewalk.d.ts +3 -1
  69. package/dist/types/session/session-handoff.d.ts +3 -3
  70. package/dist/types/session/session-manager.d.ts +32 -0
  71. package/dist/types/session/session-provider-boundary.d.ts +1 -1
  72. package/dist/types/session/session-tools.d.ts +8 -0
  73. package/dist/types/session/turn-recovery.d.ts +9 -4
  74. package/dist/types/slash-commands/builtin-collaboration.d.ts +2 -0
  75. package/dist/types/slash-commands/builtin-completions.d.ts +36 -0
  76. package/dist/types/slash-commands/builtin-control.d.ts +2 -0
  77. package/dist/types/slash-commands/builtin-lifecycle.d.ts +3 -0
  78. package/dist/types/slash-commands/builtin-marketplace.d.ts +11 -0
  79. package/dist/types/slash-commands/builtin-modes.d.ts +5 -0
  80. package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
  81. package/dist/types/slash-commands/builtin-session.d.ts +2 -0
  82. package/dist/types/task/index.d.ts +2 -0
  83. package/dist/types/tools/gh-common.d.ts +69 -0
  84. package/dist/types/tools/gh-pr-checkout.d.ts +84 -0
  85. package/dist/types/tools/gh-pr-diff.d.ts +102 -0
  86. package/dist/types/tools/gh-run-watch.d.ts +78 -0
  87. package/dist/types/tools/gh-search.d.ts +61 -0
  88. package/dist/types/tools/gh-types.d.ts +340 -0
  89. package/dist/types/tools/gh-view.d.ts +88 -0
  90. package/dist/types/tools/gh.d.ts +4 -201
  91. package/dist/types/tools/read-archive.d.ts +16 -0
  92. package/dist/types/tools/read-format.d.ts +104 -0
  93. package/dist/types/tools/read-path-resolution.d.ts +19 -0
  94. package/dist/types/tools/read-pdf-images.d.ts +12 -0
  95. package/dist/types/tools/read-renderer.d.ts +24 -0
  96. package/dist/types/tools/read-selector.d.ts +27 -0
  97. package/dist/types/tools/read-sqlite.d.ts +16 -0
  98. package/dist/types/tools/read-summary.d.ts +19 -0
  99. package/dist/types/tools/read.d.ts +1 -23
  100. package/dist/types/tools/shell-tokenize.d.ts +18 -1
  101. package/dist/types/utils/changelog.d.ts +0 -5
  102. package/package.json +13 -13
  103. package/scripts/legacy-pi-virtual-module.ts +4 -1
  104. package/src/advisor/runtime.ts +12 -7
  105. package/src/capability/mcp.ts +11 -0
  106. package/src/capability/skill.ts +6 -0
  107. package/src/cli/command-help.ts +4 -0
  108. package/src/cli/gallery-cli.ts +1 -1
  109. package/src/cli-commands.ts +5 -0
  110. package/src/commands/commit.ts +16 -3
  111. package/src/commands/share.ts +71 -0
  112. package/src/commit/agentic/index.ts +39 -21
  113. package/src/commit/execute.ts +56 -0
  114. package/src/commit/index.ts +2 -1
  115. package/src/commit/pipeline.ts +20 -7
  116. package/src/config/custom-models.ts +188 -0
  117. package/src/config/model-config-values.ts +128 -0
  118. package/src/config/model-discovery.ts +1 -1
  119. package/src/config/model-patch.ts +252 -0
  120. package/src/config/model-provider-discovery.ts +132 -0
  121. package/src/config/model-registry.ts +84 -704
  122. package/src/config/settings-schema.ts +2 -33
  123. package/src/config/settings.ts +53 -3
  124. package/src/debug/raw-sse-buffer.ts +20 -0
  125. package/src/discovery/agent-plugin-format.ts +551 -0
  126. package/src/discovery/agent-plugins.ts +341 -0
  127. package/src/discovery/claude-plugins.ts +21 -5
  128. package/src/discovery/contained-path.ts +75 -0
  129. package/src/discovery/helpers.ts +23 -9
  130. package/src/discovery/index.ts +1 -0
  131. package/src/discovery/omp-plugins.ts +20 -7
  132. package/src/edit/hashline/diff.ts +5 -1
  133. package/src/eval/executor-base.ts +39 -6
  134. package/src/eval/jl/executor.ts +82 -371
  135. package/src/eval/kernel-session-registry.ts +398 -0
  136. package/src/eval/py/executor.ts +53 -261
  137. package/src/eval/rb/executor.ts +36 -279
  138. package/src/exec/non-interactive-env.ts +1 -0
  139. package/src/export/share.ts +2 -1
  140. package/src/extensibility/custom-tools/types.ts +2 -2
  141. package/src/extensibility/extensions/loader.ts +78 -14
  142. package/src/extensibility/extensions/runner.ts +6 -0
  143. package/src/extensibility/extensions/types.ts +12 -0
  144. package/src/extensibility/plugins/marketplace/manager.ts +2 -1
  145. package/src/extensibility/shared-events.ts +3 -2
  146. package/src/extensibility/skills.ts +9 -0
  147. package/src/internal-urls/skill-protocol.ts +14 -0
  148. package/src/internal-urls/vault-protocol.ts +2 -2
  149. package/src/launch/client.ts +11 -1
  150. package/src/launch/protocol.ts +7 -2
  151. package/src/lsp/diagnostics.ts +516 -0
  152. package/src/lsp/index.ts +20 -2819
  153. package/src/lsp/servers.ts +296 -0
  154. package/src/lsp/tool.ts +1352 -0
  155. package/src/lsp/workspace-diagnostics.ts +170 -0
  156. package/src/lsp/writethrough.ts +561 -0
  157. package/src/main.ts +3 -2
  158. package/src/mcp/config.ts +3 -0
  159. package/src/mcp/manager.ts +12 -9
  160. package/src/mcp/transports/header-policy.ts +95 -0
  161. package/src/mcp/transports/http.ts +35 -52
  162. package/src/mcp/transports/sse.ts +20 -27
  163. package/src/mcp/types.ts +15 -0
  164. package/src/modes/acp/acp-agent.ts +15 -4
  165. package/src/modes/components/agent-dashboard.ts +2 -0
  166. package/src/modes/components/agent-hub-projection.ts +2 -2
  167. package/src/modes/components/agent-hub-renderer.ts +3 -7
  168. package/src/modes/components/agent-hub.ts +5 -0
  169. package/src/modes/components/agent-transcript-viewer.ts +3 -0
  170. package/src/modes/components/chat-transcript-builder.ts +3 -0
  171. package/src/modes/components/custom-editor.ts +0 -9
  172. package/src/modes/components/status-line/component.ts +1 -0
  173. package/src/modes/components/status-line/segments.ts +6 -4
  174. package/src/modes/components/status-line/types.ts +2 -0
  175. package/src/modes/components/tool-execution.ts +13 -16
  176. package/src/modes/components/tree-selector.ts +62 -3
  177. package/src/modes/controllers/command-controller.ts +8 -2
  178. package/src/modes/controllers/event-controller.ts +15 -15
  179. package/src/modes/controllers/input-controller.ts +20 -2
  180. package/src/modes/controllers/selector-controller.ts +1 -0
  181. package/src/modes/theme/color.ts +133 -0
  182. package/src/modes/theme/loader.ts +178 -0
  183. package/src/modes/theme/schema.ts +263 -0
  184. package/src/modes/theme/symbols.ts +1000 -0
  185. package/src/modes/theme/theme-class.ts +611 -0
  186. package/src/modes/theme/theme.ts +27 -2453
  187. package/src/modes/theme/tui-adapters.ts +279 -0
  188. package/src/modes/utils/transcript-render-helpers.ts +4 -2
  189. package/src/modes/utils/ui-helpers.ts +1 -0
  190. package/src/registry/agent-registry.ts +2 -2
  191. package/src/sdk.ts +6 -49
  192. package/src/secrets/index.ts +51 -6
  193. package/src/secrets/message-transform.ts +287 -0
  194. package/src/secrets/obfuscator.ts +39 -1303
  195. package/src/secrets/placeholder-scan.ts +506 -0
  196. package/src/secrets/placeholder.ts +309 -0
  197. package/src/secrets/replacement.ts +216 -0
  198. package/src/session/agent-session-events.ts +2 -2
  199. package/src/session/agent-session-types.ts +6 -0
  200. package/src/session/agent-session.ts +146 -21
  201. package/src/session/indexed-session-storage.ts +7 -2
  202. package/src/session/messages.ts +1 -0
  203. package/src/session/prewalk.ts +57 -17
  204. package/src/session/session-advisors.ts +32 -34
  205. package/src/session/session-context.ts +3 -5
  206. package/src/session/session-handoff.ts +39 -16
  207. package/src/session/session-manager.ts +67 -3
  208. package/src/session/session-provider-boundary.ts +3 -6
  209. package/src/session/session-tools.ts +37 -3
  210. package/src/session/todo-tracker.ts +11 -1
  211. package/src/session/turn-recovery.ts +115 -84
  212. package/src/slash-commands/builtin-collaboration.ts +504 -0
  213. package/src/slash-commands/builtin-completions.ts +291 -0
  214. package/src/slash-commands/builtin-control.ts +78 -0
  215. package/src/slash-commands/builtin-lifecycle.ts +506 -0
  216. package/src/slash-commands/builtin-marketplace.ts +567 -0
  217. package/src/slash-commands/builtin-modes.ts +518 -0
  218. package/src/slash-commands/builtin-registry.ts +21 -2996
  219. package/src/slash-commands/builtin-session.ts +592 -0
  220. package/src/task/executor.ts +17 -14
  221. package/src/task/index.ts +21 -6
  222. package/src/tools/bash-skill-urls.ts +15 -0
  223. package/src/tools/bash.ts +10 -11
  224. package/src/tools/debug.ts +1 -1
  225. package/src/tools/gh-common.ts +288 -0
  226. package/src/tools/gh-pr-checkout.ts +679 -0
  227. package/src/tools/gh-pr-diff.ts +473 -0
  228. package/src/tools/gh-run-watch.ts +1015 -0
  229. package/src/tools/gh-search.ts +500 -0
  230. package/src/tools/gh-types.ts +379 -0
  231. package/src/tools/gh-view.ts +612 -0
  232. package/src/tools/gh.ts +109 -3821
  233. package/src/tools/jtd-to-json-schema.ts +123 -21
  234. package/src/tools/read-archive.ts +209 -0
  235. package/src/tools/read-format.ts +593 -0
  236. package/src/tools/read-path-resolution.ts +36 -0
  237. package/src/tools/read-pdf-images.ts +250 -0
  238. package/src/tools/read-renderer.ts +289 -0
  239. package/src/tools/read-selector.ts +84 -0
  240. package/src/tools/read-sqlite.ts +215 -0
  241. package/src/tools/read-summary.ts +199 -0
  242. package/src/tools/read.ts +82 -1824
  243. package/src/tools/shell-tokenize.ts +99 -1
  244. package/src/utils/changelog.ts +1 -1
  245. package/src/utils/title-generator.ts +3 -1
  246. package/src/web/search/providers/exa.ts +1 -1
  247. package/src/web/search/providers/zai.ts +12 -3
@@ -0,0 +1,104 @@
1
+ import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
2
+ import type { ToolSession } from "../sdk.js";
3
+ import { type LineEntry } from "../utils/block-context.js";
4
+ import { type LineRange } from "./path-utils.js";
5
+ import type { ReadToolDetails } from "./read.js";
6
+ export interface HashlineHeaderContext {
7
+ header: string;
8
+ tag: string;
9
+ fullText?: string;
10
+ }
11
+ export declare function formatReadHashlineHeader(displayPath: string, tag: string): string;
12
+ export declare function readHashlineHeaderContext(session: ToolSession, absolutePath: string, cwd: string): Promise<HashlineHeaderContext>;
13
+ export declare function hashlineHeaderContext(displayPath: string, tag: string): HashlineHeaderContext;
14
+ export declare function prependHashlineHeader(text: string, context: HashlineHeaderContext | undefined): string;
15
+ export declare function formatTextWithMode(text: string, startNum: number, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
16
+ export declare const BRACKET_CONTEXT_ELLIPSIS = "\u2026";
17
+ export declare function formatLineEntriesWithMode(entries: readonly LineEntry[], shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
18
+ /**
19
+ * Decide whether the kept lines surrounding an elided range collapse to a
20
+ * single brace-pair line in the rendered summary. Returns true when the head
21
+ * line ends with `{` / `(` / `[` and the tail line is the matching closer
22
+ * (optionally followed by terminating punctuation like `;`, `,`, or further
23
+ * closers — e.g. `};`, `})`, `]);`).
24
+ */
25
+ export declare function canMergeBracePair(headLine: string, tailLine: string): boolean;
26
+ export declare function formatSingleLine(line: number, text: string, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
27
+ export declare function formatMergedBraceLine(startLine: number, endLine: number, headText: string, tailText: string, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): {
28
+ model: string;
29
+ display: string;
30
+ };
31
+ export declare function countTextLines(text: string): number;
32
+ export declare function contiguousLineNumbers(startLine: number, count: number): number[];
33
+ export declare function lineNumbersFromSpans(spans: readonly {
34
+ startLine: number;
35
+ endLine: number;
36
+ }[]): number[];
37
+ /** Inclusive line range describing one elided span in a structural summary. */
38
+ export interface ElidedRange {
39
+ start: number;
40
+ end: number;
41
+ }
42
+ /**
43
+ * Footer appended to summarized reads telling the model how to recover the
44
+ * elided body. Without this hint, agents either ignore the `…`/`{ … }`
45
+ * markers or burn a turn guessing the right selector (see issue #1046). The
46
+ * footer demonstrates the multi-range selector syntax with concrete sample
47
+ * ranges drawn from the actual elision so the model re-reads only what it
48
+ * needs instead of falling back to `:raw` or whole-file reads.
49
+ */
50
+ export declare function formatSummaryElisionFooter(readPath: string, elidedRanges: ReadonlyArray<ElidedRange>, elidedLines: number): string;
51
+ export declare const READ_CHUNK_SIZE: number;
52
+ /**
53
+ * Context lines added around an explicit range read. Anchor-stale failures
54
+ * cluster on edits whose anchors land just outside the most recent read
55
+ * window, but the data (`scripts/session-stats/analyze_selector_reads.py`)
56
+ * shows most follow-up reads are disjoint hops, not adjacent extensions —
57
+ * so symmetric padding rarely pays for itself.
58
+ *
59
+ * Leading=1 catches accidental single-line reads where the anchor is the
60
+ * line immediately above the requested start. Trailing=3 buffers the
61
+ * common case where the agent asks for a narrow range and then needs the
62
+ * next few lines to disambiguate an anchor.
63
+ */
64
+ export declare const RANGE_LEADING_CONTEXT_LINES = 1;
65
+ export declare const RANGE_TRAILING_CONTEXT_LINES = 3;
66
+ export declare function buildInMemoryTextResult(session: ToolSession, text: string, offset: number | undefined, limit: number | undefined, options: {
67
+ details?: ReadToolDetails;
68
+ sourcePath?: string;
69
+ sourceUrl?: string;
70
+ sourceInternal?: string;
71
+ entityLabel: string;
72
+ ignoreResultLimits?: boolean;
73
+ raw?: boolean;
74
+ immutable?: boolean;
75
+ }): AgentToolResult<ReadToolDetails>;
76
+ /**
77
+ * Render a multi-range read against in-memory text. Each range emits a
78
+ * formatted block with its own anchors / line numbers, blocks are joined
79
+ * with an elision separator, and ranges past EOF surface as `[…]` notices
80
+ * so the model can correct the next call. No leading/trailing context is
81
+ * added — multi-range callers always specify exact bounds.
82
+ */
83
+ export declare function buildInMemoryMultiRangeResult(session: ToolSession, text: string, ranges: readonly LineRange[], options: {
84
+ details?: ReadToolDetails;
85
+ sourcePath?: string;
86
+ sourceUrl?: string;
87
+ sourceInternal?: string;
88
+ entityLabel: string;
89
+ raw?: boolean;
90
+ immutable?: boolean;
91
+ }): AgentToolResult<ReadToolDetails>;
92
+ export declare function decodeUtf8Text(bytes: Uint8Array): string | null;
93
+ export declare function prependSuffixResolutionNotice(text: string, suffixResolution?: {
94
+ from: string;
95
+ to: string;
96
+ }): string;
97
+ /**
98
+ * Tag Markdown reads for the TUI's formatted preview, gated on the opt-in
99
+ * `read.renderMarkdown` setting. Off by default; when disabled, no local
100
+ * read is tagged `text/markdown`, so the renderer output is identical to
101
+ * the pre-setting behavior. Internal-URL reads keep their protocol-supplied
102
+ * `contentType` and render as Markdown regardless of the setting.
103
+ */
104
+ export declare function markMarkdownContentType(session: ToolSession, details: ReadToolDetails, filePath: string): ReadToolDetails;
@@ -0,0 +1,19 @@
1
+ import type { ToolSession } from "../sdk.js";
2
+ export declare function isRemoteMountPath(absolutePath: string): boolean;
3
+ export declare function isNotFoundError(error: unknown): boolean;
4
+ /** Per-execute memo of suffix-glob lookups; `null` records a confirmed miss. */
5
+ export type SuffixMatchCache = Map<string, {
6
+ absolutePath: string;
7
+ displayPath: string;
8
+ } | null>;
9
+ /**
10
+ * Memoized {@link findUniqueWorkspaceSuffix} for a single read call. A missing
11
+ * path with archive/sqlite extensions probes the workspace once per stage
12
+ * (archive candidates, sqlite candidates, plain path) — each glob carries a
13
+ * 5s timeout, so repeated lookups of the same string stack into a long
14
+ * stall before erroring. The cache collapses repeats within one execute().
15
+ */
16
+ export declare function findSuffixMatchCached(session: ToolSession, cache: SuffixMatchCache, rawPath: string, signal?: AbortSignal): Promise<{
17
+ absolutePath: string;
18
+ displayPath: string;
19
+ } | null>;
@@ -0,0 +1,12 @@
1
+ import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
2
+ import type { ToolSession } from "../sdk.js";
3
+ import type { ReadToolDetails } from "./read.js";
4
+ export declare function rewritePdfImagePlaceholders(markdown: string, pdfPath: string): string;
5
+ export declare function splitPdfImageMemberReadPath(readPath: string): {
6
+ pdfPath: string;
7
+ member: string;
8
+ } | null;
9
+ export declare function readPdfImageMember(session: ToolSession, autoResizeImages: boolean, absolutePdfPath: string, pdfDisplayPath: string, member: string, suffixResolution: {
10
+ from: string;
11
+ to: string;
12
+ } | undefined, signal?: AbortSignal): Promise<AgentToolResult<ReadToolDetails>>;
@@ -0,0 +1,24 @@
1
+ import type { Component } from "@oh-my-pi/pi-tui";
2
+ import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
3
+ import { type Theme } from "../modes/theme/theme.js";
4
+ import type { ReadToolDetails } from "./read.js";
5
+ interface ReadRenderArgs {
6
+ path?: unknown;
7
+ file_path?: unknown;
8
+ offset?: number;
9
+ limit?: number;
10
+ raw?: boolean;
11
+ }
12
+ export declare const readToolRenderer: {
13
+ renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component;
14
+ renderResult(result: {
15
+ content: Array<{
16
+ type: string;
17
+ text?: string;
18
+ }>;
19
+ details?: ReadToolDetails;
20
+ isError?: boolean;
21
+ }, options: RenderResultOptions, uiTheme: Theme, args?: ReadRenderArgs): Component;
22
+ mergeCallAndResult: boolean;
23
+ };
24
+ export {};
@@ -0,0 +1,27 @@
1
+ import type { LineRange } from "./path-utils.js";
2
+ /** Parsed representation of a path-embedded selector. */
3
+ export type ParsedSelector = {
4
+ kind: "none";
5
+ } | {
6
+ kind: "raw";
7
+ } | {
8
+ kind: "conflicts";
9
+ } | {
10
+ kind: "lines";
11
+ ranges: [LineRange, ...LineRange[]];
12
+ raw?: boolean;
13
+ };
14
+ /** Returns true when the selector requested verbatim/raw output (alone or combined with a range). */
15
+ export declare function isRawSelector(parsed: ParsedSelector): boolean;
16
+ /** Returns true when the selector requested multiple line ranges. */
17
+ export declare function isMultiRange(parsed: ParsedSelector): boolean;
18
+ export declare function parseSel(sel: string | undefined): ParsedSelector;
19
+ /**
20
+ * Convert a single-range selector to the offset/limit pair used by internal pagination.
21
+ * Returns the FIRST range only — multi-range callers MUST branch on `isMultiRange` before
22
+ * calling this helper.
23
+ */
24
+ export declare function selToOffsetLimit(parsed: ParsedSelector): {
25
+ offset?: number;
26
+ limit?: number;
27
+ };
@@ -0,0 +1,16 @@
1
+ import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
2
+ import type { ToolSession } from "../sdk.js";
3
+ import type { ReadToolDetails } from "./read.js";
4
+ import { type SuffixMatchCache } from "./read-path-resolution.js";
5
+ interface ResolvedSqliteReadPath {
6
+ absolutePath: string;
7
+ sqliteSubPath: string;
8
+ queryString: string;
9
+ suffixResolution?: {
10
+ from: string;
11
+ to: string;
12
+ };
13
+ }
14
+ export declare function resolveSqliteReadPath(session: ToolSession, readPath: string, suffixCache: SuffixMatchCache, signal?: AbortSignal): Promise<ResolvedSqliteReadPath | null>;
15
+ export declare function readSqlite(resolvedSqlitePath: ResolvedSqliteReadPath, signal?: AbortSignal): Promise<AgentToolResult<ReadToolDetails>>;
16
+ export {};
@@ -0,0 +1,19 @@
1
+ import { type SummaryResult } from "@oh-my-pi/pi-natives";
2
+ import type { ToolSession } from "../sdk.js";
3
+ import { type ElidedRange } from "./read-format.js";
4
+ /**
5
+ * Prose files (Markdown flavors and plain text) skip code-block summarization
6
+ * unless `read.summarize.prose` opts them in.
7
+ */
8
+ export declare function isProseSummaryPath(filePath: string): boolean;
9
+ export declare function routeReadThroughBridge(session: ToolSession, absolutePath: string, options?: {
10
+ line?: number;
11
+ limit?: number;
12
+ }): Promise<string> | undefined;
13
+ export declare function trySummarize(session: ToolSession, absolutePath: string, fileSize: number, signal?: AbortSignal): Promise<SummaryResult | null>;
14
+ export declare function renderSummary(session: ToolSession, summary: SummaryResult): {
15
+ text: string;
16
+ displayText: string;
17
+ elidedRanges: ElidedRange[];
18
+ elidedLines: number;
19
+ };
@@ -1,10 +1,8 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback, ToolTier } from "@oh-my-pi/pi-agent-core";
2
- import type { Component } from "@oh-my-pi/pi-tui";
3
- import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
4
- import { type Theme } from "../modes/theme/theme.js";
5
2
  import type { ToolSession } from "../sdk.js";
6
3
  import { type TruncationResult } from "../session/streaming-output.js";
7
4
  import { type OutputMeta } from "./output-meta.js";
5
+ export { readToolRenderer } from "./read-renderer.js";
8
6
  declare const readSchema: import("@oh-my-pi/omptype").FluentType<{
9
7
  path: string;
10
8
  }, {
@@ -76,23 +74,3 @@ export declare class ReadTool implements AgentTool<typeof readSchema, ReadToolDe
76
74
  syncInspectImageState(availableOverride?: boolean): boolean;
77
75
  execute(_toolCallId: string, params: ReadParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<ReadToolDetails>, _toolContext?: AgentToolContext): Promise<AgentToolResult<ReadToolDetails>>;
78
76
  }
79
- interface ReadRenderArgs {
80
- path?: unknown;
81
- file_path?: unknown;
82
- offset?: number;
83
- limit?: number;
84
- raw?: boolean;
85
- }
86
- export declare const readToolRenderer: {
87
- renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component;
88
- renderResult(result: {
89
- content: Array<{
90
- type: string;
91
- text?: string;
92
- }>;
93
- details?: ReadToolDetails;
94
- isError?: boolean;
95
- }, options: RenderResultOptions, uiTheme: Theme, args?: ReadRenderArgs): Component;
96
- mergeCallAndResult: boolean;
97
- };
98
- export {};
@@ -17,7 +17,7 @@ export declare function tokenizeShellSegments(command: string): string[][];
17
17
  *
18
18
  * @see extractFlatShellCommandSegments
19
19
  */
20
- export interface FlatShellCommandSegment {
20
+ interface FlatShellCommandSegment {
21
21
  /** Original segment text with quoting and escaping preserved. */
22
22
  text: string;
23
23
  /**
@@ -41,3 +41,20 @@ export interface FlatShellCommandSegment {
41
41
  * complete input in that case.
42
42
  */
43
43
  export declare function extractFlatShellCommandSegments(command: string): FlatShellCommandSegment[];
44
+ /**
45
+ * Parses a leading `cd <path> && ...` prefix so the bash tool can route the
46
+ * target through its structured `cwd` parameter when the model omits it.
47
+ *
48
+ * Returns the single path token (quotes and backslash escapes resolved to their
49
+ * literal value) and the command remainder after the top-level `&&`, or `null`
50
+ * when the command does not begin with exactly `cd`, one path token, and a
51
+ * top-level `&&`. The scanner deliberately bails on anything else in the prefix
52
+ * — redirects (`cd /tmp 2>/dev/null && ...`), extra arguments, or paths needing
53
+ * shell expansion (`$`, backticks, `(`) — leaving the whole command for the
54
+ * shell instead of absorbing shell syntax into `cwd`.
55
+ */
56
+ export declare function extractLeadingCdTarget(command: string): {
57
+ path: string;
58
+ rest: string;
59
+ } | null;
60
+ export {};
@@ -38,11 +38,6 @@ export declare function formatStartupChangelogSummary(selection: StartupChangelo
38
38
  */
39
39
  export declare function resolveBundledChangelogPath(assetPath: string, moduleUrl: string | URL): string | URL;
40
40
  export declare function parseChangelog(changelogPath: string | undefined): Promise<ChangelogEntry[]>;
41
- /**
42
- * Compare changelog entries by their parsed version parts.
43
- * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
44
- */
45
- export declare function compareChangelogEntries(v1: ChangelogEntry, v2: ChangelogEntry): number;
46
41
  /**
47
42
  * Parse an omp changelog marker version into comparable parts.
48
43
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "17.2.10",
4
+ "version": "17.2.12",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -50,18 +50,18 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@babel/parser": "^7.29.7",
53
- "@oh-my-pi/hashline": "17.2.10",
54
- "@oh-my-pi/omp-stats": "17.2.10",
55
- "@oh-my-pi/omptype": "17.2.10",
56
- "@oh-my-pi/pi-agent-core": "17.2.10",
57
- "@oh-my-pi/pi-ai": "17.2.10",
58
- "@oh-my-pi/pi-catalog": "17.2.10",
59
- "@oh-my-pi/pi-mnemopi": "17.2.10",
60
- "@oh-my-pi/pi-natives": "17.2.10",
61
- "@oh-my-pi/pi-tui": "17.2.10",
62
- "@oh-my-pi/pi-utils": "17.2.10",
63
- "@oh-my-pi/pi-wire": "17.2.10",
64
- "@oh-my-pi/snapcompact": "17.2.10",
53
+ "@oh-my-pi/hashline": "17.2.12",
54
+ "@oh-my-pi/omp-stats": "17.2.12",
55
+ "@oh-my-pi/omptype": "17.2.12",
56
+ "@oh-my-pi/pi-agent-core": "17.2.12",
57
+ "@oh-my-pi/pi-ai": "17.2.12",
58
+ "@oh-my-pi/pi-catalog": "17.2.12",
59
+ "@oh-my-pi/pi-mnemopi": "17.2.12",
60
+ "@oh-my-pi/pi-natives": "17.2.12",
61
+ "@oh-my-pi/pi-tui": "17.2.12",
62
+ "@oh-my-pi/pi-utils": "17.2.12",
63
+ "@oh-my-pi/pi-wire": "17.2.12",
64
+ "@oh-my-pi/snapcompact": "17.2.12",
65
65
  "@opentelemetry/api": "^1.9.1",
66
66
  "@opentelemetry/api-logs": "^0.220.0",
67
67
  "@opentelemetry/context-async-hooks": "^2.9.0",
@@ -151,7 +151,10 @@ export async function collectBundledPiEntries(): Promise<BundledPiEntry[]> {
151
151
  const glob = new Bun.Glob(`**/*${pattern.sourceSuffix}`);
152
152
  const matches: string[] = [];
153
153
  for await (const match of glob.scan({ cwd: sourceDir, onlyFiles: true })) {
154
- matches.push(match);
154
+ // Bun.Glob yields host separators; the export keys and generated
155
+ // identifiers below are `/`-shaped. Same normalization as
156
+ // `generate-docs-index.ts`.
157
+ matches.push(match.split(path.sep).join("/"));
155
158
  }
156
159
  matches.sort();
157
160
  for (const match of matches) {
@@ -5,7 +5,8 @@ import * as AIError from "@oh-my-pi/pi-ai/error";
5
5
  import { raceWithSignal } from "@oh-my-pi/pi-ai/utils/abort";
6
6
  import { type CursorExecResolvedCarrier, kCursorExecResolved } from "@oh-my-pi/pi-ai/utils/block-symbols";
7
7
  import { logger } from "@oh-my-pi/pi-utils";
8
- import { obfuscateToolArguments, type SecretObfuscator } from "../secrets/obfuscator";
8
+ import { obfuscateToolArguments } from "../secrets/message-transform";
9
+ import type { SecretObfuscator } from "../secrets/obfuscator";
9
10
  import {
10
11
  formatExecutionSourcePreview,
11
12
  formatSessionHistoryMarkdown,
@@ -970,14 +971,16 @@ export class AdvisorRuntime {
970
971
  this.#wakeAllWaiters();
971
972
  const failedMessages = this.agent.state.messages.slice(messageSnapshot);
972
973
  const terminalFailure = this.#terminalAssistantFailure(messageSnapshot);
973
- const classifierRefusal =
974
- (terminalFailure !== undefined && isClassifierRefusal(terminalFailure)) ||
975
- AIError.is(AIError.classify(err), AIError.Flag.ContentBlocked);
974
+ const rawErrorId = AIError.classify(err);
976
975
  const terminalFailureId =
977
976
  terminalFailure === undefined ? undefined : AIError.classifyMessage(terminalFailure);
977
+ const classifierRefusal =
978
+ (terminalFailure !== undefined && isClassifierRefusal(terminalFailure)) ||
979
+ (!AIError.is(rawErrorId, AIError.Flag.AccountPolicy) &&
980
+ AIError.is(rawErrorId, AIError.Flag.ContentBlocked));
978
981
  const contextOverflow =
979
982
  (terminalFailureId !== undefined && AIError.is(terminalFailureId, AIError.Flag.ContextOverflow)) ||
980
- AIError.is(AIError.classify(err), AIError.Flag.ContextOverflow);
983
+ AIError.is(rawErrorId, AIError.Flag.ContextOverflow);
981
984
  // A terminal provider failure that is neither retriable nor an
982
985
  // overflow (e.g. a blocked prompt) will fail identically on every
983
986
  // retry — classify it before rollback so the batch is dropped after
@@ -1208,12 +1211,14 @@ export class AdvisorRuntime {
1208
1211
  }
1209
1212
  }
1210
1213
 
1211
- /** Mirrors turn recovery's refusal classification and retains AIError's provider-neutral content-block fallback. */
1214
+ /** Mirrors turn recovery's refusal classification without treating account eligibility as a model refusal. */
1212
1215
  function isClassifierRefusal(message: AssistantMessage): boolean {
1213
1216
  if (message.stopReason !== "error") return false;
1217
+ const id = AIError.classifyMessage(message);
1218
+ if (AIError.is(id, AIError.Flag.AccountPolicy)) return false;
1214
1219
  const stopType = message.stopDetails?.type;
1215
1220
  if (stopType === "refusal" || stopType === "sensitive") return true;
1216
- return AIError.is(AIError.classifyMessage(message), AIError.Flag.ContentBlocked);
1221
+ return AIError.is(id, AIError.Flag.ContentBlocked);
1217
1222
  }
1218
1223
 
1219
1224
  /**
@@ -27,12 +27,23 @@ export interface MCPServer {
27
27
  args?: string[];
28
28
  /** Environment variables */
29
29
  env?: Record<string, string>;
30
+ /**
31
+ * `literal`: env values are opaque plugin package data (Agent Plugins
32
+ * §§4.1/9.2) — exempt from env-name lookup and `!command` resolution.
33
+ */
34
+ envPolicy?: "literal";
30
35
  /** Working directory for stdio transport */
31
36
  cwd?: string;
32
37
  /** URL (for HTTP/SSE transport) */
33
38
  url?: string;
34
39
  /** HTTP headers (for HTTP transport) */
35
40
  headers?: Record<string, string>;
41
+ /**
42
+ * `origin-locked`: configured headers are literal package data pinned to the
43
+ * configured URL's origin (Agent Plugins §7.2.1) — never expanded, never
44
+ * forwarded cross-origin, and client-generated headers win case-insensitively.
45
+ */
46
+ headerPolicy?: "origin-locked";
36
47
  /** Authentication configuration */
37
48
  auth?: {
38
49
  type: "oauth" | "apikey";
@@ -43,6 +43,12 @@ export interface Skill {
43
43
  content: string;
44
44
  /** Parsed frontmatter */
45
45
  frontmatter?: SkillFrontmatter;
46
+ /**
47
+ * Filesystem-resolved plugin root this skill was packaged in (Agent Plugins
48
+ * §4.1). When set, every `skill://` resource access must realpath-resolve
49
+ * within this directory; symlinks may target other files inside it.
50
+ */
51
+ containRoot?: string;
46
52
  /** Source level */
47
53
  level: "user" | "project";
48
54
  /** Source metadata */
@@ -72,6 +72,10 @@ export const sayHelp = {
72
72
 
73
73
  export const searchHelp = { description: "Test web search providers" } satisfies CommandMetadata;
74
74
 
75
+ export const shareHelp = {
76
+ description: "Share a saved session via an encrypted link (same as /share)",
77
+ } satisfies CommandMetadata;
78
+
75
79
  export const setupHelp = {
76
80
  description: "Run onboarding setup or install dependencies for optional features",
77
81
  } satisfies CommandMetadata;
@@ -153,7 +153,7 @@ export async function renderGalleryState(
153
153
  const component = new ToolExecutionComponent(
154
154
  componentName,
155
155
  streamingArgs,
156
- { showImages: false },
156
+ { showImages: false, useBuiltInRenderer: !fixture.customRendered },
157
157
  tool,
158
158
  ui,
159
159
  getProjectDir(),
@@ -120,6 +120,11 @@ export const commands: CommandEntry[] = [
120
120
  load: () => import("./commands/say").then(m => m.default),
121
121
  help: commandHelp.sayHelp,
122
122
  },
123
+ {
124
+ name: "share",
125
+ load: () => import("./commands/share").then(m => m.default),
126
+ help: commandHelp.shareHelp,
127
+ },
123
128
  {
124
129
  name: "setup",
125
130
  load: () => import("./commands/setup").then(m => m.default),
@@ -5,7 +5,7 @@
5
5
  import { postmortem } from "@oh-my-pi/pi-utils";
6
6
  import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
7
7
  import { commitHelp as commandHelp } from "../cli/command-help";
8
- import { runCommitCommand } from "../commit";
8
+ import { CommitAbortedError, runCommitCommand } from "../commit";
9
9
  import type { CommitCommandArgs } from "../commit/types";
10
10
  import { initTheme } from "../modes/theme/theme";
11
11
 
@@ -41,7 +41,20 @@ export default class Commit extends Command {
41
41
  // is already written. Mirror the `runPrintMode` exit pattern from
42
42
  // `main.ts` so the CLI returns to the shell instead of stranding the user
43
43
  // on Ctrl+C (issue #1041).
44
- await runCommitCommand(cmd);
45
- await postmortem.quit(0);
44
+ let exitCode = 0;
45
+ try {
46
+ const { usedFallback } = await runCommitCommand(cmd);
47
+ // A commit written by the mechanical fallback is a degraded outcome:
48
+ // the agent did not do the work it was asked to do, so the command
49
+ // reports non-zero so callers can distinguish it from a real
50
+ // single-commit decision (issue #7835).
51
+ if (usedFallback) exitCode = 1;
52
+ } catch (error) {
53
+ if (!(error instanceof CommitAbortedError)) throw error;
54
+ // Failure already reported with a readable message; exit non-zero
55
+ // without letting the runtime dump a stack/minified-source blob.
56
+ exitCode = 1;
57
+ }
58
+ await postmortem.quit(exitCode);
46
59
  }
47
60
  }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Share a saved session as an encrypted link without launching the agent.
3
+ *
4
+ * `omp share <session>` accepts a session id (prefix) or a path to a session
5
+ * `.jsonl` and uploads the sealed snapshot exactly like the `/share` slash
6
+ * command, honoring `share.serverUrl`, `share.store`, and
7
+ * `share.redactSecrets`.
8
+ */
9
+
10
+ import { getAgentDir } from "@oh-my-pi/pi-utils";
11
+ import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
12
+ import { shareHelp as commandHelp } from "../cli/command-help";
13
+ import { Settings } from "../config/settings";
14
+ import { shareSession } from "../export/share";
15
+ import { buildSecretObfuscator } from "../secrets";
16
+ import { resolveResumableSession } from "../session/session-listing";
17
+ import { SessionManager } from "../session/session-manager";
18
+
19
+ export default class Share extends Command {
20
+ static description = commandHelp.description;
21
+ static args = {
22
+ session: Args.string({
23
+ description: "Session id (prefix) or path to a session .jsonl",
24
+ required: true,
25
+ }),
26
+ };
27
+ static flags = {
28
+ gist: Flags.boolean({
29
+ description: "Upload to a secret GitHub gist instead of the share server",
30
+ default: false,
31
+ }),
32
+ };
33
+
34
+ async run(): Promise<void> {
35
+ const { args, flags } = await this.parse(Share);
36
+
37
+ const sessionArg = args.session ?? "";
38
+ let sessionPath = sessionArg;
39
+ if (!sessionArg.includes("/") && !sessionArg.includes("\\") && !sessionArg.endsWith(".jsonl")) {
40
+ const match = await resolveResumableSession(sessionArg, process.cwd());
41
+ if (!match) {
42
+ process.stderr.write(`Session "${sessionArg}" not found.\n`);
43
+ process.exitCode = 1;
44
+ return;
45
+ }
46
+ sessionPath = match.session.path;
47
+ }
48
+
49
+ const sm = await SessionManager.open(sessionPath);
50
+ // Settings resolve against the session's own project so its
51
+ // share.redactSecrets/secrets.enabled policy governs, not the invoking cwd's.
52
+ const settings = await Settings.loadReadOnly({ cwd: sm.getCwd() });
53
+ // Same leak boundary as /share: a share blob leaves the machine, so honor
54
+ // share.redactSecrets with the full obfuscator built against the session's
55
+ // own project directory (its secrets.yml, not the invoking cwd's).
56
+ const obfuscator =
57
+ settings.get("share.redactSecrets") && settings.get("secrets.enabled")
58
+ ? await buildSecretObfuscator(sm.getCwd(), getAgentDir())
59
+ : undefined;
60
+
61
+ const result = await shareSession(sm, {
62
+ serverUrl: settings.get("share.serverUrl"),
63
+ store: flags.gist ? "gist" : settings.get("share.store"),
64
+ obfuscator,
65
+ });
66
+ const lines = [`Share URL: ${result.url}`];
67
+ if (result.gistUrl) lines.push(`Gist: ${result.gistUrl}`);
68
+ if (result.truncated) lines.push("Note: large content was trimmed to fit the share size limit.");
69
+ console.log(lines.join("\n"));
70
+ }
71
+ }