@oh-my-pi/pi-coding-agent 17.2.9 → 17.2.11

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 (281) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/{CHANGELOG-8yy8h3bc.md → CHANGELOG-d9xenpn9.md} +83 -0
  3. package/dist/cli.js +10208 -12596
  4. package/dist/types/capability/mcp.d.ts +11 -0
  5. package/dist/types/capability/skill.d.ts +6 -0
  6. package/dist/types/cli/args.d.ts +1 -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/model-registry.d.ts +4 -0
  14. package/dist/types/config/model-resolver.d.ts +13 -0
  15. package/dist/types/config/settings-schema.d.ts +1 -34
  16. package/dist/types/discovery/agent-plugin-format.d.ts +143 -0
  17. package/dist/types/discovery/agent-plugins.d.ts +1 -0
  18. package/dist/types/discovery/contained-path.d.ts +34 -0
  19. package/dist/types/discovery/index.d.ts +1 -0
  20. package/dist/types/extensibility/custom-commands/types.d.ts +5 -5
  21. package/dist/types/extensibility/custom-tools/types.d.ts +3 -3
  22. package/dist/types/extensibility/extensions/loader.d.ts +9 -2
  23. package/dist/types/extensibility/extensions/types.d.ts +45 -8
  24. package/dist/types/extensibility/hooks/types.d.ts +5 -5
  25. package/dist/types/extensibility/shared-events.d.ts +3 -2
  26. package/dist/types/extensibility/skills.d.ts +5 -0
  27. package/dist/types/index.d.ts +2 -2
  28. package/dist/types/main.d.ts +1 -1
  29. package/dist/types/mcp/transports/header-policy.d.ts +45 -0
  30. package/dist/types/mcp/types.d.ts +15 -0
  31. package/dist/types/modes/acp/acp-agent.d.ts +1 -1
  32. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
  33. package/dist/types/modes/acp/acp-event-mapper.d.ts +1 -1
  34. package/dist/types/modes/acp/acp-mode.d.ts +1 -1
  35. package/dist/types/modes/components/agent-hub-projection.d.ts +38 -0
  36. package/dist/types/modes/components/agent-hub-renderer.d.ts +41 -0
  37. package/dist/types/modes/components/agent-hub.d.ts +14 -5
  38. package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
  39. package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
  40. package/dist/types/modes/components/custom-editor.d.ts +1 -2
  41. package/dist/types/modes/components/model-browser.d.ts +9 -1
  42. package/dist/types/modes/components/status-line/types.d.ts +2 -0
  43. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  44. package/dist/types/modes/interactive-mode.d.ts +8 -1
  45. package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
  46. package/dist/types/registry/agent-registry.d.ts +47 -0
  47. package/dist/types/registry/persisted-agents.d.ts +3 -1
  48. package/dist/types/secrets/index.d.ts +23 -1
  49. package/dist/types/session/agent-session-events.d.ts +2 -2
  50. package/dist/types/session/agent-session.d.ts +4 -2
  51. package/dist/types/session/messages.d.ts +1 -0
  52. package/dist/types/session/prewalk.d.ts +3 -1
  53. package/dist/types/session/session-entries.d.ts +10 -0
  54. package/dist/types/session/session-loader.d.ts +11 -1
  55. package/dist/types/session/session-manager.d.ts +9 -1
  56. package/dist/types/session/session-tools.d.ts +18 -1
  57. package/dist/types/session/turn-recovery.d.ts +7 -2
  58. package/dist/types/slash-commands/acp-builtins.d.ts +1 -1
  59. package/dist/types/slash-commands/available-commands.d.ts +1 -1
  60. package/dist/types/task/executor.d.ts +6 -0
  61. package/dist/types/task/index.d.ts +4 -3
  62. package/dist/types/task/read-only-policy.d.ts +3 -0
  63. package/dist/types/task/structured-subagent.d.ts +2 -0
  64. package/dist/types/task/types.d.ts +4 -0
  65. package/dist/types/tools/bash.d.ts +3 -3
  66. package/dist/types/tools/browser/launch.d.ts +2 -1
  67. package/dist/types/tools/browser/tab-worker.d.ts +2 -2
  68. package/dist/types/tools/path-utils.d.ts +1 -0
  69. package/dist/types/tools/read.d.ts +1 -5
  70. package/dist/types/tools/run-scope.d.ts +27 -1
  71. package/dist/types/tools/shell-tokenize.d.ts +16 -0
  72. package/dist/types/tools/terminal-output.d.ts +1 -1
  73. package/dist/types/utils/turndown.d.ts +1 -1
  74. package/dist/types/vibe/runtime.d.ts +2 -3
  75. package/dist/types/web/scrapers/readthedocs.d.ts +0 -3
  76. package/dist/types/web/search/providers/browser-headers.d.ts +2 -3
  77. package/examples/custom-tools/README.md +1 -1
  78. package/examples/extensions/README.md +1 -1
  79. package/examples/extensions/api-demo.ts +5 -6
  80. package/examples/extensions/chalk-logger.ts +1 -1
  81. package/examples/extensions/hello.ts +2 -2
  82. package/examples/extensions/reload-runtime.ts +1 -1
  83. package/examples/extensions/tools.ts +2 -2
  84. package/examples/extensions/with-deps/index.ts +1 -1
  85. package/examples/sdk/06-extensions.ts +1 -1
  86. package/package.json +15 -31
  87. package/scripts/bundle-dist.ts +1 -11
  88. package/scripts/legacy-pi-virtual-module.ts +4 -1
  89. package/src/advisor/runtime.ts +54 -0
  90. package/src/capability/mcp.ts +11 -0
  91. package/src/capability/skill.ts +6 -0
  92. package/src/cli/agents-cli.ts +1 -1
  93. package/src/cli/args.ts +24 -2
  94. package/src/cli/auth-broker-cli.ts +1 -1
  95. package/src/cli/auth-gateway-cli.ts +1 -1
  96. package/src/cli/bench-cli.ts +1 -1
  97. package/src/cli/claude-trace-cli.ts +1 -1
  98. package/src/cli/command-help.ts +4 -0
  99. package/src/cli/config-cli.ts +1 -1
  100. package/src/cli/dry-balance-cli.ts +1 -1
  101. package/src/cli/file-processor.ts +1 -1
  102. package/src/cli/flag-tables.ts +4 -0
  103. package/src/cli/gallery-cli.ts +1 -1
  104. package/src/cli/grep-cli.ts +1 -1
  105. package/src/cli/grievances-cli.ts +1 -1
  106. package/src/cli/help-extra.ts +1 -1
  107. package/src/cli/models-cli.ts +1 -1
  108. package/src/cli/plugin-cli.ts +1 -1
  109. package/src/cli/read-cli.ts +1 -1
  110. package/src/cli/setup-cli.ts +1 -1
  111. package/src/cli/shell-cli.ts +1 -1
  112. package/src/cli/ssh-cli.ts +1 -1
  113. package/src/cli/stats-cli.ts +1 -1
  114. package/src/cli/tiny-models-cli.ts +1 -1
  115. package/src/cli/ttsr-cli.ts +1 -1
  116. package/src/cli/update-cli.ts +1 -1
  117. package/src/cli/usage-cli.ts +1 -1
  118. package/src/cli/web-search-cli.ts +1 -1
  119. package/src/cli/worktree-cli.ts +1 -1
  120. package/src/cli-commands.ts +5 -0
  121. package/src/commands/commit.ts +16 -3
  122. package/src/commands/say.ts +1 -1
  123. package/src/commands/share.ts +71 -0
  124. package/src/commands/token.ts +1 -1
  125. package/src/commit/agentic/agent.ts +1 -1
  126. package/src/commit/agentic/index.ts +39 -21
  127. package/src/commit/cli.ts +1 -1
  128. package/src/commit/execute.ts +56 -0
  129. package/src/commit/index.ts +2 -1
  130. package/src/commit/pipeline.ts +20 -7
  131. package/src/config/model-discovery.ts +1 -1
  132. package/src/config/model-registry.ts +21 -1
  133. package/src/config/model-resolver.ts +54 -7
  134. package/src/config/settings-schema.ts +2 -33
  135. package/src/config/settings.ts +46 -0
  136. package/src/discovery/agent-plugin-format.ts +551 -0
  137. package/src/discovery/agent-plugins.ts +341 -0
  138. package/src/discovery/agents.ts +4 -2
  139. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +5 -4
  140. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +1 -1
  141. package/src/discovery/claude-plugins.ts +21 -5
  142. package/src/discovery/contained-path.ts +78 -0
  143. package/src/discovery/helpers.ts +23 -9
  144. package/src/discovery/index.ts +1 -0
  145. package/src/discovery/omp-plugins.ts +20 -7
  146. package/src/eval/py/runner.py +38 -1
  147. package/src/exec/non-interactive-env.ts +1 -0
  148. package/src/extensibility/custom-commands/loader.ts +4 -4
  149. package/src/extensibility/custom-commands/types.ts +5 -5
  150. package/src/extensibility/custom-tools/loader.ts +4 -4
  151. package/src/extensibility/custom-tools/types.ts +3 -3
  152. package/src/extensibility/extensions/loader.ts +85 -20
  153. package/src/extensibility/extensions/runner.ts +6 -0
  154. package/src/extensibility/extensions/types.ts +51 -8
  155. package/src/extensibility/hooks/loader.ts +4 -5
  156. package/src/extensibility/hooks/types.ts +5 -5
  157. package/src/extensibility/plugins/legacy-pi-compat.ts +53 -0
  158. package/src/extensibility/plugins/marketplace/manager.ts +2 -1
  159. package/src/extensibility/shared-events.ts +3 -2
  160. package/src/extensibility/skills.ts +9 -0
  161. package/src/index.ts +2 -2
  162. package/src/internal-urls/memory-protocol.ts +5 -1
  163. package/src/internal-urls/skill-protocol.ts +14 -0
  164. package/src/internal-urls/vault-protocol.ts +2 -2
  165. package/src/launch/client.ts +11 -1
  166. package/src/launch/protocol.ts +7 -2
  167. package/src/launch/terminal-output.ts +1 -1
  168. package/src/main.ts +88 -23
  169. package/src/markit/converters/docx.ts +1 -1
  170. package/src/markit/converters/epub.ts +1 -1
  171. package/src/markit/converters/pptx.ts +1 -1
  172. package/src/markit/converters/xlsx.ts +1 -1
  173. package/src/mcp/config.ts +3 -0
  174. package/src/mcp/manager.ts +12 -9
  175. package/src/mcp/transports/header-policy.ts +95 -0
  176. package/src/mcp/transports/http.ts +35 -52
  177. package/src/mcp/transports/sse.ts +20 -27
  178. package/src/mcp/types.ts +15 -0
  179. package/src/modes/acp/acp-agent.ts +20 -9
  180. package/src/modes/acp/acp-client-bridge.ts +1 -1
  181. package/src/modes/acp/acp-event-mapper.ts +1 -1
  182. package/src/modes/acp/acp-mode.ts +1 -1
  183. package/src/modes/components/agent-dashboard.ts +2 -0
  184. package/src/modes/components/agent-hub-projection.ts +248 -0
  185. package/src/modes/components/agent-hub-renderer.ts +194 -0
  186. package/src/modes/components/agent-hub.ts +674 -207
  187. package/src/modes/components/agent-transcript-viewer.ts +3 -0
  188. package/src/modes/components/assistant-message.ts +1 -1
  189. package/src/modes/components/chat-transcript-builder.ts +3 -0
  190. package/src/modes/components/custom-editor.ts +0 -9
  191. package/src/modes/components/extensions/inspector-panel.ts +11 -6
  192. package/src/modes/components/footer.ts +1 -3
  193. package/src/modes/components/model-browser.ts +11 -3
  194. package/src/modes/components/model-hub.ts +4 -1
  195. package/src/modes/components/status-line/component.ts +1 -0
  196. package/src/modes/components/status-line/segments.ts +10 -7
  197. package/src/modes/components/status-line/types.ts +2 -0
  198. package/src/modes/components/tool-execution.ts +13 -16
  199. package/src/modes/components/tree-selector.ts +62 -3
  200. package/src/modes/controllers/command-controller.ts +4 -1
  201. package/src/modes/controllers/event-controller.ts +44 -20
  202. package/src/modes/controllers/extension-ui-controller.ts +2 -2
  203. package/src/modes/controllers/input-controller.ts +20 -2
  204. package/src/modes/controllers/mcp-command-controller.ts +81 -20
  205. package/src/modes/controllers/selector-controller.ts +41 -49
  206. package/src/modes/controllers/streaming-reveal.ts +1 -1
  207. package/src/modes/interactive-mode.ts +13 -2
  208. package/src/modes/rpc/rpc-mode.ts +2 -2
  209. package/src/modes/runtime-init.ts +1 -1
  210. package/src/modes/theme/theme.ts +2 -2
  211. package/src/modes/utils/transcript-render-helpers.ts +4 -2
  212. package/src/modes/utils/ui-helpers.ts +1 -0
  213. package/src/prompts/tools/computer.md +1 -1
  214. package/src/registry/agent-lifecycle.ts +14 -7
  215. package/src/registry/agent-registry.ts +65 -2
  216. package/src/registry/persisted-agents.ts +341 -16
  217. package/src/sdk.ts +6 -49
  218. package/src/secrets/index.ts +52 -1
  219. package/src/session/agent-session-events.ts +2 -2
  220. package/src/session/agent-session.ts +54 -16
  221. package/src/session/messages.ts +1 -0
  222. package/src/session/prewalk.ts +57 -17
  223. package/src/session/session-context.ts +3 -5
  224. package/src/session/session-entries.ts +10 -0
  225. package/src/session/session-handoff.ts +5 -1
  226. package/src/session/session-listing.ts +1 -1
  227. package/src/session/session-loader.ts +74 -8
  228. package/src/session/session-manager.ts +22 -2
  229. package/src/session/session-paths.ts +57 -9
  230. package/src/session/session-tools.ts +65 -4
  231. package/src/session/todo-tracker.ts +11 -1
  232. package/src/session/turn-recovery.ts +96 -74
  233. package/src/slash-commands/acp-builtins.ts +1 -1
  234. package/src/slash-commands/available-commands.ts +1 -1
  235. package/src/slash-commands/builtin-registry.ts +12 -8
  236. package/src/task/executor.ts +70 -20
  237. package/src/task/index.ts +30 -34
  238. package/src/task/isolation-runner.ts +24 -11
  239. package/src/task/persisted-revive.ts +12 -5
  240. package/src/task/read-only-policy.ts +27 -0
  241. package/src/task/structured-subagent.ts +14 -4
  242. package/src/task/types.ts +4 -0
  243. package/src/tools/auto-generated-guard.ts +1 -1
  244. package/src/tools/bash-interactive.ts +4 -4
  245. package/src/tools/bash-skill-urls.ts +15 -0
  246. package/src/tools/bash.ts +16 -17
  247. package/src/tools/browser/cmux/cmux-tab.ts +66 -18
  248. package/src/tools/browser/launch.ts +41 -12
  249. package/src/tools/browser/readable.ts +9 -9
  250. package/src/tools/browser/tab-supervisor.ts +12 -3
  251. package/src/tools/browser/tab-worker-entry.ts +1 -1
  252. package/src/tools/browser/tab-worker.ts +101 -12
  253. package/src/tools/debug.ts +1 -1
  254. package/src/tools/fetch.ts +1 -1
  255. package/src/tools/jtd-to-json-schema.ts +123 -21
  256. package/src/tools/path-utils.ts +9 -2
  257. package/src/tools/read.ts +21 -9
  258. package/src/tools/run-scope.ts +290 -4
  259. package/src/tools/shell-tokenize.ts +98 -0
  260. package/src/tools/terminal-output.ts +1 -1
  261. package/src/tools/todo.ts +1 -1
  262. package/src/utils/clipboard.ts +10 -2
  263. package/src/utils/external-editor.ts +4 -2
  264. package/src/utils/jj.ts +1 -1
  265. package/src/utils/turndown.ts +1 -2
  266. package/src/vibe/runtime.ts +5 -5
  267. package/src/web/scrapers/arxiv.ts +1 -1
  268. package/src/web/scrapers/go-pkg.ts +1 -1
  269. package/src/web/scrapers/iacr.ts +1 -1
  270. package/src/web/scrapers/readthedocs.ts +2 -1
  271. package/src/web/scrapers/twitter.ts +2 -2
  272. package/src/web/scrapers/types.ts +1 -1
  273. package/src/web/scrapers/wikipedia.ts +1 -1
  274. package/src/web/search/providers/browser-headers.ts +12 -39
  275. package/src/web/search/providers/codex.ts +3 -26
  276. package/src/web/search/providers/ecosia.ts +1 -1
  277. package/src/web/search/providers/exa.ts +1 -1
  278. package/src/web/search/providers/google.ts +1 -1
  279. package/src/web/search/providers/mojeek.ts +1 -1
  280. package/src/web/search/providers/startpage.ts +1 -1
  281. package/src/markit/converters/mammoth.d.ts +0 -24
@@ -28,6 +28,7 @@ import { type Skill, skillCapability } from "../capability/skill";
28
28
  import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
29
29
  import { type CustomTool, toolCapability } from "../capability/tool";
30
30
  import type { LoadContext, LoadResult } from "../capability/types";
31
+ import { legacyProviderAllowed } from "./agent-plugin-format";
31
32
  import {
32
33
  buildRuleFromMarkdown,
33
34
  createSourceMeta,
@@ -44,12 +45,24 @@ const DESCRIPTION =
44
45
  "Sub-discovery (skills, hooks, tools, commands, rules, prompts, .mcp.json) inside extension packages";
45
46
  const PRIORITY = 90;
46
47
 
48
+ /**
49
+ * Extension roots this legacy provider may process for a given surface. Roots
50
+ * whose root `plugin.json` targets the Agent Plugins standard keep their
51
+ * portable components (skills, MCP) exclusive to the `agent-plugins` provider;
52
+ * fatally invalid Agent Plugins packages are skipped entirely.
53
+ */
54
+ async function allowedRoots(ctx: LoadContext, surface: "skills" | "mcp" | "other"): Promise<OmpExtensionRoot[]> {
55
+ const roots = await listOmpExtensionRoots(ctx);
56
+ const flags = await Promise.all(roots.map(root => legacyProviderAllowed(root.path, surface)));
57
+ return roots.filter((_, i) => flags[i]);
58
+ }
59
+
47
60
  // =============================================================================
48
61
  // Skills
49
62
  // =============================================================================
50
63
 
51
64
  async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
52
- const roots = await listOmpExtensionRoots(ctx);
65
+ const roots = await allowedRoots(ctx, "skills");
53
66
  const results = await Promise.all(
54
67
  roots.map(root =>
55
68
  scanSkillsFromDir(ctx, {
@@ -71,7 +84,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
71
84
  // =============================================================================
72
85
 
73
86
  async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashCommand>> {
74
- const roots = await listOmpExtensionRoots(ctx);
87
+ const roots = await allowedRoots(ctx, "other");
75
88
  const results = await Promise.all(
76
89
  roots.map(root =>
77
90
  loadFilesFromDir<SlashCommand>(ctx, path.join(root.path, "commands"), PROVIDER_ID, root.level, {
@@ -97,7 +110,7 @@ async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashComm
97
110
  // =============================================================================
98
111
 
99
112
  async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
100
- const roots = await listOmpExtensionRoots(ctx);
113
+ const roots = await allowedRoots(ctx, "other");
101
114
  const results = await Promise.all(
102
115
  roots.map(root =>
103
116
  loadFilesFromDir<Rule>(ctx, path.join(root.path, "rules"), PROVIDER_ID, root.level, {
@@ -118,7 +131,7 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
118
131
  // =============================================================================
119
132
 
120
133
  async function loadPrompts(ctx: LoadContext): Promise<LoadResult<Prompt>> {
121
- const roots = await listOmpExtensionRoots(ctx);
134
+ const roots = await allowedRoots(ctx, "other");
122
135
  const results = await Promise.all(
123
136
  roots.map(root =>
124
137
  loadFilesFromDir<Prompt>(ctx, path.join(root.path, "prompts"), PROVIDER_ID, root.level, {
@@ -145,7 +158,7 @@ async function loadPrompts(ctx: LoadContext): Promise<LoadResult<Prompt>> {
145
158
  const HOOK_TYPES: ReadonlyArray<"pre" | "post"> = ["pre", "post"];
146
159
 
147
160
  async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
148
- const roots = await listOmpExtensionRoots(ctx);
161
+ const roots = await allowedRoots(ctx, "other");
149
162
  const tasks: Array<{ root: OmpExtensionRoot; hookType: "pre" | "post" }> = [];
150
163
  for (const root of roots) {
151
164
  for (const hookType of HOOK_TYPES) {
@@ -183,7 +196,7 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
183
196
  const TOOL_EXTENSIONS = ["json", "md", "ts", "js", "sh", "bash", "py"];
184
197
 
185
198
  async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
186
- const roots = await listOmpExtensionRoots(ctx);
199
+ const roots = await allowedRoots(ctx, "other");
187
200
  const perRoot = await Promise.all(
188
201
  roots.map(async root => {
189
202
  const toolsDir = path.join(root.path, "tools");
@@ -276,7 +289,7 @@ interface RawMcpServer {
276
289
  }
277
290
 
278
291
  async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>> {
279
- const roots = await listOmpExtensionRoots(ctx);
292
+ const roots = await allowedRoots(ctx, "mcp");
280
293
  const items: MCPServer[] = [];
281
294
  const warnings: string[] = [];
282
295
 
@@ -40,6 +40,7 @@ import os
40
40
  import re
41
41
  import runpy
42
42
  import shlex
43
+ import shutil
43
44
  import signal
44
45
  import subprocess
45
46
  import sys
@@ -576,8 +577,10 @@ class _BoundedLineScanner:
576
577
  def _magic_pip(args: str) -> None:
577
578
  argv = shlex.split(args) if args else ["--help"]
578
579
  cmd = [sys.executable, "-m", "pip", *argv]
580
+ # stdin=DEVNULL: see _run_shell_body.
579
581
  proc = subprocess.Popen(
580
582
  cmd,
583
+ stdin=subprocess.DEVNULL,
581
584
  stdout=subprocess.PIPE,
582
585
  stderr=subprocess.STDOUT,
583
586
  )
@@ -737,9 +740,37 @@ def _magic_run(args: str) -> None:
737
740
  _STATE.user_ns[name] = value
738
741
 
739
742
 
743
+ def _resolve_bash() -> str:
744
+ if os.name != "nt":
745
+ return "/bin/bash"
746
+ # Prefer Git Bash over WSL's System32 bash.exe, which runs inside a
747
+ # separate Linux environment and does not share the Windows filesystem
748
+ # layout or PATH.
749
+ for env_var, suffix in (
750
+ ("ProgramFiles", r"Git\bin\bash.exe"),
751
+ ("ProgramFiles(x86)", r"Git\bin\bash.exe"),
752
+ ("LOCALAPPDATA", r"Programs\Git\bin\bash.exe"),
753
+ ):
754
+ root = os.environ.get(env_var)
755
+ if root:
756
+ candidate = os.path.join(root, suffix)
757
+ if os.path.isfile(candidate):
758
+ return candidate
759
+ found = shutil.which("bash")
760
+ if found and "system32" not in found.lower():
761
+ return found
762
+ # WSL's System32 bash.exe runs in a separate Linux environment, so
763
+ # silently falling back to it would execute the cell somewhere the user
764
+ # did not intend; fail loudly instead.
765
+ raise RuntimeError(
766
+ "%%bash requires a POSIX bash, but none was found. "
767
+ "Install Git for Windows or add a non-WSL bash to PATH."
768
+ )
769
+
770
+
740
771
  @cell_magic("bash")
741
772
  def _magic_cell_bash(args: str, body: str) -> int:
742
- return _run_shell_body(body, shell_arg="/bin/bash")
773
+ return _run_shell_body(body, shell_arg=_resolve_bash())
743
774
 
744
775
 
745
776
  @cell_magic("capture")
@@ -780,8 +811,12 @@ def _magic_cell_writefile(args: str, body: str) -> str:
780
811
 
781
812
 
782
813
  def _run_shell_body(body: str, *, shell_arg: str) -> int:
814
+ # stdin=DEVNULL: children must not inherit the runner's stdin, which is
815
+ # the host's NDJSON control channel (a reading child would steal frames,
816
+ # and inheriting the pipe deadlocks nested interpreters on Windows).
783
817
  proc = subprocess.Popen(
784
818
  [shell_arg, "-c", body],
819
+ stdin=subprocess.DEVNULL,
785
820
  stdout=subprocess.PIPE,
786
821
  stderr=subprocess.STDOUT,
787
822
  )
@@ -821,9 +856,11 @@ class _ShellResult(list):
821
856
 
822
857
 
823
858
  def __omp_shell(cmd: str) -> _ShellResult:
859
+ # stdin=DEVNULL: see _run_shell_body.
824
860
  proc = subprocess.Popen(
825
861
  cmd,
826
862
  shell=True,
863
+ stdin=subprocess.DEVNULL,
827
864
  stdout=subprocess.PIPE,
828
865
  stderr=subprocess.STDOUT,
829
866
  )
@@ -24,6 +24,7 @@ export const NON_INTERACTIVE_ENV: Readonly<Record<string, string>> = {
24
24
  GIT_TERMINAL_PROMPT: "0",
25
25
  SSH_ASKPASS: "/usr/bin/false",
26
26
  CI: "1",
27
+ AGENT: "1",
27
28
  // Package manager defaults for unattended execution.
28
29
  npm_config_yes: "true",
29
30
  npm_config_update_notifier: "false",
@@ -6,8 +6,8 @@
6
6
  */
7
7
  import * as fs from "node:fs";
8
8
  import * as path from "node:path";
9
- import * as arktype from "@oh-my-pi/omptype";
10
- import * as zodModule from "@oh-my-pi/omptype/zod";
9
+ import { type } from "@oh-my-pi/omptype";
10
+ import * as zod from "@oh-my-pi/omptype/zod";
11
11
  import { getAgentDir, getProjectDir, isEnoent, logger } from "@oh-my-pi/pi-utils";
12
12
  import { getConfigDirs } from "../../config";
13
13
  import { execCommand } from "../../exec/exec";
@@ -187,8 +187,8 @@ export async function loadCustomCommands(options: LoadCustomCommandsOptions = {}
187
187
  exec: (command: string, args: string[], execOptions) =>
188
188
  execCommand(command, args, execOptions?.cwd ?? cwd, execOptions),
189
189
  typebox,
190
- arktype,
191
- zod: zodModule,
190
+ arktype: type,
191
+ zod,
192
192
  pi: PiCodingAgent,
193
193
  };
194
194
 
@@ -5,7 +5,7 @@
5
5
  * Unlike markdown commands which expand to prompts, custom commands can execute
6
6
  * arbitrary logic with full access to the hook context.
7
7
  */
8
- import type * as arktype from "@oh-my-pi/omptype";
8
+ import type { type as ArkType } from "@oh-my-pi/omptype";
9
9
  import type * as TypeBox from "@oh-my-pi/omptype/typebox";
10
10
  import type * as zod from "@oh-my-pi/omptype/zod";
11
11
  import type { ExecOptions, ExecResult, HookCommandContext } from "../../extensibility/hooks/types";
@@ -23,11 +23,11 @@ export interface CustomCommandAPI {
23
23
  cwd: string;
24
24
  /** Execute a shell command */
25
25
  exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
26
- /** Injected zod-backed typebox shim (legacy/compat). */
26
+ /** Injected TypeBox shim (legacy/compat). */
27
27
  typebox: typeof TypeBox;
28
- /** Injected arktype module for validation in custom commands. */
29
- arktype: typeof arktype;
30
- /** Injected omptype-backed zod facade for command validation. */
28
+ /** Injected omptype schema builder for custom commands. */
29
+ arktype: typeof ArkType;
30
+ /** Injected Zod-compatible omptype builder for custom commands. */
31
31
  zod: typeof zod;
32
32
  /** Injected pi-coding-agent exports */
33
33
  pi: typeof PiCodingAgent;
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Custom tool loader - loads TypeScript tool modules using native Bun import.
3
3
  *
4
- * Dependencies (the zod-backed typebox shim and pi-coding-agent) are injected via the
5
- * CustomToolAPI to avoid import resolution issues with custom tools loaded from user directories.
4
+ * Dependencies are injected through CustomToolAPI so tools loaded from user
5
+ * directories do not depend on workspace module resolution.
6
6
  */
7
7
  import * as path from "node:path";
8
8
  import { type } from "@oh-my-pi/omptype";
9
- import * as zodModule from "@oh-my-pi/omptype/zod";
9
+ import * as zod from "@oh-my-pi/omptype/zod";
10
10
  import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
11
11
  import { logger } from "@oh-my-pi/pi-utils";
12
12
  import { toolCapability } from "../../capability/tool";
@@ -149,7 +149,7 @@ export class CustomToolLoader {
149
149
  logger,
150
150
  typebox,
151
151
  arktype: type,
152
- zod: zodModule,
152
+ zod,
153
153
  pi,
154
154
  pushPendingAction: action => {
155
155
  if (!pushPendingAction) {
@@ -30,7 +30,7 @@ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
30
30
  import type { Theme } from "../../modes/theme/theme";
31
31
  import type { ReadonlySessionManager } from "../../session/session-manager";
32
32
  import type { TodoItem } from "../../tools/todo";
33
- import type { RecoveredRetryError } from "../shared-events";
33
+ import type { RetryErrorUpdate } from "../shared-events";
34
34
 
35
35
  /** Alias for clarity */
36
36
  export type CustomToolUIContext = HookUIContext;
@@ -70,7 +70,7 @@ export interface CustomToolAPI {
70
70
  typebox: typeof TypeBox;
71
71
  /** Injected arktype module for arktype-authored custom tools. */
72
72
  arktype: typeof ArkType;
73
- /** Injected omptype-backed zod facade for parameter schemas. */
73
+ /** Injected Zod-compatible omptype builder for custom tools. */
74
74
  zod: typeof zod;
75
75
  /** Injected pi-coding-agent exports */
76
76
  pi: typeof PiCodingAgent;
@@ -139,7 +139,7 @@ export type CustomToolSessionEvent =
139
139
  success: boolean;
140
140
  attempt: number;
141
141
  finalError?: string;
142
- recoveredErrors?: RecoveredRetryError[];
142
+ retryErrors?: RetryErrorUpdate[];
143
143
  }
144
144
  | {
145
145
  reason: "ttsr_triggered";
@@ -4,8 +4,8 @@
4
4
  import type * as fs1 from "node:fs";
5
5
  import * as fs from "node:fs/promises";
6
6
  import * as path from "node:path";
7
- import { Type } from "@oh-my-pi/omptype";
8
- import * as zodModule from "@oh-my-pi/omptype/zod";
7
+ import { type } from "@oh-my-pi/omptype";
8
+ import * as zod from "@oh-my-pi/omptype/zod";
9
9
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
10
10
  import type {
11
11
  ImageContent,
@@ -46,6 +46,7 @@ import type {
46
46
  ProviderConfig,
47
47
  RegisteredCommand,
48
48
  ToolDefinition,
49
+ ToolInfo,
49
50
  } from "./types";
50
51
 
51
52
  installLegacyPiSpecifierShim();
@@ -72,6 +73,15 @@ export class ExtensionRuntime implements IExtensionRuntime {
72
73
  flagValues = new Map<string, boolean | string>();
73
74
  pendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; sourceId: string }> = [];
74
75
 
76
+ registerProvider(name: string, config: ProviderConfig, sourceId: string): void {
77
+ this.pendingProviderRegistrations.push({ name, config, sourceId });
78
+ }
79
+
80
+ unregisterProvider(name: string): void {
81
+ const remaining = this.pendingProviderRegistrations.filter(registration => registration.name !== name);
82
+ this.pendingProviderRegistrations.splice(0, this.pendingProviderRegistrations.length, ...remaining);
83
+ }
84
+
75
85
  sendMessage(): void {
76
86
  throw new ExtensionRuntimeNotInitializedError();
77
87
  }
@@ -92,7 +102,7 @@ export class ExtensionRuntime implements IExtensionRuntime {
92
102
  throw new ExtensionRuntimeNotInitializedError();
93
103
  }
94
104
 
95
- getAllTools(): string[] {
105
+ getAllTools(): ToolInfo[] {
96
106
  throw new ExtensionRuntimeNotInitializedError();
97
107
  }
98
108
 
@@ -141,8 +151,8 @@ export class ExtensionRuntime implements IExtensionRuntime {
141
151
  class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
142
152
  readonly logger = logger;
143
153
  readonly typebox = TypeBox;
144
- readonly arktype = Type;
145
- readonly zod = zodModule;
154
+ readonly arktype = type;
155
+ readonly zod = zod;
146
156
  readonly flagValues = new Map<string, boolean | string>();
147
157
  readonly pendingProviderRegistrations: Array<{
148
158
  name: string;
@@ -245,7 +255,7 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
245
255
  return this.runtime.getActiveTools();
246
256
  }
247
257
 
248
- getAllTools(): string[] {
258
+ getAllTools(): ToolInfo[] {
249
259
  return this.runtime.getAllTools();
250
260
  }
251
261
 
@@ -289,7 +299,11 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
289
299
  }
290
300
 
291
301
  registerProvider(name: string, config: ProviderConfig): void {
292
- this.runtime.pendingProviderRegistrations.push({ name, config, sourceId: this.extension.path });
302
+ this.runtime.registerProvider(name, config, this.extension.path);
303
+ }
304
+
305
+ unregisterProvider(name: string): void {
306
+ this.runtime.unregisterProvider(name, this.extension.path);
293
307
  }
294
308
  }
295
309
 
@@ -310,12 +324,37 @@ function createExtension(extensionPath: string, resolvedPath: string): Extension
310
324
  };
311
325
  }
312
326
 
313
- async function loadExtension(
314
- extensionPath: string,
315
- cwd: string,
316
- eventBus: EventBus,
327
+ /**
328
+ * Runs an extension factory with provider registration rollback on failure.
329
+ * Restores the complete registration queue when the factory throws because an
330
+ * extension may unregister entries queued by an earlier extension.
331
+ */
332
+ async function runExtensionFactory(
333
+ factory: ExtensionFactory,
334
+ api: ExtensionAPI,
317
335
  runtime: IExtensionRuntime,
318
- ): Promise<{ extension: Extension | null; error: string | null }> {
336
+ ): Promise<void> {
337
+ const providerRegistrationCheckpoint = [...runtime.pendingProviderRegistrations];
338
+
339
+ try {
340
+ await factory(api);
341
+ } catch (error) {
342
+ runtime.pendingProviderRegistrations.splice(
343
+ 0,
344
+ runtime.pendingProviderRegistrations.length,
345
+ ...providerRegistrationCheckpoint,
346
+ );
347
+ throw error;
348
+ }
349
+ }
350
+
351
+ interface ImportedExtensionModule {
352
+ factory: ExtensionFactory | null;
353
+ resolvedPath: string;
354
+ error: string | null;
355
+ }
356
+
357
+ async function importExtensionModule(extensionPath: string, cwd: string): Promise<ImportedExtensionModule> {
319
358
  const resolvedPath = resolvePath(extensionPath, cwd);
320
359
  try {
321
360
  const module = (await withHostGuard(() => loadLegacyPiModule(resolvedPath))) as LoadedExtensionModule;
@@ -323,16 +362,34 @@ async function loadExtension(
323
362
 
324
363
  if (typeof factory !== "function") {
325
364
  return {
326
- extension: null,
365
+ factory: null,
366
+ resolvedPath,
327
367
  error: `Extension does not export a valid factory function: ${extensionPath}`,
328
368
  };
329
369
  }
330
370
 
331
- const extension = createExtension(extensionPath, resolvedPath);
371
+ return { factory, resolvedPath, error: null };
372
+ } catch (err) {
373
+ const message = err instanceof Error ? err.message : String(err);
374
+ return { factory: null, resolvedPath, error: `Failed to load extension: ${message}` };
375
+ }
376
+ }
377
+
378
+ async function bindExtension(
379
+ extensionPath: string,
380
+ imported: ImportedExtensionModule,
381
+ cwd: string,
382
+ eventBus: EventBus,
383
+ runtime: IExtensionRuntime,
384
+ ): Promise<{ extension: Extension | null; error: string | null }> {
385
+ const factory = imported.factory;
386
+ if (imported.error !== null || factory === null) {
387
+ return { extension: null, error: imported.error };
388
+ }
389
+ try {
390
+ const extension = createExtension(extensionPath, imported.resolvedPath);
332
391
  const api = new ConcreteExtensionAPI(PiCodingAgent, extension, runtime, cwd, eventBus);
333
- await withHostGuard(async () => {
334
- await factory(api);
335
- });
392
+ await withHostGuard(() => runExtensionFactory(factory, api, runtime));
336
393
 
337
394
  return { extension, error: null };
338
395
  } catch (err) {
@@ -353,12 +410,17 @@ export async function loadExtensionFromFactory(
353
410
  ): Promise<Extension> {
354
411
  const extension = createExtension(name, name);
355
412
  const api = new ConcreteExtensionAPI(PiCodingAgent, extension, runtime, cwd, eventBus);
356
- await factory(api);
413
+ await runExtensionFactory(factory, api, runtime);
357
414
  return extension;
358
415
  }
359
416
 
360
417
  /**
361
418
  * Load extensions from paths.
419
+ *
420
+ * Module import (the dominant cold-start cost — file I/O plus module
421
+ * evaluation) runs concurrently across extensions; factory binding then runs
422
+ * sequentially in the original path order, so registration semantics
423
+ * (last-wins collisions, shared runtime flag defaults) stay deterministic.
362
424
  */
363
425
  export async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {
364
426
  const extensions: Extension[] = [];
@@ -366,8 +428,11 @@ export async function loadExtensions(paths: string[], cwd: string, eventBus?: Ev
366
428
  const resolvedEventBus = eventBus ?? new EventBus();
367
429
  const runtime = new ExtensionRuntime();
368
430
 
369
- for (const extPath of paths) {
370
- const { extension, error } = await loadExtension(extPath, cwd, resolvedEventBus, runtime);
431
+ const imported = await Promise.all(paths.map(extPath => importExtensionModule(extPath, cwd)));
432
+
433
+ for (let i = 0; i < paths.length; i++) {
434
+ const extPath = paths[i]!;
435
+ const { extension, error } = await bindExtension(extPath, imported[i]!, cwd, resolvedEventBus, runtime);
371
436
 
372
437
  if (error) {
373
438
  errors.push({ path: extPath, error });
@@ -530,6 +530,12 @@ export class ExtensionRunner {
530
530
  this.runtime.setServiceTier = actions.setServiceTier ?? throwUnsupportedServiceTierAction;
531
531
  this.runtime.getSessionName = actions.getSessionName;
532
532
  this.runtime.setSessionName = actions.setSessionName;
533
+ this.runtime.registerProvider = (name, config, sourceId) => {
534
+ this.modelRegistry.registerProvider(name, config, sourceId);
535
+ };
536
+ this.runtime.unregisterProvider = name => {
537
+ this.modelRegistry.unregisterProvider(name);
538
+ };
533
539
 
534
540
  // Context actions (required)
535
541
  this.#getModel = contextActions.getModel;
@@ -8,7 +8,7 @@
8
8
  * - Interact with the user via UI primitives
9
9
  */
10
10
 
11
- import type { Type as arktype } from "@oh-my-pi/omptype";
11
+ import type { type as ArkType } from "@oh-my-pi/omptype";
12
12
  import type * as TypeBox from "@oh-my-pi/omptype/typebox";
13
13
  import type * as zod from "@oh-my-pi/omptype/zod";
14
14
  import type {
@@ -596,6 +596,36 @@ export interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = un
596
596
  ) => Component;
597
597
  }
598
598
 
599
+ /** Whether a tool's source is scoped to the user, the project, or a transient runtime session. */
600
+ export type SourceScope = "user" | "project" | "temporary";
601
+
602
+ /** Whether a tool's source came from an installed package or a top-level (loose) file. */
603
+ export type SourceOrigin = "package" | "top-level";
604
+
605
+ /**
606
+ * Provenance metadata describing where a registered tool came from. Mirrors the
607
+ * `@earendil-works/pi-coding-agent` `SourceInfo` contract so extensions authored
608
+ * against upstream pi (e.g. gentle-pi) can read `sourceInfo.source` unchanged.
609
+ */
610
+ export interface SourceInfo {
611
+ /** Synthetic or on-disk identifier for the tool's origin (e.g. `<builtin:read>`). */
612
+ path: string;
613
+ /** Origin class: `"builtin"`, `"sdk"`, `"mcp"`, or `"extension"`. */
614
+ source: string;
615
+ scope: SourceScope;
616
+ origin: SourceOrigin;
617
+ baseDir?: string;
618
+ }
619
+
620
+ /** Tool metadata returned by {@link ExtensionAPI.getAllTools}: identity, schema, and source provenance. */
621
+ export interface ToolInfo {
622
+ name: string;
623
+ description: string;
624
+ parameters: TSchema;
625
+ promptGuidelines?: string[];
626
+ sourceInfo: SourceInfo;
627
+ }
628
+
599
629
  // ============================================================================
600
630
  // Resource Events
601
631
  // ============================================================================
@@ -1109,12 +1139,13 @@ export interface ExtensionAPI {
1109
1139
  /** File logger for error/warning/debug messages */
1110
1140
  logger: typeof PiLogger;
1111
1141
 
1112
- /** Injected zod-backed typebox shim for legacy `Type.Object(...)` parameter authoring. */
1142
+ /** Injected TypeBox shim for legacy `Type.Object(...)` parameter authoring. */
1113
1143
  typebox: typeof TypeBox;
1114
1144
 
1115
- /** Injected arktype module for arktype-authored extension tools (canonical going forward). */
1116
- arktype: typeof arktype;
1117
- /** Injected omptype-backed zod facade for extension tool parameter schemas. */
1145
+ /** Injected omptype schema builder for extension tools. */
1146
+ arktype: typeof ArkType;
1147
+
1148
+ /** Injected Zod-compatible omptype builder for extension tools. */
1118
1149
  zod: typeof zod;
1119
1150
 
1120
1151
  /** Injected pi-coding-agent exports for accessing SDK utilities */
@@ -1267,8 +1298,8 @@ export interface ExtensionAPI {
1267
1298
  /** Get the list of currently active tool names. */
1268
1299
  getActiveTools(): string[];
1269
1300
 
1270
- /** Get all configured tools (built-in + extension tools). */
1271
- getAllTools(): string[];
1301
+ /** Get all configured tools (built-in + extension tools) with schema and source metadata. */
1302
+ getAllTools(): ToolInfo[];
1272
1303
 
1273
1304
  /** Set the active tools by name. */
1274
1305
  setActiveTools(toolNames: string[]): Promise<void>;
@@ -1342,6 +1373,14 @@ export interface ExtensionAPI {
1342
1373
  */
1343
1374
  registerProvider(name: string, config: ProviderConfig): void;
1344
1375
 
1376
+ /**
1377
+ * Unregister a provider previously registered by an extension.
1378
+ *
1379
+ * Removes extension-provided models and restores overridden built-in models.
1380
+ * Has no effect when the provider is not registered.
1381
+ */
1382
+ unregisterProvider(name: string): void;
1383
+
1345
1384
  /** Shared event bus for extension communication. */
1346
1385
  events: EventBus;
1347
1386
  }
@@ -1464,7 +1503,7 @@ export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) =>
1464
1503
 
1465
1504
  export type GetActiveToolsHandler = () => string[];
1466
1505
 
1467
- export type GetAllToolsHandler = () => string[];
1506
+ export type GetAllToolsHandler = () => ToolInfo[];
1468
1507
 
1469
1508
  export type GetCommandsHandler = () => SlashCommandInfo[];
1470
1509
 
@@ -1485,6 +1524,10 @@ export interface ExtensionRuntimeState {
1485
1524
  flagValues: Map<string, boolean | string>;
1486
1525
  /** Provider registrations queued during extension loading, processed during session initialization */
1487
1526
  pendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; sourceId: string }>;
1527
+ /** Queue a provider registration until initialization, then apply it immediately. */
1528
+ registerProvider(name: string, config: ProviderConfig, sourceId: string): void;
1529
+ /** Remove a queued or initialized provider registration. */
1530
+ unregisterProvider(name: string, sourceId: string): void;
1488
1531
  }
1489
1532
 
1490
1533
  /** Action implementations for ExtensionAPI methods. */
@@ -2,8 +2,8 @@
2
2
  * Hook loader - loads TypeScript hook modules using native Bun import.
3
3
  */
4
4
  import * as path from "node:path";
5
- import * as arktype from "@oh-my-pi/omptype";
6
- import * as zodModule from "@oh-my-pi/omptype/zod";
5
+ import { type } from "@oh-my-pi/omptype";
6
+ import * as zod from "@oh-my-pi/omptype/zod";
7
7
  import { logger } from "@oh-my-pi/pi-utils";
8
8
  import { hookCapability } from "../../capability/hook";
9
9
  import type { Hook } from "../../discovery";
@@ -122,9 +122,8 @@ async function createHookAPI(
122
122
  },
123
123
  logger,
124
124
  typebox,
125
- // HookAPI.arktype is typed as the arktype `Type` constructor; expose it from the module namespace.
126
- arktype: arktype.Type,
127
- zod: zodModule,
125
+ arktype: type,
126
+ zod,
128
127
  pi: PiCodingAgent,
129
128
  } as HookAPI;
130
129
 
@@ -1,4 +1,4 @@
1
- import type { Type } from "@oh-my-pi/omptype";
1
+ import type { type as ArkType } from "@oh-my-pi/omptype";
2
2
  import type * as TypeBox from "@oh-my-pi/omptype/typebox";
3
3
  import type * as zod from "@oh-my-pi/omptype/zod";
4
4
  import type { ImageContent, Message, Model, TextContent } from "@oh-my-pi/pi-ai";
@@ -582,11 +582,11 @@ export interface HookAPI {
582
582
 
583
583
  /** File logger for error/warning/debug messages */
584
584
  logger: typeof PiLogger;
585
- /** Injected zod-backed typebox shim (legacy/compat — prefer `arktype`). */
585
+ /** Injected TypeBox shim (legacy/compat — prefer `arktype`). */
586
586
  typebox: typeof TypeBox;
587
- /** Injected arktype module for arktype-authored hooks. */
588
- arktype: typeof Type;
589
- /** Injected omptype-backed zod facade for hook validation. */
587
+ /** Injected omptype schema builder for hooks. */
588
+ arktype: typeof ArkType;
589
+ /** Injected Zod-compatible omptype builder for hooks. */
590
590
  zod: typeof zod;
591
591
  /** Injected pi-coding-agent exports */
592
592
  pi: typeof PiCodingAgent;