@oh-my-pi/pi-coding-agent 17.1.7 → 17.2.0

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 (246) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/dist/{CHANGELOG-5k4dq4g6.md → CHANGELOG-be1f2t8h.md} +127 -0
  3. package/dist/cli.js +9554 -12379
  4. package/dist/template-8vdv6xb4.js +1671 -0
  5. package/dist/template-f8wx9vfn.css +1355 -0
  6. package/dist/template-qat058wr.html +55 -0
  7. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  8. package/dist/types/advisor/advise-tool.d.ts +0 -7
  9. package/dist/types/advisor/runtime.d.ts +8 -11
  10. package/dist/types/advisor/transcript-recorder.d.ts +15 -0
  11. package/dist/types/async/job-manager.d.ts +11 -0
  12. package/dist/types/auto-thinking/classifier.d.ts +9 -2
  13. package/dist/types/cleanse/agent.d.ts +19 -0
  14. package/dist/types/cleanse/balance.d.ts +7 -0
  15. package/dist/types/cleanse/checkers.d.ts +13 -0
  16. package/dist/types/cleanse/index.d.ts +16 -0
  17. package/dist/types/cleanse/loop.d.ts +16 -0
  18. package/dist/types/cleanse/parsers.d.ts +13 -0
  19. package/dist/types/cleanse/progress.d.ts +14 -0
  20. package/dist/types/cleanse/types.d.ts +64 -0
  21. package/dist/types/cli/args.d.ts +2 -0
  22. package/dist/types/cli/session-picker.d.ts +14 -7
  23. package/dist/types/collab/guest.d.ts +21 -2
  24. package/dist/types/commands/cleanse.d.ts +23 -0
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/config/settings-schema.d.ts +63 -8
  27. package/dist/types/cursor-bridge-tools.d.ts +54 -0
  28. package/dist/types/cursor.d.ts +193 -8
  29. package/dist/types/edit/edit-clipboard.d.ts +19 -0
  30. package/dist/types/edit/hashline/diff.d.ts +9 -1
  31. package/dist/types/edit/index.d.ts +8 -1
  32. package/dist/types/edit/streaming.d.ts +8 -1
  33. package/dist/types/export/html/index.d.ts +2 -0
  34. package/dist/types/extensibility/extensions/runner.d.ts +19 -2
  35. package/dist/types/extensibility/extensions/types.d.ts +25 -1
  36. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +27 -1
  37. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +2 -0
  38. package/dist/types/internal-urls/local-protocol.d.ts +3 -2
  39. package/dist/types/launch/terminal-output-worker-client.d.ts +5 -0
  40. package/dist/types/launch/terminal-output-worker-protocol.d.ts +14 -0
  41. package/dist/types/launch/terminal-output-worker.d.ts +1 -0
  42. package/dist/types/lsp/client.d.ts +2 -0
  43. package/dist/types/main.d.ts +2 -0
  44. package/dist/types/mcp/manager.d.ts +33 -4
  45. package/dist/types/modes/components/codex-reset-fireworks.d.ts +51 -0
  46. package/dist/types/modes/components/read-tool-group.d.ts +12 -0
  47. package/dist/types/modes/components/session-selector.d.ts +6 -0
  48. package/dist/types/modes/components/status-line/component.d.ts +23 -0
  49. package/dist/types/modes/components/tool-execution.d.ts +16 -7
  50. package/dist/types/modes/components/usage-row.d.ts +2 -0
  51. package/dist/types/modes/controllers/mcp-command-controller.d.ts +26 -1
  52. package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
  53. package/dist/types/modes/interactive-mode.d.ts +8 -5
  54. package/dist/types/modes/rpc/rpc-client.d.ts +7 -0
  55. package/dist/types/modes/rpc/rpc-types.d.ts +16 -0
  56. package/dist/types/modes/theme/theme.d.ts +12 -1
  57. package/dist/types/modes/types.d.ts +2 -1
  58. package/dist/types/sdk.d.ts +1 -0
  59. package/dist/types/session/agent-session-events.d.ts +2 -0
  60. package/dist/types/session/agent-session-types.d.ts +36 -1
  61. package/dist/types/session/agent-session.d.ts +4 -2
  62. package/dist/types/session/async-job-delivery.d.ts +8 -0
  63. package/dist/types/session/claude-session-store.d.ts +13 -0
  64. package/dist/types/session/codex-session-store.d.ts +14 -0
  65. package/dist/types/session/credential-pin.d.ts +58 -0
  66. package/dist/types/session/foreign-session-import.d.ts +15 -0
  67. package/dist/types/session/foreign-session-jsonl.d.ts +9 -0
  68. package/dist/types/session/foreign-session-store.d.ts +23 -0
  69. package/dist/types/session/model-controls.d.ts +3 -3
  70. package/dist/types/session/session-advisors.d.ts +47 -2
  71. package/dist/types/session/session-entries.d.ts +19 -1
  72. package/dist/types/session/session-handoff.d.ts +4 -1
  73. package/dist/types/session/session-loader.d.ts +2 -0
  74. package/dist/types/session/session-maintenance.d.ts +1 -1
  75. package/dist/types/session/session-manager.d.ts +21 -0
  76. package/dist/types/session/session-tools.d.ts +25 -1
  77. package/dist/types/session/turn-recovery.d.ts +10 -4
  78. package/dist/types/system-prompt.d.ts +2 -1
  79. package/dist/types/task/executor.d.ts +11 -2
  80. package/dist/types/task/isolation-ownership.d.ts +34 -0
  81. package/dist/types/task/render.d.ts +7 -0
  82. package/dist/types/thinking.d.ts +18 -6
  83. package/dist/types/tools/acp-bridge.d.ts +28 -5
  84. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +1 -2
  85. package/dist/types/tools/browser/tab-worker.d.ts +1 -4
  86. package/dist/types/tools/grep.d.ts +17 -1
  87. package/dist/types/tools/hub/launch.d.ts +5 -1
  88. package/dist/types/tools/index.d.ts +4 -1
  89. package/dist/types/tools/path-utils.d.ts +19 -0
  90. package/dist/types/tools/read.d.ts +2 -0
  91. package/dist/types/tools/xdev.d.ts +2 -1
  92. package/dist/types/tui/output-block.d.ts +5 -5
  93. package/dist/types/utils/changelog.d.ts +19 -0
  94. package/dist/types/utils/git.d.ts +10 -0
  95. package/dist/types/utils/jj.d.ts +11 -4
  96. package/dist/types/web/search/types.d.ts +2 -2
  97. package/package.json +16 -12
  98. package/scripts/bundle-dist.ts +3 -1
  99. package/src/advisor/advise-tool.ts +0 -11
  100. package/src/advisor/runtime.ts +138 -24
  101. package/src/advisor/transcript-recorder.ts +56 -0
  102. package/src/async/job-manager.ts +30 -7
  103. package/src/auto-thinking/classifier.ts +48 -10
  104. package/src/cleanse/agent.ts +226 -0
  105. package/src/cleanse/balance.ts +79 -0
  106. package/src/cleanse/checkers.ts +996 -0
  107. package/src/cleanse/index.ts +190 -0
  108. package/src/cleanse/loop.ts +51 -0
  109. package/src/cleanse/parsers.ts +726 -0
  110. package/src/cleanse/progress.ts +50 -0
  111. package/src/cleanse/prompts/assignment.md +47 -0
  112. package/src/cleanse/types.ts +72 -0
  113. package/src/cli/args.ts +6 -0
  114. package/src/cli/flag-tables.ts +2 -0
  115. package/src/cli/gallery-fixtures/fs.ts +25 -0
  116. package/src/cli/session-picker.ts +34 -17
  117. package/src/cli/ttsr-cli.ts +19 -1
  118. package/src/cli/update-cli.ts +3 -0
  119. package/src/cli/usage-cli.ts +29 -4
  120. package/src/cli/worktree-cli.ts +28 -11
  121. package/src/cli-commands.ts +1 -0
  122. package/src/cli.ts +11 -1
  123. package/src/collab/guest.ts +37 -4
  124. package/src/collab/host.ts +1 -0
  125. package/src/commands/cleanse.ts +45 -0
  126. package/src/commands/launch.ts +6 -0
  127. package/src/config/model-registry.ts +103 -25
  128. package/src/config/settings-schema.ts +65 -6
  129. package/src/config/settings.ts +25 -0
  130. package/src/cursor-bridge-tools.ts +81 -0
  131. package/src/cursor.ts +463 -12
  132. package/src/discovery/claude-plugins.ts +144 -34
  133. package/src/edit/edit-clipboard.ts +23 -0
  134. package/src/edit/hashline/diff.ts +49 -10
  135. package/src/edit/hashline/execute.ts +38 -6
  136. package/src/edit/hashline/filesystem.ts +27 -3
  137. package/src/edit/index.ts +12 -2
  138. package/src/edit/renderer.ts +4 -4
  139. package/src/edit/streaming.ts +17 -2
  140. package/src/export/html/index.ts +17 -10
  141. package/src/export/html/template.js +1 -1
  142. package/src/extensibility/extensions/runner.ts +70 -0
  143. package/src/extensibility/extensions/types.ts +30 -0
  144. package/src/extensibility/legacy-pi-ai-shim.ts +46 -1
  145. package/src/extensibility/legacy-pi-coding-agent-shim.ts +12 -13
  146. package/src/internal-urls/local-protocol.ts +3 -2
  147. package/src/internal-urls/mcp-protocol.ts +4 -1
  148. package/src/launch/broker.ts +14 -4
  149. package/src/launch/terminal-output-worker-client.ts +53 -0
  150. package/src/launch/terminal-output-worker-protocol.ts +11 -0
  151. package/src/launch/terminal-output-worker.ts +23 -0
  152. package/src/lsp/client.ts +18 -3
  153. package/src/lsp/index.ts +4 -0
  154. package/src/lsp/render.ts +1 -1
  155. package/src/main.ts +127 -56
  156. package/src/mcp/manager.ts +120 -18
  157. package/src/modes/acp/acp-agent.ts +27 -18
  158. package/src/modes/acp/acp-event-mapper.ts +38 -4
  159. package/src/modes/components/chat-transcript-builder.ts +30 -11
  160. package/src/modes/components/codex-reset-fireworks.ts +369 -0
  161. package/src/modes/components/read-tool-group.ts +159 -17
  162. package/src/modes/components/session-selector.ts +19 -3
  163. package/src/modes/components/settings-selector.ts +9 -1
  164. package/src/modes/components/status-line/component.ts +381 -54
  165. package/src/modes/components/tool-execution.ts +78 -31
  166. package/src/modes/components/usage-row.ts +10 -5
  167. package/src/modes/controllers/event-controller.ts +26 -4
  168. package/src/modes/controllers/mcp-command-controller.ts +68 -3
  169. package/src/modes/controllers/selector-controller.ts +94 -36
  170. package/src/modes/controllers/tan-command-controller.ts +14 -0
  171. package/src/modes/interactive-mode.ts +67 -64
  172. package/src/modes/prompt-action-autocomplete.ts +5 -3
  173. package/src/modes/rpc/rpc-client.ts +18 -0
  174. package/src/modes/rpc/rpc-mode.ts +16 -1
  175. package/src/modes/rpc/rpc-types.ts +11 -0
  176. package/src/modes/theme/theme.ts +151 -6
  177. package/src/modes/types.ts +2 -1
  178. package/src/modes/utils/ui-helpers.ts +38 -21
  179. package/src/prompts/goals/guided-goal-interview.md +41 -6
  180. package/src/prompts/system/auto-thinking-difficulty.md +4 -2
  181. package/src/prompts/system/plan-mode-active.md +2 -2
  182. package/src/prompts/system/system-prompt.md +3 -0
  183. package/src/prompts/system/vibe-mode-active.md +4 -1
  184. package/src/prompts/system/xdev-mount-notice.md +1 -1
  185. package/src/prompts/tools/bash.md +15 -17
  186. package/src/prompts/tools/browser.md +1 -0
  187. package/src/prompts/tools/checkpoint.md +1 -1
  188. package/src/prompts/tools/glob.md +7 -6
  189. package/src/prompts/tools/goal.md +1 -1
  190. package/src/prompts/tools/grep.md +7 -6
  191. package/src/sdk.ts +178 -15
  192. package/src/session/agent-session-events.ts +1 -0
  193. package/src/session/agent-session-types.ts +40 -1
  194. package/src/session/agent-session.ts +330 -179
  195. package/src/session/async-job-delivery.ts +8 -0
  196. package/src/session/claude-session-store.ts +426 -0
  197. package/src/session/codex-session-store.ts +673 -0
  198. package/src/session/credential-pin.ts +93 -0
  199. package/src/session/foreign-session-import.ts +52 -0
  200. package/src/session/foreign-session-jsonl.ts +29 -0
  201. package/src/session/foreign-session-store.ts +26 -0
  202. package/src/session/model-controls.ts +15 -7
  203. package/src/session/session-advisors.ts +142 -23
  204. package/src/session/session-entries.ts +21 -1
  205. package/src/session/session-handoff.ts +20 -3
  206. package/src/session/session-history-format.ts +31 -6
  207. package/src/session/session-loader.ts +25 -9
  208. package/src/session/session-maintenance.ts +59 -11
  209. package/src/session/session-manager.ts +61 -0
  210. package/src/session/session-tools.ts +107 -5
  211. package/src/session/settings-stream-fn.ts +1 -0
  212. package/src/session/turn-recovery.ts +97 -51
  213. package/src/slash-commands/builtin-registry.ts +136 -5
  214. package/src/system-prompt.ts +3 -2
  215. package/src/task/executor.ts +17 -4
  216. package/src/task/isolation-ownership.ts +106 -0
  217. package/src/task/render.ts +20 -4
  218. package/src/task/worktree.ts +8 -0
  219. package/src/thinking.ts +29 -10
  220. package/src/tools/acp-bridge.ts +52 -8
  221. package/src/tools/ask.ts +3 -3
  222. package/src/tools/ast-edit.ts +9 -2
  223. package/src/tools/browser/cmux/cmux-tab.ts +9 -14
  224. package/src/tools/browser/tab-worker.ts +12 -35
  225. package/src/tools/browser.ts +7 -2
  226. package/src/tools/checkpoint.ts +0 -13
  227. package/src/tools/gh-renderer.ts +3 -3
  228. package/src/tools/grep.ts +64 -8
  229. package/src/tools/hub/launch.ts +10 -15
  230. package/src/tools/index.ts +38 -5
  231. package/src/tools/path-utils.ts +88 -0
  232. package/src/tools/read.ts +3 -0
  233. package/src/tools/write.ts +44 -3
  234. package/src/tools/xdev.ts +39 -14
  235. package/src/tui/code-cell.ts +4 -4
  236. package/src/tui/output-block.ts +25 -8
  237. package/src/utils/changelog.ts +144 -4
  238. package/src/utils/git.ts +61 -14
  239. package/src/utils/jj.ts +19 -13
  240. package/src/utils/shell-snapshot-fn-env.sh +5 -2
  241. package/src/web/search/providers/codex.ts +34 -0
  242. package/src/web/search/render.ts +2 -2
  243. package/src/web/search/types.ts +1 -1
  244. package/dist/types/goals/guided-setup.d.ts +0 -30
  245. package/src/goals/guided-setup.ts +0 -171
  246. package/src/prompts/goals/guided-goal-system.md +0 -33
@@ -1,23 +1,69 @@
1
1
  import type { AgentEvent, AgentTool, AgentToolContext } from "@oh-my-pi/pi-agent-core";
2
- import type { CursorMcpCall, CursorShellStreamCallbacks, CursorTodoSnapshot, CursorExecHandlers as ICursorExecHandlers, ToolResultMessage } from "@oh-my-pi/pi-ai";
2
+ import type { CursorMcpCall, CursorMcpResource, CursorMcpResourceContent, CursorShellStreamCallbacks, CursorTodoSnapshot, CursorExecHandlers as ICursorExecHandlers, ToolResultMessage } from "@oh-my-pi/pi-ai";
3
+ import type { MCPResourceReadResult } from "./mcp/types.js";
3
4
  import type { TodoPhase } from "./tools/todo.js";
5
+ /**
6
+ * A tool instance the bridge can run, matching the erased shape the session's
7
+ * tool registry stores. The concrete tools have narrower `execute` parameter
8
+ * types than the default `AgentTool`, which only unify through this alias.
9
+ */
10
+ type CursorBridgeTool = AgentTool<any, any, any>;
11
+ /**
12
+ * The live MCP connections Cursor's resource frames are answered from.
13
+ *
14
+ * Named so every construction site can hand over the same adapter; a session
15
+ * and its advisors share one set of connections.
16
+ */
17
+ export interface CursorMcpResourceAdapter {
18
+ serverNames(): string[];
19
+ getServerResources(name: string): Promise<{
20
+ resources: {
21
+ uri: string;
22
+ name?: string;
23
+ description?: string;
24
+ mimeType?: string;
25
+ }[];
26
+ } | undefined>;
27
+ readServerResource(name: string, uri: string): Promise<MCPResourceReadResult | undefined>;
28
+ }
4
29
  interface CursorExecBridgeOptions {
5
30
  cwd: string;
6
31
  getCwd?: () => string;
7
32
  tools: Map<string, AgentTool>;
8
33
  /** Resolves execution overrides (mounted-device permission wrappers) before the canonical map. */
9
34
  getExecutableTool?: (name: string) => AgentTool | undefined;
35
+ /**
36
+ * The `replace`-mode `edit` instance `pi_edit` must run, when the session
37
+ * granted `edit` at all.
38
+ *
39
+ * `PiEditExecArgs` is that mode's schema verbatim, and the session's own
40
+ * `edit` may be in any mode — `hashline` by default — whose schema rejects
41
+ * `old_text`/`new_text` outright. {@link tools} therefore cannot be trusted
42
+ * for this one frame: a session that starts on another provider keeps its
43
+ * configured instance in the map (only Cursor sessions move `edit` out), and
44
+ * switching to Cursor later does not rebuild the roster.
45
+ */
46
+ getEditReplaceTool?: () => CursorBridgeTool | undefined;
10
47
  getToolContext?: () => AgentToolContext | undefined;
11
48
  emitEvent?: (event: AgentEvent) => void;
12
49
  /**
13
- * Whether the Cursor native `delete` frame may remove files. Unlike every
14
- * other exec handler, `executeDelete` mutates the filesystem directly instead
15
- * of consulting {@link tools}, so a background read-only advisor could delete
16
- * workspace files it was never granted a mutating tool for (issue #5680
17
- * review). Defaults to allowed to preserve the primary agent's behavior;
18
- * callers with a restricted tool set (advisors) opt out.
50
+ * Whether frames that mutate the filesystem WITHOUT running a registry tool
51
+ * may do so: the native `delete` frame, and a `read_mcp_resource` carrying
52
+ * `download_path`. Both write or remove workspace files directly instead of
53
+ * consulting {@link tools}, so a background read-only advisor could touch
54
+ * files it was never granted a mutating tool for (issue #5680 review).
55
+ *
56
+ * This is a grant, not a policy: it answers "did the session hand this
57
+ * channel a file-writing tool", which callers derive from their own roster
58
+ * before any bridge-specific rewriting. The primary Cursor session moves
59
+ * `edit` out of {@link tools} and serves it through
60
+ * {@link getEditReplaceTool}, so reading the map here would deny an
61
+ * edit-only session. Defaults to allowed
62
+ * to preserve the primary agent's behavior; callers with a restricted tool
63
+ * set (advisors) opt out. The user's approval policy is resolved separately,
64
+ * per call.
19
65
  */
20
- allowNativeDelete?: boolean;
66
+ allowDirectFileMutation?: boolean;
21
67
  /**
22
68
  * Mirror Cursor's server-owned todo list into local session state. Cursor
23
69
  * resolves `update_todos` / `read_todos` remotely, so without this bridge
@@ -30,18 +76,148 @@ interface CursorExecBridgeOptions {
30
76
  * Cursor emits no local `todo` toolResult, so nothing else records it.
31
77
  */
32
78
  persistTodoPhases?: (phases: TodoPhase[]) => void;
79
+ /**
80
+ * Build a `grep` tool honoring a frame's own context width and match cap.
81
+ *
82
+ * The modern `pi_grep` frame carries both, and the shared `grep` instance
83
+ * is fixed to the session settings at construction — so without this the
84
+ * two fields are silently dropped. Callers that cannot supply it keep the
85
+ * shared instance and the session's defaults.
86
+ *
87
+ * The returned tool is executed as-is. Callers whose registry tools carry an
88
+ * approval wrapper MUST apply the same wrapper here, or a frame supplying
89
+ * either field silently escapes the approval gate that every other call
90
+ * goes through.
91
+ */
92
+ createGrepTool?(options: {
93
+ context?: number;
94
+ totalMatchLimit?: number;
95
+ }): CursorBridgeTool | undefined;
96
+ /**
97
+ * The session's live MCP connections, for Cursor's resource frames.
98
+ *
99
+ * `list_mcp_resources` / `read_mcp_resource` ask what this client's servers
100
+ * advertise. Without this the bridge answers an empty catalog and
101
+ * `not_found`, hiding resources the session is in fact connected to.
102
+ *
103
+ * `getServerResources` is async because a server's catalog loads in the
104
+ * background after its tools register: a frame arriving in that window would
105
+ * otherwise read the not-yet-populated cache and report an empty catalog,
106
+ * which is indistinguishable from a server that advertises nothing.
107
+ */
108
+ mcpResources?: CursorMcpResourceAdapter;
33
109
  }
34
110
  export declare class CursorExecHandlers implements ICursorExecHandlers {
35
111
  private options;
36
112
  constructor(options: CursorExecBridgeOptions);
113
+ /**
114
+ * Modern Cursor builds paginate the legacy `read` frame with
115
+ * `offset`/`limit`, exactly as `pi_read` does. Dropping them returns the
116
+ * whole file (or its own truncation) for every page, so a model walking a
117
+ * large file never advances. Composed with the same helper, so both frames
118
+ * translate a range identically.
119
+ */
37
120
  read(args: Parameters<NonNullable<ICursorExecHandlers["read"]>>[0]): Promise<ToolResultMessage<unknown>>;
38
121
  ls(args: Parameters<NonNullable<ICursorExecHandlers["ls"]>>[0]): Promise<ToolResultMessage<unknown>>;
122
+ /**
123
+ * Modern Cursor builds paginate this frame with `offset`. The local `grep`
124
+ * paginates by file through `skip`, which is the same unit its own
125
+ * "use skip=N for the next page" advice counts in — so an unforwarded
126
+ * offset re-runs the identical search and returns page one forever.
127
+ */
39
128
  grep(args: Parameters<NonNullable<ICursorExecHandlers["grep"]>>[0]): Promise<ToolResultMessage<unknown>>;
40
129
  write(args: Parameters<NonNullable<ICursorExecHandlers["write"]>>[0]): Promise<ToolResultMessage<unknown>>;
41
130
  delete(args: Parameters<NonNullable<ICursorExecHandlers["delete"]>>[0]): Promise<ToolResultMessage<unknown>>;
42
131
  shell(args: Parameters<NonNullable<ICursorExecHandlers["shell"]>>[0]): Promise<ToolResultMessage<unknown>>;
43
132
  shellStream(args: Parameters<NonNullable<ICursorExecHandlers["shellStream"]>>[0], callbacks: CursorShellStreamCallbacks): Promise<ToolResultMessage<unknown>>;
44
133
  diagnostics(args: Parameters<NonNullable<ICursorExecHandlers["diagnostics"]>>[0]): Promise<ToolResultMessage<unknown>>;
134
+ /**
135
+ * Modern Cursor CLI Pi tool frames (`ExecServerMessage` 45-51).
136
+ *
137
+ * These are a separate frame family from the legacy `read`/`shell`/... set,
138
+ * not aliases: different args, different result oneofs, and no `tool_call_id`
139
+ * (the provider mints one and passes it in `call.toolCallId`). Each maps onto
140
+ * the local tool with matching semantics, so the same approval, sandboxing
141
+ * and event plumbing applies as for a model-issued call.
142
+ */
143
+ /**
144
+ * `offset`/`limit` are a 1-indexed start line plus a line count (verified
145
+ * against the reference `LocalPiReadExecutor`), which is exactly the local
146
+ * `read` tool's `:N+K` inline selector — the tool takes no range kwargs, so
147
+ * the range has to be composed onto the path or ranged reads silently
148
+ * return the whole file.
149
+ */
150
+ piRead(call: Parameters<NonNullable<ICursorExecHandlers["piRead"]>>[0]): Promise<ToolResultMessage<unknown>>;
151
+ piBash(call: Parameters<NonNullable<ICursorExecHandlers["piBash"]>>[0]): Promise<ToolResultMessage<unknown>>;
152
+ /**
153
+ * `PiEditExecArgs` is the local `edit` tool's replace mode verbatim: a path
154
+ * plus `old_text`/`new_text` pairs. The tool's schema is snake_case, so the
155
+ * proto's camelCase accessors are mapped back on the way in.
156
+ *
157
+ * The replace-mode instance is requested explicitly rather than resolved
158
+ * from {@link CursorExecBridgeOptions.tools}: the registry's `edit` is in
159
+ * the session's configured mode, whose schema rejects these arguments.
160
+ */
161
+ piEdit(call: Parameters<NonNullable<ICursorExecHandlers["piEdit"]>>[0]): Promise<ToolResultMessage<unknown>>;
162
+ piWrite(call: Parameters<NonNullable<ICursorExecHandlers["piWrite"]>>[0]): Promise<ToolResultMessage<unknown>>;
163
+ /**
164
+ * `literal` makes the pattern a fixed string; the local tool is regex-only,
165
+ * so the pattern is escaped on the way in (same translation the legacy pi
166
+ * shim does).
167
+ *
168
+ * `context` and `limit` are not expressible in the model-facing schema —
169
+ * context width comes from settings fixed at tool construction — so the
170
+ * frame's values are honored by building a per-call `grep` through
171
+ * {@link CursorExecBridgeOptions.createGrepTool}. Both are `optional int32`,
172
+ * so a present `0` context means "no context lines", not "use the default".
173
+ * Without the factory the shared instance runs with session defaults.
174
+ */
175
+ piGrep(call: Parameters<NonNullable<ICursorExecHandlers["piGrep"]>>[0]): Promise<ToolResultMessage<unknown>>;
176
+ /**
177
+ * `pi_find` is a filename search, which is the local `glob` tool — not
178
+ * `grep`. Its `pattern` is a glob, joined onto `path` because `glob` takes a
179
+ * single combined path spec.
180
+ *
181
+ * `limit` is `optional int32`, so `0` is present rather than unset; the
182
+ * reference clamps it with `Math.max(1, limit ?? 1000)`, and an unset limit
183
+ * leaves the local tool's own default in place.
184
+ */
185
+ piFind(call: Parameters<NonNullable<ICursorExecHandlers["piFind"]>>[0]): Promise<ToolResultMessage<unknown>>;
186
+ /**
187
+ * Redirected to `read`, which lists directories — same as the legacy `ls`.
188
+ * The frame's entry `limit` is not mapped; see {@link piLsPath}.
189
+ */
190
+ piLs(call: Parameters<NonNullable<ICursorExecHandlers["piLs"]>>[0]): Promise<ToolResultMessage<unknown>>;
191
+ /**
192
+ * The resources this client's MCP servers advertise.
193
+ *
194
+ * Cursor addresses a later read by `server`, so every entry carries the name
195
+ * it came from. An absent `server` filter means "all of them".
196
+ */
197
+ listMcpResources({ server }: {
198
+ server?: string;
199
+ }): Promise<CursorMcpResource[]>;
200
+ /**
201
+ * Read one resource, or `null` when the server or uri is unknown.
202
+ *
203
+ * MCP returns a list of content items; the wire carries exactly one text or
204
+ * blob. Text items are joined, since a multi-part text resource is one
205
+ * document; otherwise the first blob stands in. `blob` arrives base64 and
206
+ * the wire wants bytes.
207
+ *
208
+ * A `downloadPath` frame is a different contract: write the bytes to that
209
+ * workspace-relative path and answer with the path alone, so a large binary
210
+ * lands on disk instead of in the model's context. That makes it a workspace
211
+ * mutation reached without a registry tool, so it is gated exactly like the
212
+ * native `delete` frame — on the session actually granting a file-writing
213
+ * tool, and on the user's `write`-tier policy. The gate runs before the read
214
+ * so a refused download never fetches the resource either.
215
+ */
216
+ readMcpResource({ server, uri, downloadPath, }: {
217
+ server: string;
218
+ uri: string;
219
+ downloadPath?: string;
220
+ }): Promise<CursorMcpResourceContent | null>;
45
221
  /**
46
222
  * Settle a completed native Cursor todo call, mirroring its list when the
47
223
  * server supplied an authoritative one.
@@ -76,5 +252,14 @@ export declare class CursorExecHandlers implements ICursorExecHandlers {
76
252
  */
77
253
  todoSync(snapshot: CursorTodoSnapshot | null, toolCallId: string, error?: string | null): ToolResultMessage;
78
254
  mcp(call: CursorMcpCall): Promise<ToolResultMessage<unknown>>;
255
+ /**
256
+ * Resolve an MCP call's approval without running it.
257
+ *
258
+ * Same resolution the wrapper applies at execution time, minus the
259
+ * execution: an unknown tool is not approvable, and a `prompt` is not an
260
+ * approval — the frame has no way to carry an interactive question, and the
261
+ * user is asked for real when the call itself arrives.
262
+ */
263
+ mcpApprovalPreflight(call: CursorMcpCall): Promise<boolean>;
79
264
  }
80
265
  export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Session-bound edit clipboard register.
3
+ *
4
+ * `CUT`/`PASTE` hashline ops share one {@link Clipboard} per session so
5
+ * content captured by one edit call can be pasted by a later one (and across
6
+ * files within one call). The executor works on a fork per batch and commits
7
+ * it back only after every write lands — see `executeHashlineSingle`.
8
+ */
9
+ import type { Clipboard } from "@oh-my-pi/hashline";
10
+ interface EditClipboardOwner {
11
+ editClipboard?: Clipboard;
12
+ }
13
+ /**
14
+ * Look up (or lazily create) the clipboard register attached to a session.
15
+ * Storage lives on `session.editClipboard` so it ages out exactly with the
16
+ * session itself.
17
+ */
18
+ export declare function getEditClipboard(session: EditClipboardOwner): Clipboard;
19
+ export {};
@@ -1,4 +1,4 @@
1
- import { type PatchSection, type SnapshotStore } from "@oh-my-pi/hashline";
1
+ import { type Clipboard, type PatchSection, type SnapshotStore } from "@oh-my-pi/hashline";
2
2
  export interface HashlineDiffOptions {
3
3
  /**
4
4
  * Use the streaming-tolerant applier ({@link PatchSection.applyPartialTo})
@@ -12,6 +12,14 @@ export interface HashlineDiffOptions {
12
12
  * authoring input; the final apply path still validates through Patcher.
13
13
  */
14
14
  skipHashValidation?: boolean;
15
+ /**
16
+ * Clipboard register shared across the sections of one patch preview.
17
+ * `CUT` in an earlier section feeds `PASTE` in a later one, so the preview
18
+ * matches apply. Multi-section previews MUST thread one register through
19
+ * sections in patch order; omitted, each section gets a
20
+ * private register (same-file cut/paste still previews correctly).
21
+ */
22
+ clipboard?: Clipboard;
15
23
  }
16
24
  export declare function computeHashlineSectionDiff(section: PatchSection, cwd: string, snapshots: SnapshotStore, options?: HashlineDiffOptions): Promise<{
17
25
  diff: string;
@@ -33,7 +33,14 @@ export declare class EditTool implements AgentTool<TInput> {
33
33
  readonly loadMode = "essential";
34
34
  readonly concurrency = "exclusive";
35
35
  readonly strict = true;
36
- constructor(session: ToolSession);
36
+ /**
37
+ * `mode` pins the edit variant for this instance, for callers whose protocol
38
+ * fixes the shape of an edit. The Cursor `pi_edit` frame carries
39
+ * `old_text`/`new_text` pairs, which only `replace` accepts — under the
40
+ * default `hashline` mode those args do not match the schema at all. Left
41
+ * unset, the env/settings resolution applies as before.
42
+ */
43
+ constructor(session: ToolSession, mode?: EditMode);
37
44
  get mode(): EditMode;
38
45
  get description(): string;
39
46
  get parameters(): TInput;
@@ -12,7 +12,7 @@
12
12
  * The shared renderer / `ToolExecutionComponent` consult the strategy via
13
13
  * the injected `editMode` rather than probing argument shape.
14
14
  */
15
- import { type SnapshotStore } from "@oh-my-pi/hashline";
15
+ import { type Clipboard, type SnapshotStore } from "@oh-my-pi/hashline";
16
16
  import type { Theme } from "../modes/theme/theme.js";
17
17
  import { type EditMode, resolveEditMode } from "../utils/edit-mode.js";
18
18
  export interface PerFileDiffPreview {
@@ -34,6 +34,13 @@ export interface StreamingDiffContext {
34
34
  * not flicker in the preview.
35
35
  */
36
36
  isStreaming?: boolean;
37
+ /**
38
+ * Session-persistent clipboard register (`CUT`/`PASTE`). Previews
39
+ * fork it per frame — never mutating it — so a `PASTE` of content cut in
40
+ * an earlier edit call (or an earlier section of this patch) renders the
41
+ * real rows.
42
+ */
43
+ clipboard?: Clipboard;
37
44
  }
38
45
  /**
39
46
  * Per-file projection of a streamed edit payload. Pairs one target file path
@@ -3,6 +3,8 @@ import type { SessionEntry, SessionHeader } from "../../session/session-entries.
3
3
  import { SessionManager } from "../../session/session-manager.js";
4
4
  import type { ExportThemeNames } from "./args.js";
5
5
  export { type ExportThemeNames, parseExportArgs } from "./args.js";
6
+ /** Resolve a Bun file-loader value without parsing Windows drive letters as URL schemes. */
7
+ export declare function resolveBundledHtmlAssetPath(assetPath: string, moduleDir?: string): string;
6
8
  /** Compose the standalone export template: minified CSS, tool renderers, and viewer JS inlined. */
7
9
  export declare function getTemplate(): string;
8
10
  export interface ExportOptions {
@@ -8,9 +8,10 @@ import type { ModelRegistry } from "../../config/model-registry.js";
8
8
  import type { Settings } from "../../config/settings.js";
9
9
  import type { LocalProtocolOptions } from "../../internal-urls/local-protocol.js";
10
10
  import type { MemoryRuntimeContext } from "../../memory-backend/index.js";
11
+ import type { AsyncJobSnapshot } from "../../session/agent-session.js";
11
12
  import type { SessionManager } from "../../session/session-manager.js";
12
13
  import type { BranchHandler, NavigateTreeHandler, NewSessionHandler } from "../session-handler-types.js";
13
- import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, SessionStopEvent, SessionStopEventResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types.js";
14
+ import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, McpNotificationEvent, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, SessionStopEvent, SessionStopEventResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types.js";
14
15
  /** Combined result from all before_agent_start handlers */
15
16
  interface BeforeAgentStartCombinedResult {
16
17
  messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
@@ -73,7 +74,7 @@ export declare class ExtensionRunner {
73
74
  markToolCallEmitted(toolCallId: string, toolName: string): void;
74
75
  /** Consumes a {@link markToolCallEmitted} marker; true when the loop already emitted. */
75
76
  consumeToolCallEmitted(toolCallId: string, toolName: string): boolean;
76
- constructor(extensions: Extension[], runtime: ExtensionRuntime, cwd: string, sessionManager: SessionManager, modelRegistry: ModelRegistry, getMemory?: () => MemoryRuntimeContext | undefined, settings?: Settings | undefined, localProtocolOptions?: LocalProtocolOptions | undefined);
77
+ constructor(extensions: Extension[], runtime: ExtensionRuntime, cwd: string, sessionManager: SessionManager, modelRegistry: ModelRegistry, getMemory?: () => MemoryRuntimeContext | undefined, settings?: Settings | undefined, localProtocolOptions?: LocalProtocolOptions | undefined, getAsyncJobSnapshot?: () => AsyncJobSnapshot | null);
77
78
  initialize(actions: ExtensionActions, contextActions: ExtensionContextActions, commandContextActions?: ExtensionCommandContextActions, uiContext?: ExtensionUIContext): void;
78
79
  /**
79
80
  * Forward a `credential_disabled` event from `AuthStorage` to extension handlers.
@@ -90,6 +91,22 @@ export declare class ExtensionRunner {
90
91
  * {@link onError} via {@link emit}'s normal isolation.
91
92
  */
92
93
  emitCredentialDisabled(event: CredentialDisabledEvent): Promise<void>;
94
+ /**
95
+ * Forward an MCP server notification to extension handlers.
96
+ *
97
+ * If {@link initialize} has not yet run, the notification is buffered and replayed
98
+ * once initialize wires the runtime/UI context. Matches the credential-disabled
99
+ * deferral above: the sdk.ts bridge registers `MCPManager.addNotificationListener`
100
+ * inside `createAgentSession` — BEFORE the mode controller calls `initialize()` on
101
+ * this runner — so notification frames drained by the manager (either fresh
102
+ * arrivals or replay from its own startup buffer) can reach us pre-init. Without
103
+ * this buffer they would evaporate for a second time here.
104
+ *
105
+ * Bounded at {@link MAX_PENDING_MCP_NOTIFICATIONS}; oldest entries drop under
106
+ * pressure. Never throws; per-handler errors are routed through {@link onError}
107
+ * via {@link emit}'s normal isolation.
108
+ */
109
+ emitMcpNotification(event: Omit<McpNotificationEvent, "type">): Promise<void>;
93
110
  /** Emits a session stop pass that can be cancelled with the active settle signal. */
94
111
  emitSessionStop(event: Omit<SessionStopEvent, "type">): Promise<SessionStopEventResult | undefined>;
95
112
  getUIContext(): ExtensionUIContext;
@@ -26,6 +26,7 @@ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol.js
26
26
  import type { MemoryRuntimeContext } from "../../memory-backend/index.js";
27
27
  import type { CustomEditor } from "../../modes/components/custom-editor.js";
28
28
  import type { Theme } from "../../modes/theme/theme.js";
29
+ import type { AsyncJobSnapshot } from "../../session/agent-session.js";
29
30
  import type { CompactMode } from "../../session/compact-modes.js";
30
31
  import type { CustomMessage, CustomMessagePayload } from "../../session/messages.js";
31
32
  import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager.js";
@@ -276,6 +277,8 @@ export interface ExtensionContext {
276
277
  ui: ExtensionUIContext;
277
278
  /** Get current context usage for the active model. */
278
279
  getContextUsage(): ContextUsage | undefined;
280
+ /** Get a read-only snapshot of async jobs owned by this session. */
281
+ getAsyncJobSnapshot(): AsyncJobSnapshot | null;
279
282
  /** Compact the session context (interactive mode shows UI). */
280
283
  compact(instructionsOrOptions?: string | CompactOptions): Promise<void>;
281
284
  /** Whether UI is available (false in print/RPC mode) */
@@ -494,6 +497,26 @@ export interface CredentialDisabledEvent {
494
497
  /** Verbatim error captured for forensics (truncated upstream). */
495
498
  disabledCause: string;
496
499
  }
500
+ /**
501
+ * Fired for every JSON-RPC notification received from a connected MCP server,
502
+ * AFTER the runtime's own handling of known list/update methods. Unknown or
503
+ * server-custom methods are delivered too — extensions can bridge them into
504
+ * session behavior by inspecting `method`/`params` and injecting a follow-up
505
+ * via `pi.sendMessage(..., { deliverAs })` or `pi.sendUserMessage(...)`.
506
+ */
507
+ export interface McpNotificationEvent {
508
+ type: "mcp_notification";
509
+ /**
510
+ * Server name as declared in the MCP config (raw, unsanitized). Note this
511
+ * differs from the sanitized prefix used in `mcp__<sanitized_server>_<tool>`
512
+ * tool names — filter by this raw name, not by tool-name prefix matching.
513
+ */
514
+ server: string;
515
+ /** JSON-RPC method (e.g. `notifications/tools/list_changed`, or server-custom). */
516
+ method: string;
517
+ /** JSON-RPC params, opaque to the runtime. */
518
+ params: unknown;
519
+ }
497
520
  /** Fired when user executes a bash command via ! or !! prefix */
498
521
  export interface UserBashEvent {
499
522
  type: "user_bash";
@@ -639,7 +662,7 @@ export declare function isToolCallEventType<TName extends string, TInput extends
639
662
  input: TInput;
640
663
  };
641
664
  /** Union of all event types */
642
- export type ExtensionEvent = ResourcesDiscoverEvent | SessionEvent | ContextEvent | BeforeProviderRequestEvent | AfterProviderResponseEvent | BeforeAgentStartEvent | AgentStartEvent | AgentEndEvent | SessionStopEvent | TurnStartEvent | TurnEndEvent | MessageStartEvent | MessageUpdateEvent | MessageEndEvent | ToolExecutionStartEvent | ToolExecutionUpdateEvent | ToolExecutionEndEvent | AutoCompactionStartEvent | AutoCompactionEndEvent | AutoRetryStartEvent | AutoRetryEndEvent | TtsrTriggeredEvent | TodoReminderEvent | GoalUpdatedEvent | CredentialDisabledEvent | UserBashEvent | UserPythonEvent | InputEvent | ToolCallEvent | ToolResultEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent;
665
+ export type ExtensionEvent = ResourcesDiscoverEvent | SessionEvent | ContextEvent | BeforeProviderRequestEvent | AfterProviderResponseEvent | BeforeAgentStartEvent | AgentStartEvent | AgentEndEvent | SessionStopEvent | TurnStartEvent | TurnEndEvent | MessageStartEvent | MessageUpdateEvent | MessageEndEvent | ToolExecutionStartEvent | ToolExecutionUpdateEvent | ToolExecutionEndEvent | AutoCompactionStartEvent | AutoCompactionEndEvent | AutoRetryStartEvent | AutoRetryEndEvent | TtsrTriggeredEvent | TodoReminderEvent | GoalUpdatedEvent | CredentialDisabledEvent | McpNotificationEvent | UserBashEvent | UserPythonEvent | InputEvent | ToolCallEvent | ToolResultEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent;
643
666
  export interface ContextEventResult {
644
667
  messages?: AgentMessage[];
645
668
  }
@@ -748,6 +771,7 @@ export interface ExtensionAPI {
748
771
  on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;
749
772
  on(event: "user_bash", handler: ExtensionHandler<UserBashEvent, UserBashEventResult>): void;
750
773
  on(event: "user_python", handler: ExtensionHandler<UserPythonEvent, UserPythonEventResult>): void;
774
+ on(event: "mcp_notification", handler: ExtensionHandler<McpNotificationEvent>): void;
751
775
  /** Register a tool that the LLM can call. */
752
776
  registerTool<TParams extends TSchema = TSchema, TDetails = unknown>(tool: ToolDefinition<TParams, TDetails>): void;
753
777
  /** Register a custom command. */
@@ -19,7 +19,7 @@
19
19
  * `types.ts` via the `export *` below — pi-ai still exports both as types,
20
20
  * only the runtime `Type` builder and `StringEnum()` helper were removed.
21
21
  */
22
- import type { Api, Model } from "@oh-my-pi/pi-ai";
22
+ import type { Api, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
23
23
  import type { Effort } from "@oh-my-pi/pi-catalog/effort";
24
24
  import { calculateCost, getBundledModel, getBundledModels, getBundledProviders, modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
25
25
  import { type TSchema, Type } from "./typebox.js";
@@ -32,6 +32,15 @@ export interface StringEnumOptions<T extends string> {
32
32
  export declare function StringEnum<T extends string | number>(values: readonly T[] | Record<string, T>, options?: StringEnumOptions<any>): TSchema;
33
33
  /** Clamp a historical Pi thinking level against OMP's model metadata. */
34
34
  export declare function clampThinkingLevel<TApi extends Api>(model: Model<TApi>, level: Effort | "off"): Effort | "off";
35
+ /**
36
+ * Compatibility implementation of historical pi-ai's `isRetryableAssistantError`.
37
+ *
38
+ * Classifies whether a failed assistant message looks like a transient provider
39
+ * or transport error so legacy extensions can decide if the last assistant turn
40
+ * should be restarted. Account/quota limits are treated as non-retryable. This
41
+ * does not implement any retry policy; callers own budget, backoff, and reporting.
42
+ */
43
+ export declare function isRetryableAssistantError(message: AssistantMessage): boolean;
35
44
  export * from "@oh-my-pi/pi-ai";
36
45
  /**
37
46
  * Compatibility re-exports for catalog symbols that pi-ai historically exposed
@@ -45,3 +54,20 @@ export * from "@oh-my-pi/pi-ai";
45
54
  export { calculateCost, getBundledModel, getBundledModels, getBundledProviders, modelsAreEqual, Type };
46
55
  export declare const getModel: typeof getBundledModel;
47
56
  export declare const getModels: typeof getBundledModels;
57
+ /**
58
+ * Compatibility re-exports for runtime helpers that upstream
59
+ * `@earendil-works/pi-ai` exposed from its package root but omp's
60
+ * `@oh-my-pi/pi-ai` barrel no longer forwards. Each symbol still exists in the
61
+ * host graph — only its root re-export was dropped — so bridging it here keeps
62
+ * legacy extensions importing it from the pi-ai root resolving through Bun's
63
+ * static named-export check (e.g. `omp plugin install pi-blackhole`).
64
+ *
65
+ * This is the full set derived from an audit of the upstream root surface: the
66
+ * error-classification predicate `isContextOverflow` (now under
67
+ * `@oh-my-pi/pi-ai/error`) and the JSON-repair helpers that omp relocated to
68
+ * `@oh-my-pi/pi-utils`. Upstream root symbols with no omp equivalent are
69
+ * intentionally not shimmed — the package has diverged and there is nothing to
70
+ * forward.
71
+ */
72
+ export { isContextOverflow } from "@oh-my-pi/pi-ai/error";
73
+ export { parseJsonWithRepair, parseStreamingJson, repairJson } from "@oh-my-pi/pi-utils";
@@ -376,6 +376,8 @@ export { getProjectDir } from "@oh-my-pi/pi-utils";
376
376
  */
377
377
  export declare function getPackageDir(): string;
378
378
  export { estimateTokens } from "@oh-my-pi/pi-agent-core/compaction";
379
+ export { CONFIG_DIR_NAME } from "@oh-my-pi/pi-utils";
380
+ export { parseArgs } from "../cli/args.js";
379
381
  export * from "../index.js";
380
382
  export { formatBytes as formatSize } from "../tools/render-utils.js";
381
383
  export { copyToClipboard } from "../utils/clipboard.js";
@@ -47,8 +47,9 @@ export declare class LocalProtocolHandler implements ProtocolHandler {
47
47
  readonly immutable = false;
48
48
  /**
49
49
  * Install a process-global override that wins over the AgentRegistry-based
50
- * derivation. Used by SDK consumers that wire `localProtocolOptions` on
51
- * `createAgentSession` and by subagents that share their parent's root.
50
+ * derivation. Used by top-level SDK consumers that wire
51
+ * `localProtocolOptions` on `createAgentSession`; subagents keep their
52
+ * inherited mapping session-bound.
52
53
  */
53
54
  static setOverride(value: LocalProtocolOptions | undefined): void;
54
55
  /** Reset the process-global override. Test-only. */
@@ -0,0 +1,5 @@
1
+ import type { TerminalOutputOptions } from "./terminal-output.js";
2
+ /** Replay legacy broker PTY bytes without evaluating xterm in the client process. */
3
+ export declare function renderTerminalOutputIsolated(output: string, options: TerminalOutputOptions): Promise<string[] | undefined>;
4
+ /** Distribution smoke for source, npm-bundle, and compiled worker routing. */
5
+ export declare function smokeTestTerminalOutputWorker(): Promise<void>;
@@ -0,0 +1,14 @@
1
+ import type { TerminalOutputOptions } from "./terminal-output.js";
2
+ /** Hidden CLI selector for legacy PTY replay outside the client process. */
3
+ export declare const TERMINAL_OUTPUT_WORKER_ARG = "__omp_worker_terminal_output";
4
+ export interface TerminalOutputWorkerRequest {
5
+ output: string;
6
+ options: TerminalOutputOptions;
7
+ }
8
+ export type TerminalOutputWorkerResult = {
9
+ ok: true;
10
+ rows: string[] | undefined;
11
+ } | {
12
+ ok: false;
13
+ error: string;
14
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -19,6 +19,8 @@ export interface WatchedFileChange {
19
19
  export declare function supportsDocumentDiagnostics(client: LspClient): boolean;
20
20
  /** Timeout for warmup initialize requests (5 seconds) */
21
21
  export declare const WARMUP_TIMEOUT_MS = 5000;
22
+ /** Allow an explicit user reload to retry a matching initialization failure immediately. */
23
+ export declare function clearInitializationFailure(config: ServerConfig, cwd: string): void;
22
24
  /**
23
25
  * Get or create an LSP client for the given server configuration and working directory.
24
26
  * @param config - Server configuration
@@ -8,6 +8,7 @@ import type { SubmittedUserInput } from "./modes/types.js";
8
8
  import { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession, discoverAuthStorage } from "./sdk.js";
9
9
  import type { AgentSession } from "./session/agent-session.js";
10
10
  import type { AuthStorage } from "./session/auth-storage.js";
11
+ import type { ForeignSessionSource, ForeignSessionStore } from "./session/foreign-session-store.js";
11
12
  import { type SessionInfo } from "./session/session-listing.js";
12
13
  import { SessionManager } from "./session/session-manager.js";
13
14
  type RunAcpMode = (createSession: AcpSessionFactory) => Promise<never>;
@@ -65,6 +66,7 @@ interface RunRootCommandDependencies {
65
66
  discoverAuthStorage?: typeof discoverAuthStorage;
66
67
  selectSession?: typeof selectSession;
67
68
  runAcpMode?: RunAcpMode;
69
+ createForeignSessionStore?: (source: ForeignSessionSource) => ForeignSessionStore;
68
70
  settings?: Settings;
69
71
  forceSetupWizard?: boolean;
70
72
  }
@@ -61,13 +61,42 @@ export declare class MCPManager {
61
61
  static resetForTests(): void;
62
62
  constructor(cwd: string, toolCache?: MCPToolCache | null);
63
63
  /**
64
- * Set a callback to receive all server notifications.
64
+ * Register a listener for server-initiated MCP notifications.
65
+ *
66
+ * The listener is called for every JSON-RPC notification received from any
67
+ * connected server, AFTER the manager's own handling of known methods
68
+ * (`notifications/tools/list_changed`, `notifications/resources/list_changed`,
69
+ * `notifications/resources/updated`, `notifications/prompts/list_changed`).
70
+ * For list-change methods the internal refresh promise is awaited before
71
+ * fanout, so listeners observe up-to-date manager and tool state. Unknown
72
+ * or server-custom methods are also delivered, letting consumers bridge
73
+ * server-initiated events into session-level behavior (e.g. an extension
74
+ * injecting a steer via `pi.sendMessage`).
75
+ *
76
+ * Notifications received before any listener attached are buffered
77
+ * (bounded FIFO, cap {@link NOTIFICATION_BUFFER_CAP}, drop-oldest) and
78
+ * drained into the first subscriber — matches {@link setOnPromptsChanged}'s
79
+ * replay-on-attach and {@link IrcBus}'s mailbox semantics.
80
+ *
81
+ * Returns an unsubscribe function; call it to remove the listener.
82
+ *
83
+ * Multiple listeners are allowed; each is invoked with independent error
84
+ * isolation — a listener that throws does not prevent other listeners from
85
+ * firing.
65
86
  */
66
- setOnNotification(handler: (serverName: string, method: string, params: unknown) => void): void;
87
+ addNotificationListener(listener: (serverName: string, method: string, params: unknown) => void): () => void;
67
88
  /**
68
89
  * Set a callback to fire when any server's tools change.
69
- */
70
- setOnToolsChanged(handler: (tools: CustomTool<TSchema, MCPToolDetails>[]) => void): void;
90
+ *
91
+ * May return a Promise; if so, {@link refreshServerTools} awaits it so that
92
+ * downstream consumers (e.g. `mcp_notification` listeners for
93
+ * `notifications/tools/list_changed`) observe not just the manager's
94
+ * refreshed tool set but also any session-level rebind driven by the
95
+ * handler (`session.refreshMCPTools`). Other callsites (initial connect,
96
+ * disconnect, reconnect) invoke the handler synchronously — their downstream
97
+ * chains don't need to serialize on the rebind.
98
+ */
99
+ setOnToolsChanged(handler: (tools: CustomTool<TSchema, MCPToolDetails>[]) => void | Promise<void>): void;
71
100
  /**
72
101
  * Set a callback to fire when any server's resources change.
73
102
  */