@bastani/atomic 0.8.21 → 0.8.22-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 (235) hide show
  1. package/CHANGELOG.md +40 -9
  2. package/dist/builtin/intercom/broker/broker.ts +3 -3
  3. package/dist/builtin/intercom/config.ts +3 -3
  4. package/dist/builtin/intercom/index.ts +1 -1
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/intercom/ui/compose.ts +2 -2
  7. package/dist/builtin/mcp/host-html-template.ts +0 -3
  8. package/dist/builtin/mcp/package.json +1 -1
  9. package/dist/builtin/subagents/CHANGELOG.md +13 -4
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
  14. package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
  15. package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
  16. package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
  17. package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
  18. package/dist/builtin/subagents/src/agents/skills.ts +19 -1
  19. package/dist/builtin/subagents/src/extension/index.ts +24 -22
  20. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
  21. package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
  22. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
  23. package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
  24. package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
  25. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
  26. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
  27. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
  28. package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
  29. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
  32. package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
  33. package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
  34. package/dist/builtin/subagents/src/shared/types.ts +4 -2
  35. package/dist/builtin/subagents/src/shared/utils.ts +3 -61
  36. package/dist/builtin/subagents/src/tui/render.ts +303 -157
  37. package/dist/builtin/web-access/package.json +1 -1
  38. package/dist/builtin/workflows/CHANGELOG.md +95 -35
  39. package/dist/builtin/workflows/README.md +228 -41
  40. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
  41. package/dist/builtin/workflows/builtin/goal.ts +39 -25
  42. package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
  43. package/dist/builtin/workflows/builtin/ralph.ts +21 -21
  44. package/dist/builtin/workflows/package.json +6 -5
  45. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  46. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
  47. package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
  48. package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
  49. package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
  50. package/dist/builtin/workflows/src/extension/index.ts +690 -352
  51. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
  52. package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
  53. package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
  54. package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
  55. package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
  56. package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
  57. package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
  58. package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
  59. package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
  60. package/dist/builtin/workflows/src/index.ts +2 -0
  61. package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
  62. package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
  63. package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
  64. package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
  65. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
  66. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
  67. package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
  68. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
  69. package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
  70. package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
  71. package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
  72. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
  73. package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
  74. package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
  75. package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
  76. package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
  77. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
  78. package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
  79. package/dist/builtin/workflows/src/shared/store.ts +58 -14
  80. package/dist/builtin/workflows/src/shared/types.ts +105 -40
  81. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
  82. package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
  83. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
  84. package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
  85. package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
  86. package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
  87. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
  88. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
  89. package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
  90. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
  91. package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
  92. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
  93. package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
  94. package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
  95. package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
  96. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
  97. package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
  98. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
  99. package/dist/builtin/workflows/src/tui/toast.ts +2 -2
  100. package/dist/builtin/workflows/src/tui/widget.ts +53 -12
  101. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
  102. package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
  103. package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
  104. package/dist/config.d.ts +9 -0
  105. package/dist/config.d.ts.map +1 -1
  106. package/dist/config.js +45 -0
  107. package/dist/config.js.map +1 -1
  108. package/dist/core/agent-session.d.ts +27 -9
  109. package/dist/core/agent-session.d.ts.map +1 -1
  110. package/dist/core/agent-session.js +196 -17
  111. package/dist/core/agent-session.js.map +1 -1
  112. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  113. package/dist/core/atomic-guide-command.js +2 -2
  114. package/dist/core/atomic-guide-command.js.map +1 -1
  115. package/dist/core/codex-fast-mode.d.ts +36 -0
  116. package/dist/core/codex-fast-mode.d.ts.map +1 -0
  117. package/dist/core/codex-fast-mode.js +117 -0
  118. package/dist/core/codex-fast-mode.js.map +1 -0
  119. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  120. package/dist/core/compaction/branch-summarization.js +1 -1
  121. package/dist/core/compaction/branch-summarization.js.map +1 -1
  122. package/dist/core/compaction/compaction.d.ts.map +1 -1
  123. package/dist/core/compaction/compaction.js +1 -1
  124. package/dist/core/compaction/compaction.js.map +1 -1
  125. package/dist/core/extensions/index.d.ts +4 -1
  126. package/dist/core/extensions/index.d.ts.map +1 -1
  127. package/dist/core/extensions/index.js +1 -0
  128. package/dist/core/extensions/index.js.map +1 -1
  129. package/dist/core/extensions/loader.d.ts +7 -2
  130. package/dist/core/extensions/loader.d.ts.map +1 -1
  131. package/dist/core/extensions/loader.js +23 -8
  132. package/dist/core/extensions/loader.js.map +1 -1
  133. package/dist/core/extensions/reactive-widget.d.ts +58 -0
  134. package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
  135. package/dist/core/extensions/reactive-widget.js +182 -0
  136. package/dist/core/extensions/reactive-widget.js.map +1 -0
  137. package/dist/core/extensions/runner.d.ts.map +1 -1
  138. package/dist/core/extensions/runner.js +1 -0
  139. package/dist/core/extensions/runner.js.map +1 -1
  140. package/dist/core/extensions/types.d.ts +26 -12
  141. package/dist/core/extensions/types.d.ts.map +1 -1
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/messages.d.ts +1 -1
  144. package/dist/core/messages.d.ts.map +1 -1
  145. package/dist/core/messages.js +8 -2
  146. package/dist/core/messages.js.map +1 -1
  147. package/dist/core/model-registry.d.ts +4 -0
  148. package/dist/core/model-registry.d.ts.map +1 -1
  149. package/dist/core/model-registry.js +11 -0
  150. package/dist/core/model-registry.js.map +1 -1
  151. package/dist/core/resource-loader.d.ts +9 -1
  152. package/dist/core/resource-loader.d.ts.map +1 -1
  153. package/dist/core/resource-loader.js +49 -21
  154. package/dist/core/resource-loader.js.map +1 -1
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +22 -13
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-manager.d.ts +7 -5
  159. package/dist/core/session-manager.d.ts.map +1 -1
  160. package/dist/core/session-manager.js +5 -3
  161. package/dist/core/session-manager.js.map +1 -1
  162. package/dist/core/settings-manager.d.ts +16 -0
  163. package/dist/core/settings-manager.d.ts.map +1 -1
  164. package/dist/core/settings-manager.js +64 -5
  165. package/dist/core/settings-manager.js.map +1 -1
  166. package/dist/core/slash-commands.d.ts.map +1 -1
  167. package/dist/core/slash-commands.js +1 -0
  168. package/dist/core/slash-commands.js.map +1 -1
  169. package/dist/core/system-prompt.d.ts.map +1 -1
  170. package/dist/core/system-prompt.js +7 -4
  171. package/dist/core/system-prompt.js.map +1 -1
  172. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
  174. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  175. package/dist/index.d.ts +4 -3
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +3 -2
  178. package/dist/index.js.map +1 -1
  179. package/dist/main.d.ts +3 -0
  180. package/dist/main.d.ts.map +1 -1
  181. package/dist/main.js +12 -0
  182. package/dist/main.js.map +1 -1
  183. package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
  184. package/dist/modes/interactive/chat-input-actions.js.map +1 -1
  185. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/diff.js +0 -1
  187. package/dist/modes/interactive/components/diff.js.map +1 -1
  188. package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
  189. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
  190. package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
  191. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
  192. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/footer.js +7 -12
  194. package/dist/modes/interactive/components/footer.js.map +1 -1
  195. package/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/index.js +1 -0
  198. package/dist/modes/interactive/components/index.js.map +1 -1
  199. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  200. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.js +132 -30
  202. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +53 -6
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/dist/modes/rpc/rpc-mode.js +3 -0
  208. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/docs/compaction.md +1 -1
  210. package/docs/custom-provider.md +2 -2
  211. package/docs/development.md +2 -2
  212. package/docs/docs.json +2 -2
  213. package/docs/extensions.md +18 -13
  214. package/docs/providers.md +5 -1
  215. package/docs/quickstart.md +5 -3
  216. package/docs/rpc.md +5 -5
  217. package/docs/sdk.md +12 -12
  218. package/docs/settings.md +18 -0
  219. package/docs/themes.md +6 -6
  220. package/docs/tui.md +20 -18
  221. package/docs/usage.md +2 -0
  222. package/docs/workflows.md +403 -39
  223. package/examples/extensions/qna.ts +2 -2
  224. package/package.json +4 -4
  225. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
  226. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
  227. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
  228. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
  229. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
  230. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
  231. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
  232. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
  233. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
  234. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
  235. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
@@ -5,6 +5,11 @@
5
5
  import { type EventBus } from "../event-bus.ts";
6
6
  import type { ResolvedResource } from "../package-manager.ts";
7
7
  import type { Extension, ExtensionFactory, ExtensionRuntime, LoadExtensionsResult } from "./types.ts";
8
+ export interface WorkflowResourceProvider {
9
+ get(): ResolvedResource[];
10
+ refresh?(): Promise<ResolvedResource[]>;
11
+ }
12
+ export type WorkflowResourceProviderInput = WorkflowResourceProvider | ResolvedResource[];
8
13
  /**
9
14
  * Create a runtime with throwing stubs for action methods.
10
15
  * Runner.bindCore() replaces these with real implementations.
@@ -13,11 +18,11 @@ export declare function createExtensionRuntime(): ExtensionRuntime;
13
18
  /**
14
19
  * Create an Extension from an inline factory function.
15
20
  */
16
- export declare function loadExtensionFromFactory(factory: ExtensionFactory, cwd: string, eventBus: EventBus, runtime: ExtensionRuntime, extensionPath?: string, workflowResources?: ResolvedResource[]): Promise<Extension>;
21
+ export declare function loadExtensionFromFactory(factory: ExtensionFactory, cwd: string, eventBus: EventBus, runtime: ExtensionRuntime, extensionPath?: string, workflowResourceProvider?: WorkflowResourceProviderInput): Promise<Extension>;
17
22
  /**
18
23
  * Load extensions from paths.
19
24
  */
20
- export declare function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus, workflowResources?: ResolvedResource[]): Promise<LoadExtensionsResult>;
25
+ export declare function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus, workflowResourceProvider?: WorkflowResourceProviderInput): Promise<LoadExtensionsResult>;
21
26
  /**
22
27
  * Discover and load extensions from standard locations.
23
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EACV,SAAS,EAET,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AA8FpB;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAsDzD;AA0QD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAa,EAC1B,iBAAiB,GAAE,gBAAgB,EAAO,GACzC,OAAO,CAAC,SAAS,CAAC,CAYpB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,QAAQ,EACnB,iBAAiB,GAAE,gBAAgB,EAAO,GACzC,OAAO,CAAC,oBAAoB,CAAC,CA+B/B;AAqID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAsB,EAChC,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAAC,oBAAoB,CAAC,CA4C/B","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as _bundledPiAgentCore from \"@earendil-works/pi-agent-core\";\nimport * as _bundledPiAi from \"@earendil-works/pi-ai\";\nimport * as _bundledPiAiOauth from \"@earendil-works/pi-ai/oauth\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport * as _bundledPiTui from \"@earendil-works/pi-tui\";\nimport { createJiti } from \"jiti/static\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport {\n APP_NAME,\n CONFIG_DIR_NAME,\n getAgentDir,\n isBunBinary,\n} from \"../../config.ts\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from the Atomic package\n// name (or upstream-compatible pi package names).\nimport * as _bundledPiCodingAgent from \"../../index.ts\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { createEventBus, type EventBus } from \"../event-bus.ts\";\nimport type { ExecOptions } from \"../exec.ts\";\nimport type { ResolvedResource } from \"../package-manager.ts\";\nimport { execCommand } from \"../exec.ts\";\nimport { createSyntheticSourceInfo } from \"../source-info.ts\";\nimport type {\n Extension,\n ExtensionAPI,\n ExtensionFactory,\n ExtensionRuntime,\n LoadExtensionsResult,\n MessageRenderer,\n ProviderConfig,\n RegisteredCommand,\n ToolDefinition,\n} from \"./types.ts\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n typebox: _bundledTypebox,\n \"typebox/compile\": _bundledTypeboxCompile,\n \"typebox/value\": _bundledTypeboxValue,\n \"@sinclair/typebox\": _bundledTypebox,\n \"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n \"@sinclair/typebox/value\": _bundledTypeboxValue,\n \"@earendil-works/pi-agent-core\": _bundledPiAgentCore,\n \"@earendil-works/pi-tui\": _bundledPiTui,\n \"@earendil-works/pi-ai\": _bundledPiAi,\n \"@earendil-works/pi-ai/oauth\": _bundledPiAiOauth,\n \"@bastani/atomic\": _bundledPiCodingAgent,\n \"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n \"@mariozechner/pi-tui\": _bundledPiTui,\n \"@mariozechner/pi-ai\": _bundledPiAi,\n \"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\n\nfunction getAliases(): Record<string, string> {\n if (_aliases) return _aliases;\n\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n const typeboxEntry = require.resolve(\"typebox\");\n const typeboxCompileEntry = require.resolve(\"typebox/compile\");\n const typeboxValueEntry = require.resolve(\"typebox/value\");\n\n const packagesRoot = path.resolve(__dirname, \"../../../../\");\n const resolveWorkspaceOrImport = (\n workspaceRelativePath: string,\n specifier: string,\n ): string => {\n const workspacePath = path.join(packagesRoot, workspaceRelativePath);\n if (fs.existsSync(workspacePath)) {\n return workspacePath;\n }\n return fileURLToPath(import.meta.resolve(specifier));\n };\n\n const piCodingAgentEntry = packageIndex;\n const piAgentCoreEntry = resolveWorkspaceOrImport(\n \"agent/dist/index.js\",\n \"@earendil-works/pi-agent-core\",\n );\n const piTuiEntry = resolveWorkspaceOrImport(\n \"tui/dist/index.js\",\n \"@earendil-works/pi-tui\",\n );\n const piAiEntry = resolveWorkspaceOrImport(\n \"ai/dist/index.js\",\n \"@earendil-works/pi-ai\",\n );\n const piAiOauthEntry = resolveWorkspaceOrImport(\n \"ai/dist/oauth.js\",\n \"@earendil-works/pi-ai/oauth\",\n );\n\n _aliases = {\n \"@bastani/atomic\": piCodingAgentEntry,\n \"@earendil-works/pi-coding-agent\": piCodingAgentEntry,\n \"@earendil-works/pi-agent-core\": piAgentCoreEntry,\n \"@earendil-works/pi-tui\": piTuiEntry,\n \"@earendil-works/pi-ai\": piAiEntry,\n \"@earendil-works/pi-ai/oauth\": piAiOauthEntry,\n \"@mariozechner/pi-agent-core\": piAgentCoreEntry,\n \"@mariozechner/pi-tui\": piTuiEntry,\n \"@mariozechner/pi-ai\": piAiEntry,\n \"@mariozechner/pi-ai/oauth\": piAiOauthEntry,\n typebox: typeboxEntry,\n \"typebox/compile\": typeboxCompileEntry,\n \"typebox/value\": typeboxValueEntry,\n \"@sinclair/typebox\": typeboxEntry,\n \"@sinclair/typebox/compile\": typeboxCompileEntry,\n \"@sinclair/typebox/value\": typeboxValueEntry,\n };\n\n return _aliases;\n}\n\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n const notInitialized = () => {\n throw new Error(\n \"Extension runtime not initialized. Action methods cannot be called during extension loading.\",\n );\n };\n const state: { staleMessage?: string } = {};\n const assertActive = () => {\n if (state.staleMessage) {\n throw new Error(state.staleMessage);\n }\n };\n\n const runtime: ExtensionRuntime = {\n sendMessage: notInitialized,\n sendUserMessage: notInitialized,\n appendEntry: notInitialized,\n setSessionName: notInitialized,\n getSessionName: notInitialized,\n setLabel: notInitialized,\n getActiveTools: notInitialized,\n getAllTools: notInitialized,\n setActiveTools: notInitialized,\n // registerTool() is valid during extension load; refresh is only needed post-bind.\n refreshTools: () => {},\n getCommands: notInitialized,\n setModel: () =>\n Promise.reject(new Error(\"Extension runtime not initialized\")),\n getThinkingLevel: notInitialized,\n setThinkingLevel: notInitialized,\n flagValues: new Map(),\n pendingProviderRegistrations: [],\n assertActive,\n invalidate: (message) => {\n state.staleMessage ??=\n message ??\n \"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n },\n // Pre-bind: queue registrations so bindCore() can flush them once the\n // model registry is available. bindCore() replaces both with direct calls.\n registerProvider: (name, config, extensionPath = \"<unknown>\") => {\n runtime.pendingProviderRegistrations.push({\n name,\n config,\n extensionPath,\n });\n },\n unregisterProvider: (name) => {\n runtime.pendingProviderRegistrations =\n runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n },\n };\n\n return runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n extension: Extension,\n runtime: ExtensionRuntime,\n cwd: string,\n eventBus: EventBus,\n workflowResources: ResolvedResource[] = [],\n): ExtensionAPI {\n const api = {\n // Registration methods - write to extension\n on(event: string, handler: HandlerFn): void {\n runtime.assertActive();\n const list = extension.handlers.get(event) ?? [];\n list.push(handler);\n extension.handlers.set(event, list);\n },\n\n registerTool(tool: ToolDefinition): void {\n runtime.assertActive();\n extension.tools.set(tool.name, {\n definition: tool,\n sourceInfo: extension.sourceInfo,\n });\n runtime.refreshTools();\n },\n\n registerCommand(\n name: string,\n options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">,\n ): void {\n runtime.assertActive();\n extension.commands.set(name, {\n name,\n sourceInfo: extension.sourceInfo,\n ...options,\n });\n },\n\n registerShortcut(\n shortcut: KeyId,\n options: {\n description?: string;\n handler: (\n ctx: import(\"./types.ts\").ExtensionContext,\n ) => Promise<void> | void;\n },\n ): void {\n runtime.assertActive();\n extension.shortcuts.set(shortcut, {\n shortcut,\n extensionPath: extension.path,\n ...options,\n });\n },\n\n registerFlag(\n name: string,\n options: {\n description?: string;\n type: \"boolean\" | \"string\";\n default?: boolean | string;\n },\n ): void {\n runtime.assertActive();\n extension.flags.set(name, {\n name,\n extensionPath: extension.path,\n ...options,\n });\n if (options.default !== undefined && !runtime.flagValues.has(name)) {\n runtime.flagValues.set(name, options.default);\n }\n },\n\n registerMessageRenderer<T>(\n customType: string,\n renderer: MessageRenderer<T>,\n ): void {\n runtime.assertActive();\n extension.messageRenderers.set(customType, renderer as MessageRenderer);\n },\n\n // Flag access - checks extension registered it, reads from runtime\n getFlag(name: string): boolean | string | undefined {\n runtime.assertActive();\n if (!extension.flags.has(name)) return undefined;\n return runtime.flagValues.get(name);\n },\n\n getWorkflowResources(): ResolvedResource[] {\n runtime.assertActive();\n return [...workflowResources];\n },\n\n // Action methods - delegate to shared runtime\n sendMessage(message, options): void {\n runtime.assertActive();\n runtime.sendMessage(message, options);\n },\n\n sendUserMessage(content, options): void {\n runtime.assertActive();\n runtime.sendUserMessage(content, options);\n },\n\n appendEntry(customType: string, data?: unknown): void {\n runtime.assertActive();\n runtime.appendEntry(customType, data);\n },\n\n setSessionName(name: string): void {\n runtime.assertActive();\n runtime.setSessionName(name);\n },\n\n getSessionName(): string | undefined {\n runtime.assertActive();\n return runtime.getSessionName();\n },\n\n setLabel(entryId: string, label: string | undefined): void {\n runtime.assertActive();\n runtime.setLabel(entryId, label);\n },\n\n exec(command: string, args: string[], options?: ExecOptions) {\n runtime.assertActive();\n return execCommand(command, args, options?.cwd ?? cwd, options);\n },\n\n getActiveTools(): string[] {\n runtime.assertActive();\n return runtime.getActiveTools();\n },\n\n getAllTools() {\n runtime.assertActive();\n return runtime.getAllTools();\n },\n\n setActiveTools(toolNames: string[]): void {\n runtime.assertActive();\n runtime.setActiveTools(toolNames);\n },\n\n getCommands() {\n runtime.assertActive();\n return runtime.getCommands();\n },\n\n setModel(model) {\n runtime.assertActive();\n return runtime.setModel(model);\n },\n\n getThinkingLevel() {\n runtime.assertActive();\n return runtime.getThinkingLevel();\n },\n\n setThinkingLevel(level) {\n runtime.assertActive();\n runtime.setThinkingLevel(level);\n },\n\n registerProvider(name: string, config: ProviderConfig) {\n runtime.assertActive();\n runtime.registerProvider(name, config, extension.path);\n },\n\n unregisterProvider(name: string) {\n runtime.assertActive();\n runtime.unregisterProvider(name, extension.path);\n },\n\n events: eventBus,\n } as ExtensionAPI;\n\n return api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n const jiti = createJiti(import.meta.url, {\n moduleCache: false,\n // In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n // Also disable tryNative so jiti handles ALL imports (not just the entry point)\n // In Node.js/dev: use aliases to resolve to node_modules paths\n ...(isBunBinary\n ? { virtualModules: VIRTUAL_MODULES, tryNative: false }\n : { alias: getAliases() }),\n });\n\n const module = await jiti.import(extensionPath, { default: true });\n const factory = module as ExtensionFactory;\n return typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(\n extensionPath: string,\n resolvedPath: string,\n): Extension {\n const source =\n extensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n ? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n : \"local\";\n const baseDir = extensionPath.startsWith(\"<\")\n ? undefined\n : path.dirname(resolvedPath);\n\n return {\n path: extensionPath,\n resolvedPath,\n sourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\n handlers: new Map(),\n tools: new Map(),\n messageRenderers: new Map(),\n commands: new Map(),\n flags: new Map(),\n shortcuts: new Map(),\n };\n}\n\nasync function loadExtension(\n extensionPath: string,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n workflowResources: ResolvedResource[] = [],\n): Promise<{ extension: Extension | null; error: string | null }> {\n const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });\n\n try {\n const factory = await loadExtensionModule(resolvedPath);\n if (!factory) {\n return {\n extension: null,\n error: `Extension does not export a valid factory function: ${extensionPath}`,\n };\n }\n\n const extension = createExtension(extensionPath, resolvedPath);\n const api = createExtensionAPI(\n extension,\n runtime,\n cwd,\n eventBus,\n workflowResources,\n );\n await factory(api);\n\n return { extension, error: null };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { extension: null, error: `Failed to load extension: ${message}` };\n }\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n factory: ExtensionFactory,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n extensionPath = \"<inline>\",\n workflowResources: ResolvedResource[] = [],\n): Promise<Extension> {\n const extension = createExtension(extensionPath, extensionPath);\n const resolvedCwd = resolvePath(cwd);\n const api = createExtensionAPI(\n extension,\n runtime,\n resolvedCwd,\n eventBus,\n workflowResources,\n );\n await factory(api);\n return extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(\n paths: string[],\n cwd: string,\n eventBus?: EventBus,\n workflowResources: ResolvedResource[] = [],\n): Promise<LoadExtensionsResult> {\n const extensions: Extension[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n const resolvedCwd = resolvePath(cwd);\n const resolvedEventBus = eventBus ?? createEventBus();\n const runtime = createExtensionRuntime();\n\n for (const extPath of paths) {\n const { extension, error } = await loadExtension(\n extPath,\n resolvedCwd,\n resolvedEventBus,\n runtime,\n workflowResources,\n );\n\n if (error) {\n errors.push({ path: extPath, error });\n continue;\n }\n\n if (extension) {\n extensions.push(extension);\n }\n }\n\n return {\n extensions,\n errors,\n runtime,\n };\n}\n\ninterface PiManifest {\n extensions?: string[];\n themes?: string[];\n skills?: string[];\n prompts?: string[];\n}\n\nfunction manifestFromPackageJson(\n pkg: Record<string, unknown>,\n): PiManifest | null {\n const appManifest = pkg[APP_NAME];\n if (\n appManifest &&\n typeof appManifest === \"object\" &&\n !Array.isArray(appManifest)\n ) {\n return appManifest as PiManifest;\n }\n const legacyManifest = pkg.pi;\n if (\n legacyManifest &&\n typeof legacyManifest === \"object\" &&\n !Array.isArray(legacyManifest)\n ) {\n return legacyManifest as PiManifest;\n }\n return null;\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n try {\n const content = fs.readFileSync(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as Record<string, unknown>;\n return manifestFromPackageJson(pkg);\n } catch {\n return null;\n }\n}\n\nfunction isExtensionFile(name: string): boolean {\n return name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n // Check for package.json with \"pi\" field first\n const packageJsonPath = path.join(dir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const manifest = readPiManifest(packageJsonPath);\n if (manifest?.extensions?.length) {\n const entries: string[] = [];\n for (const extPath of manifest.extensions) {\n const resolvedExtPath = path.resolve(dir, extPath);\n if (fs.existsSync(resolvedExtPath)) {\n entries.push(resolvedExtPath);\n }\n }\n if (entries.length > 0) {\n return entries;\n }\n }\n }\n\n // Check for index.ts or index.js\n const indexTs = path.join(dir, \"index.ts\");\n const indexJs = path.join(dir, \"index.js\");\n if (fs.existsSync(indexTs)) {\n return [indexTs];\n }\n if (fs.existsSync(indexJs)) {\n return [indexJs];\n }\n\n return null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const discovered: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(dir, entry.name);\n\n // 1. Direct files: *.ts or *.js\n if (\n (entry.isFile() || entry.isSymbolicLink()) &&\n isExtensionFile(entry.name)\n ) {\n discovered.push(entryPath);\n continue;\n }\n\n // 2 & 3. Subdirectories\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n const entries = resolveExtensionEntries(entryPath);\n if (entries) {\n discovered.push(...entries);\n }\n }\n }\n } catch {\n return [];\n }\n\n return discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n configuredPaths: string[],\n cwd: string,\n agentDir: string = getAgentDir(),\n eventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n const resolvedCwd = resolvePath(cwd);\n const resolvedAgentDir = resolvePath(agentDir);\n const allPaths: string[] = [];\n const seen = new Set<string>();\n\n const addPaths = (paths: string[]) => {\n for (const p of paths) {\n const resolved = path.resolve(p);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n allPaths.push(p);\n }\n }\n };\n\n // 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/\n const localExtDir = path.join(resolvedCwd, CONFIG_DIR_NAME, \"extensions\");\n addPaths(discoverExtensionsInDir(localExtDir));\n\n // 2. Global extensions: agentDir/extensions/\n const globalExtDir = path.join(resolvedAgentDir, \"extensions\");\n addPaths(discoverExtensionsInDir(globalExtDir));\n\n // 3. Explicitly configured paths\n for (const p of configuredPaths) {\n const resolved = resolvePath(p, resolvedCwd, { normalizeUnicodeSpaces: true });\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n // Check for package.json with pi manifest or index.ts\n const entries = resolveExtensionEntries(resolved);\n if (entries) {\n addPaths(entries);\n continue;\n }\n // No explicit entries - discover individual files in directory\n addPaths(discoverExtensionsInDir(resolved));\n continue;\n }\n\n addPaths([resolved]);\n }\n\n return loadExtensions(allPaths, resolvedCwd, eventBus);\n\n}\n"]}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EACV,SAAS,EAET,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AA8FpB,MAAM,WAAW,wBAAwB;IACvC,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,6BAA6B,GAAG,wBAAwB,GAAG,gBAAgB,EAAE,CAAC;AAc1F;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAsDzD;AAiRD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAa,EAC1B,wBAAwB,GAAE,6BAA6D,GACtF,OAAO,CAAC,SAAS,CAAC,CAYpB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,QAAQ,EACnB,wBAAwB,GAAE,6BAA6D,GACtF,OAAO,CAAC,oBAAoB,CAAC,CA+B/B;AAqID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAsB,EAChC,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAAC,oBAAoB,CAAC,CA4C/B","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as _bundledPiAgentCore from \"@earendil-works/pi-agent-core\";\nimport * as _bundledPiAi from \"@earendil-works/pi-ai\";\nimport * as _bundledPiAiOauth from \"@earendil-works/pi-ai/oauth\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport * as _bundledPiTui from \"@earendil-works/pi-tui\";\nimport { createJiti } from \"jiti/static\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport {\n APP_NAME,\n CONFIG_DIR_NAME,\n getAgentDir,\n isBunBinary,\n} from \"../../config.ts\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from the Atomic package\n// name (or upstream-compatible pi package names).\nimport * as _bundledPiCodingAgent from \"../../index.ts\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { createEventBus, type EventBus } from \"../event-bus.ts\";\nimport type { ExecOptions } from \"../exec.ts\";\nimport type { ResolvedResource } from \"../package-manager.ts\";\nimport { execCommand } from \"../exec.ts\";\nimport { createSyntheticSourceInfo } from \"../source-info.ts\";\nimport type {\n Extension,\n ExtensionAPI,\n ExtensionFactory,\n ExtensionRuntime,\n LoadExtensionsResult,\n MessageRenderer,\n ProviderConfig,\n RegisteredCommand,\n ToolDefinition,\n} from \"./types.ts\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n typebox: _bundledTypebox,\n \"typebox/compile\": _bundledTypeboxCompile,\n \"typebox/value\": _bundledTypeboxValue,\n \"@sinclair/typebox\": _bundledTypebox,\n \"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n \"@sinclair/typebox/value\": _bundledTypeboxValue,\n \"@earendil-works/pi-agent-core\": _bundledPiAgentCore,\n \"@earendil-works/pi-tui\": _bundledPiTui,\n \"@earendil-works/pi-ai\": _bundledPiAi,\n \"@earendil-works/pi-ai/oauth\": _bundledPiAiOauth,\n \"@bastani/atomic\": _bundledPiCodingAgent,\n \"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n \"@mariozechner/pi-tui\": _bundledPiTui,\n \"@mariozechner/pi-ai\": _bundledPiAi,\n \"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\n\nfunction getAliases(): Record<string, string> {\n if (_aliases) return _aliases;\n\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n const typeboxEntry = require.resolve(\"typebox\");\n const typeboxCompileEntry = require.resolve(\"typebox/compile\");\n const typeboxValueEntry = require.resolve(\"typebox/value\");\n\n const packagesRoot = path.resolve(__dirname, \"../../../../\");\n const resolveWorkspaceOrImport = (\n workspaceRelativePath: string,\n specifier: string,\n ): string => {\n const workspacePath = path.join(packagesRoot, workspaceRelativePath);\n if (fs.existsSync(workspacePath)) {\n return workspacePath;\n }\n return fileURLToPath(import.meta.resolve(specifier));\n };\n\n const piCodingAgentEntry = packageIndex;\n const piAgentCoreEntry = resolveWorkspaceOrImport(\n \"agent/dist/index.js\",\n \"@earendil-works/pi-agent-core\",\n );\n const piTuiEntry = resolveWorkspaceOrImport(\n \"tui/dist/index.js\",\n \"@earendil-works/pi-tui\",\n );\n const piAiEntry = resolveWorkspaceOrImport(\n \"ai/dist/index.js\",\n \"@earendil-works/pi-ai\",\n );\n const piAiOauthEntry = resolveWorkspaceOrImport(\n \"ai/dist/oauth.js\",\n \"@earendil-works/pi-ai/oauth\",\n );\n\n _aliases = {\n \"@bastani/atomic\": piCodingAgentEntry,\n \"@earendil-works/pi-coding-agent\": piCodingAgentEntry,\n \"@earendil-works/pi-agent-core\": piAgentCoreEntry,\n \"@earendil-works/pi-tui\": piTuiEntry,\n \"@earendil-works/pi-ai\": piAiEntry,\n \"@earendil-works/pi-ai/oauth\": piAiOauthEntry,\n \"@mariozechner/pi-agent-core\": piAgentCoreEntry,\n \"@mariozechner/pi-tui\": piTuiEntry,\n \"@mariozechner/pi-ai\": piAiEntry,\n \"@mariozechner/pi-ai/oauth\": piAiOauthEntry,\n typebox: typeboxEntry,\n \"typebox/compile\": typeboxCompileEntry,\n \"typebox/value\": typeboxValueEntry,\n \"@sinclair/typebox\": typeboxEntry,\n \"@sinclair/typebox/compile\": typeboxCompileEntry,\n \"@sinclair/typebox/value\": typeboxValueEntry,\n };\n\n return _aliases;\n}\n\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport interface WorkflowResourceProvider {\n get(): ResolvedResource[];\n refresh?(): Promise<ResolvedResource[]>;\n}\n\nexport type WorkflowResourceProviderInput = WorkflowResourceProvider | ResolvedResource[];\n\nfunction createStaticWorkflowResourceProvider(workflowResources: ResolvedResource[]): WorkflowResourceProvider {\n return {\n get: () => workflowResources,\n };\n}\n\nfunction normalizeWorkflowResourceProvider(input: WorkflowResourceProviderInput): WorkflowResourceProvider {\n return Array.isArray(input) ? createStaticWorkflowResourceProvider(input) : input;\n}\n\nconst emptyWorkflowResourceProvider = createStaticWorkflowResourceProvider([]);\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n const notInitialized = () => {\n throw new Error(\n \"Extension runtime not initialized. Action methods cannot be called during extension loading.\",\n );\n };\n const state: { staleMessage?: string } = {};\n const assertActive = () => {\n if (state.staleMessage) {\n throw new Error(state.staleMessage);\n }\n };\n\n const runtime: ExtensionRuntime = {\n sendMessage: notInitialized,\n sendUserMessage: notInitialized,\n appendEntry: notInitialized,\n setSessionName: notInitialized,\n getSessionName: notInitialized,\n setLabel: notInitialized,\n getActiveTools: notInitialized,\n getAllTools: notInitialized,\n setActiveTools: notInitialized,\n // registerTool() is valid during extension load; refresh is only needed post-bind.\n refreshTools: () => {},\n getCommands: notInitialized,\n setModel: () =>\n Promise.reject(new Error(\"Extension runtime not initialized\")),\n getThinkingLevel: notInitialized,\n setThinkingLevel: notInitialized,\n flagValues: new Map(),\n pendingProviderRegistrations: [],\n assertActive,\n invalidate: (message) => {\n state.staleMessage ??=\n message ??\n \"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n },\n // Pre-bind: queue registrations so bindCore() can flush them once the\n // model registry is available. bindCore() replaces both with direct calls.\n registerProvider: (name, config, extensionPath = \"<unknown>\") => {\n runtime.pendingProviderRegistrations.push({\n name,\n config,\n extensionPath,\n });\n },\n unregisterProvider: (name) => {\n runtime.pendingProviderRegistrations =\n runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n },\n };\n\n return runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n extension: Extension,\n runtime: ExtensionRuntime,\n cwd: string,\n eventBus: EventBus,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): ExtensionAPI {\n const workflowResources = normalizeWorkflowResourceProvider(workflowResourceProvider);\n const api = {\n // Registration methods - write to extension\n on(event: string, handler: HandlerFn): void {\n runtime.assertActive();\n const list = extension.handlers.get(event) ?? [];\n list.push(handler);\n extension.handlers.set(event, list);\n },\n\n registerTool(tool: ToolDefinition): void {\n runtime.assertActive();\n extension.tools.set(tool.name, {\n definition: tool,\n sourceInfo: extension.sourceInfo,\n });\n runtime.refreshTools();\n },\n\n registerCommand(\n name: string,\n options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">,\n ): void {\n runtime.assertActive();\n extension.commands.set(name, {\n name,\n sourceInfo: extension.sourceInfo,\n ...options,\n });\n },\n\n registerShortcut(\n shortcut: KeyId,\n options: {\n description?: string;\n handler: (\n ctx: import(\"./types.ts\").ExtensionContext,\n ) => Promise<void> | void;\n },\n ): void {\n runtime.assertActive();\n extension.shortcuts.set(shortcut, {\n shortcut,\n extensionPath: extension.path,\n ...options,\n });\n },\n\n registerFlag(\n name: string,\n options: {\n description?: string;\n type: \"boolean\" | \"string\";\n default?: boolean | string;\n },\n ): void {\n runtime.assertActive();\n extension.flags.set(name, {\n name,\n extensionPath: extension.path,\n ...options,\n });\n if (options.default !== undefined && !runtime.flagValues.has(name)) {\n runtime.flagValues.set(name, options.default);\n }\n },\n\n registerMessageRenderer<T>(\n customType: string,\n renderer: MessageRenderer<T>,\n ): void {\n runtime.assertActive();\n extension.messageRenderers.set(customType, renderer as MessageRenderer);\n },\n\n // Flag access - checks extension registered it, reads from runtime\n getFlag(name: string): boolean | string | undefined {\n runtime.assertActive();\n if (!extension.flags.has(name)) return undefined;\n return runtime.flagValues.get(name);\n },\n\n getWorkflowResources(): ResolvedResource[] {\n runtime.assertActive();\n return [...workflowResources.get()];\n },\n\n async refreshWorkflowResources(): Promise<ResolvedResource[]> {\n runtime.assertActive();\n const refreshed = await workflowResources.refresh?.();\n return [...(refreshed ?? workflowResources.get())];\n },\n\n // Action methods - delegate to shared runtime\n sendMessage(message, options): void {\n runtime.assertActive();\n runtime.sendMessage(message, options);\n },\n\n sendUserMessage(content, options): void {\n runtime.assertActive();\n runtime.sendUserMessage(content, options);\n },\n\n appendEntry(customType: string, data?: unknown): void {\n runtime.assertActive();\n runtime.appendEntry(customType, data);\n },\n\n setSessionName(name: string): void {\n runtime.assertActive();\n runtime.setSessionName(name);\n },\n\n getSessionName(): string | undefined {\n runtime.assertActive();\n return runtime.getSessionName();\n },\n\n setLabel(entryId: string, label: string | undefined): void {\n runtime.assertActive();\n runtime.setLabel(entryId, label);\n },\n\n exec(command: string, args: string[], options?: ExecOptions) {\n runtime.assertActive();\n return execCommand(command, args, options?.cwd ?? cwd, options);\n },\n\n getActiveTools(): string[] {\n runtime.assertActive();\n return runtime.getActiveTools();\n },\n\n getAllTools() {\n runtime.assertActive();\n return runtime.getAllTools();\n },\n\n setActiveTools(toolNames: string[]): void {\n runtime.assertActive();\n runtime.setActiveTools(toolNames);\n },\n\n getCommands() {\n runtime.assertActive();\n return runtime.getCommands();\n },\n\n setModel(model) {\n runtime.assertActive();\n return runtime.setModel(model);\n },\n\n getThinkingLevel() {\n runtime.assertActive();\n return runtime.getThinkingLevel();\n },\n\n setThinkingLevel(level) {\n runtime.assertActive();\n runtime.setThinkingLevel(level);\n },\n\n registerProvider(name: string, config: ProviderConfig) {\n runtime.assertActive();\n runtime.registerProvider(name, config, extension.path);\n },\n\n unregisterProvider(name: string) {\n runtime.assertActive();\n runtime.unregisterProvider(name, extension.path);\n },\n\n events: eventBus,\n } as ExtensionAPI;\n\n return api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n const jiti = createJiti(import.meta.url, {\n moduleCache: false,\n // In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n // Also disable tryNative so jiti handles ALL imports (not just the entry point)\n // In Node.js/dev: use aliases to resolve to node_modules paths\n ...(isBunBinary\n ? { virtualModules: VIRTUAL_MODULES, tryNative: false }\n : { alias: getAliases() }),\n });\n\n const module = await jiti.import(extensionPath, { default: true });\n const factory = module as ExtensionFactory;\n return typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(\n extensionPath: string,\n resolvedPath: string,\n): Extension {\n const source =\n extensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n ? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n : \"local\";\n const baseDir = extensionPath.startsWith(\"<\")\n ? undefined\n : path.dirname(resolvedPath);\n\n return {\n path: extensionPath,\n resolvedPath,\n sourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\n handlers: new Map(),\n tools: new Map(),\n messageRenderers: new Map(),\n commands: new Map(),\n flags: new Map(),\n shortcuts: new Map(),\n };\n}\n\nasync function loadExtension(\n extensionPath: string,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<{ extension: Extension | null; error: string | null }> {\n const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });\n\n try {\n const factory = await loadExtensionModule(resolvedPath);\n if (!factory) {\n return {\n extension: null,\n error: `Extension does not export a valid factory function: ${extensionPath}`,\n };\n }\n\n const extension = createExtension(extensionPath, resolvedPath);\n const api = createExtensionAPI(\n extension,\n runtime,\n cwd,\n eventBus,\n workflowResourceProvider,\n );\n await factory(api);\n\n return { extension, error: null };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { extension: null, error: `Failed to load extension: ${message}` };\n }\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n factory: ExtensionFactory,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n extensionPath = \"<inline>\",\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<Extension> {\n const extension = createExtension(extensionPath, extensionPath);\n const resolvedCwd = resolvePath(cwd);\n const api = createExtensionAPI(\n extension,\n runtime,\n resolvedCwd,\n eventBus,\n workflowResourceProvider,\n );\n await factory(api);\n return extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(\n paths: string[],\n cwd: string,\n eventBus?: EventBus,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<LoadExtensionsResult> {\n const extensions: Extension[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n const resolvedCwd = resolvePath(cwd);\n const resolvedEventBus = eventBus ?? createEventBus();\n const runtime = createExtensionRuntime();\n\n for (const extPath of paths) {\n const { extension, error } = await loadExtension(\n extPath,\n resolvedCwd,\n resolvedEventBus,\n runtime,\n workflowResourceProvider,\n );\n\n if (error) {\n errors.push({ path: extPath, error });\n continue;\n }\n\n if (extension) {\n extensions.push(extension);\n }\n }\n\n return {\n extensions,\n errors,\n runtime,\n };\n}\n\ninterface PiManifest {\n extensions?: string[];\n themes?: string[];\n skills?: string[];\n prompts?: string[];\n}\n\nfunction manifestFromPackageJson(\n pkg: Record<string, unknown>,\n): PiManifest | null {\n const appManifest = pkg[APP_NAME];\n if (\n appManifest &&\n typeof appManifest === \"object\" &&\n !Array.isArray(appManifest)\n ) {\n return appManifest as PiManifest;\n }\n const legacyManifest = pkg.pi;\n if (\n legacyManifest &&\n typeof legacyManifest === \"object\" &&\n !Array.isArray(legacyManifest)\n ) {\n return legacyManifest as PiManifest;\n }\n return null;\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n try {\n const content = fs.readFileSync(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as Record<string, unknown>;\n return manifestFromPackageJson(pkg);\n } catch {\n return null;\n }\n}\n\nfunction isExtensionFile(name: string): boolean {\n return name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n // Check for package.json with \"pi\" field first\n const packageJsonPath = path.join(dir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const manifest = readPiManifest(packageJsonPath);\n if (manifest?.extensions?.length) {\n const entries: string[] = [];\n for (const extPath of manifest.extensions) {\n const resolvedExtPath = path.resolve(dir, extPath);\n if (fs.existsSync(resolvedExtPath)) {\n entries.push(resolvedExtPath);\n }\n }\n if (entries.length > 0) {\n return entries;\n }\n }\n }\n\n // Check for index.ts or index.js\n const indexTs = path.join(dir, \"index.ts\");\n const indexJs = path.join(dir, \"index.js\");\n if (fs.existsSync(indexTs)) {\n return [indexTs];\n }\n if (fs.existsSync(indexJs)) {\n return [indexJs];\n }\n\n return null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const discovered: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(dir, entry.name);\n\n // 1. Direct files: *.ts or *.js\n if (\n (entry.isFile() || entry.isSymbolicLink()) &&\n isExtensionFile(entry.name)\n ) {\n discovered.push(entryPath);\n continue;\n }\n\n // 2 & 3. Subdirectories\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n const entries = resolveExtensionEntries(entryPath);\n if (entries) {\n discovered.push(...entries);\n }\n }\n }\n } catch {\n return [];\n }\n\n return discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n configuredPaths: string[],\n cwd: string,\n agentDir: string = getAgentDir(),\n eventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n const resolvedCwd = resolvePath(cwd);\n const resolvedAgentDir = resolvePath(agentDir);\n const allPaths: string[] = [];\n const seen = new Set<string>();\n\n const addPaths = (paths: string[]) => {\n for (const p of paths) {\n const resolved = path.resolve(p);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n allPaths.push(p);\n }\n }\n };\n\n // 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/\n const localExtDir = path.join(resolvedCwd, CONFIG_DIR_NAME, \"extensions\");\n addPaths(discoverExtensionsInDir(localExtDir));\n\n // 2. Global extensions: agentDir/extensions/\n const globalExtDir = path.join(resolvedAgentDir, \"extensions\");\n addPaths(discoverExtensionsInDir(globalExtDir));\n\n // 3. Explicitly configured paths\n for (const p of configuredPaths) {\n const resolved = resolvePath(p, resolvedCwd, { normalizeUnicodeSpaces: true });\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n // Check for package.json with pi manifest or index.ts\n const entries = resolveExtensionEntries(resolved);\n if (entries) {\n addPaths(entries);\n continue;\n }\n // No explicit entries - discover individual files in directory\n addPaths(discoverExtensionsInDir(resolved));\n continue;\n }\n\n addPaths([resolved]);\n }\n\n return loadExtensions(allPaths, resolvedCwd, eventBus);\n\n}\n"]}
@@ -91,6 +91,15 @@ function getAliases() {
91
91
  };
92
92
  return _aliases;
93
93
  }
94
+ function createStaticWorkflowResourceProvider(workflowResources) {
95
+ return {
96
+ get: () => workflowResources,
97
+ };
98
+ }
99
+ function normalizeWorkflowResourceProvider(input) {
100
+ return Array.isArray(input) ? createStaticWorkflowResourceProvider(input) : input;
101
+ }
102
+ const emptyWorkflowResourceProvider = createStaticWorkflowResourceProvider([]);
94
103
  /**
95
104
  * Create a runtime with throwing stubs for action methods.
96
105
  * Runner.bindCore() replaces these with real implementations.
@@ -150,7 +159,8 @@ export function createExtensionRuntime() {
150
159
  * Registration methods write to the extension object.
151
160
  * Action methods delegate to the shared runtime.
152
161
  */
153
- function createExtensionAPI(extension, runtime, cwd, eventBus, workflowResources = []) {
162
+ function createExtensionAPI(extension, runtime, cwd, eventBus, workflowResourceProvider = emptyWorkflowResourceProvider) {
163
+ const workflowResources = normalizeWorkflowResourceProvider(workflowResourceProvider);
154
164
  const api = {
155
165
  // Registration methods - write to extension
156
166
  on(event, handler) {
@@ -207,7 +217,12 @@ function createExtensionAPI(extension, runtime, cwd, eventBus, workflowResources
207
217
  },
208
218
  getWorkflowResources() {
209
219
  runtime.assertActive();
210
- return [...workflowResources];
220
+ return [...workflowResources.get()];
221
+ },
222
+ async refreshWorkflowResources() {
223
+ runtime.assertActive();
224
+ const refreshed = await workflowResources.refresh?.();
225
+ return [...(refreshed ?? workflowResources.get())];
211
226
  },
212
227
  // Action methods - delegate to shared runtime
213
228
  sendMessage(message, options) {
@@ -314,7 +329,7 @@ function createExtension(extensionPath, resolvedPath) {
314
329
  shortcuts: new Map(),
315
330
  };
316
331
  }
317
- async function loadExtension(extensionPath, cwd, eventBus, runtime, workflowResources = []) {
332
+ async function loadExtension(extensionPath, cwd, eventBus, runtime, workflowResourceProvider = emptyWorkflowResourceProvider) {
318
333
  const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });
319
334
  try {
320
335
  const factory = await loadExtensionModule(resolvedPath);
@@ -325,7 +340,7 @@ async function loadExtension(extensionPath, cwd, eventBus, runtime, workflowReso
325
340
  };
326
341
  }
327
342
  const extension = createExtension(extensionPath, resolvedPath);
328
- const api = createExtensionAPI(extension, runtime, cwd, eventBus, workflowResources);
343
+ const api = createExtensionAPI(extension, runtime, cwd, eventBus, workflowResourceProvider);
329
344
  await factory(api);
330
345
  return { extension, error: null };
331
346
  }
@@ -337,24 +352,24 @@ async function loadExtension(extensionPath, cwd, eventBus, runtime, workflowReso
337
352
  /**
338
353
  * Create an Extension from an inline factory function.
339
354
  */
340
- export async function loadExtensionFromFactory(factory, cwd, eventBus, runtime, extensionPath = "<inline>", workflowResources = []) {
355
+ export async function loadExtensionFromFactory(factory, cwd, eventBus, runtime, extensionPath = "<inline>", workflowResourceProvider = emptyWorkflowResourceProvider) {
341
356
  const extension = createExtension(extensionPath, extensionPath);
342
357
  const resolvedCwd = resolvePath(cwd);
343
- const api = createExtensionAPI(extension, runtime, resolvedCwd, eventBus, workflowResources);
358
+ const api = createExtensionAPI(extension, runtime, resolvedCwd, eventBus, workflowResourceProvider);
344
359
  await factory(api);
345
360
  return extension;
346
361
  }
347
362
  /**
348
363
  * Load extensions from paths.
349
364
  */
350
- export async function loadExtensions(paths, cwd, eventBus, workflowResources = []) {
365
+ export async function loadExtensions(paths, cwd, eventBus, workflowResourceProvider = emptyWorkflowResourceProvider) {
351
366
  const extensions = [];
352
367
  const errors = [];
353
368
  const resolvedCwd = resolvePath(cwd);
354
369
  const resolvedEventBus = eventBus ?? createEventBus();
355
370
  const runtime = createExtensionRuntime();
356
371
  for (const extPath of paths) {
357
- const { extension, error } = await loadExtension(extPath, resolvedCwd, resolvedEventBus, runtime, workflowResources);
372
+ const { extension, error } = await loadExtension(extPath, resolvedCwd, resolvedEventBus, runtime, workflowResourceProvider);
358
373
  if (error) {
359
374
  errors.push({ path: extPath, error });
360
375
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as _bundledPiAgentCore from \"@earendil-works/pi-agent-core\";\nimport * as _bundledPiAi from \"@earendil-works/pi-ai\";\nimport * as _bundledPiAiOauth from \"@earendil-works/pi-ai/oauth\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport * as _bundledPiTui from \"@earendil-works/pi-tui\";\nimport { createJiti } from \"jiti/static\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport {\n APP_NAME,\n CONFIG_DIR_NAME,\n getAgentDir,\n isBunBinary,\n} from \"../../config.ts\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from the Atomic package\n// name (or upstream-compatible pi package names).\nimport * as _bundledPiCodingAgent from \"../../index.ts\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { createEventBus, type EventBus } from \"../event-bus.ts\";\nimport type { ExecOptions } from \"../exec.ts\";\nimport type { ResolvedResource } from \"../package-manager.ts\";\nimport { execCommand } from \"../exec.ts\";\nimport { createSyntheticSourceInfo } from \"../source-info.ts\";\nimport type {\n Extension,\n ExtensionAPI,\n ExtensionFactory,\n ExtensionRuntime,\n LoadExtensionsResult,\n MessageRenderer,\n ProviderConfig,\n RegisteredCommand,\n ToolDefinition,\n} from \"./types.ts\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n typebox: _bundledTypebox,\n \"typebox/compile\": _bundledTypeboxCompile,\n \"typebox/value\": _bundledTypeboxValue,\n \"@sinclair/typebox\": _bundledTypebox,\n \"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n \"@sinclair/typebox/value\": _bundledTypeboxValue,\n \"@earendil-works/pi-agent-core\": _bundledPiAgentCore,\n \"@earendil-works/pi-tui\": _bundledPiTui,\n \"@earendil-works/pi-ai\": _bundledPiAi,\n \"@earendil-works/pi-ai/oauth\": _bundledPiAiOauth,\n \"@bastani/atomic\": _bundledPiCodingAgent,\n \"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n \"@mariozechner/pi-tui\": _bundledPiTui,\n \"@mariozechner/pi-ai\": _bundledPiAi,\n \"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\n\nfunction getAliases(): Record<string, string> {\n if (_aliases) return _aliases;\n\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n const typeboxEntry = require.resolve(\"typebox\");\n const typeboxCompileEntry = require.resolve(\"typebox/compile\");\n const typeboxValueEntry = require.resolve(\"typebox/value\");\n\n const packagesRoot = path.resolve(__dirname, \"../../../../\");\n const resolveWorkspaceOrImport = (\n workspaceRelativePath: string,\n specifier: string,\n ): string => {\n const workspacePath = path.join(packagesRoot, workspaceRelativePath);\n if (fs.existsSync(workspacePath)) {\n return workspacePath;\n }\n return fileURLToPath(import.meta.resolve(specifier));\n };\n\n const piCodingAgentEntry = packageIndex;\n const piAgentCoreEntry = resolveWorkspaceOrImport(\n \"agent/dist/index.js\",\n \"@earendil-works/pi-agent-core\",\n );\n const piTuiEntry = resolveWorkspaceOrImport(\n \"tui/dist/index.js\",\n \"@earendil-works/pi-tui\",\n );\n const piAiEntry = resolveWorkspaceOrImport(\n \"ai/dist/index.js\",\n \"@earendil-works/pi-ai\",\n );\n const piAiOauthEntry = resolveWorkspaceOrImport(\n \"ai/dist/oauth.js\",\n \"@earendil-works/pi-ai/oauth\",\n );\n\n _aliases = {\n \"@bastani/atomic\": piCodingAgentEntry,\n \"@earendil-works/pi-coding-agent\": piCodingAgentEntry,\n \"@earendil-works/pi-agent-core\": piAgentCoreEntry,\n \"@earendil-works/pi-tui\": piTuiEntry,\n \"@earendil-works/pi-ai\": piAiEntry,\n \"@earendil-works/pi-ai/oauth\": piAiOauthEntry,\n \"@mariozechner/pi-agent-core\": piAgentCoreEntry,\n \"@mariozechner/pi-tui\": piTuiEntry,\n \"@mariozechner/pi-ai\": piAiEntry,\n \"@mariozechner/pi-ai/oauth\": piAiOauthEntry,\n typebox: typeboxEntry,\n \"typebox/compile\": typeboxCompileEntry,\n \"typebox/value\": typeboxValueEntry,\n \"@sinclair/typebox\": typeboxEntry,\n \"@sinclair/typebox/compile\": typeboxCompileEntry,\n \"@sinclair/typebox/value\": typeboxValueEntry,\n };\n\n return _aliases;\n}\n\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n const notInitialized = () => {\n throw new Error(\n \"Extension runtime not initialized. Action methods cannot be called during extension loading.\",\n );\n };\n const state: { staleMessage?: string } = {};\n const assertActive = () => {\n if (state.staleMessage) {\n throw new Error(state.staleMessage);\n }\n };\n\n const runtime: ExtensionRuntime = {\n sendMessage: notInitialized,\n sendUserMessage: notInitialized,\n appendEntry: notInitialized,\n setSessionName: notInitialized,\n getSessionName: notInitialized,\n setLabel: notInitialized,\n getActiveTools: notInitialized,\n getAllTools: notInitialized,\n setActiveTools: notInitialized,\n // registerTool() is valid during extension load; refresh is only needed post-bind.\n refreshTools: () => {},\n getCommands: notInitialized,\n setModel: () =>\n Promise.reject(new Error(\"Extension runtime not initialized\")),\n getThinkingLevel: notInitialized,\n setThinkingLevel: notInitialized,\n flagValues: new Map(),\n pendingProviderRegistrations: [],\n assertActive,\n invalidate: (message) => {\n state.staleMessage ??=\n message ??\n \"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n },\n // Pre-bind: queue registrations so bindCore() can flush them once the\n // model registry is available. bindCore() replaces both with direct calls.\n registerProvider: (name, config, extensionPath = \"<unknown>\") => {\n runtime.pendingProviderRegistrations.push({\n name,\n config,\n extensionPath,\n });\n },\n unregisterProvider: (name) => {\n runtime.pendingProviderRegistrations =\n runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n },\n };\n\n return runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n extension: Extension,\n runtime: ExtensionRuntime,\n cwd: string,\n eventBus: EventBus,\n workflowResources: ResolvedResource[] = [],\n): ExtensionAPI {\n const api = {\n // Registration methods - write to extension\n on(event: string, handler: HandlerFn): void {\n runtime.assertActive();\n const list = extension.handlers.get(event) ?? [];\n list.push(handler);\n extension.handlers.set(event, list);\n },\n\n registerTool(tool: ToolDefinition): void {\n runtime.assertActive();\n extension.tools.set(tool.name, {\n definition: tool,\n sourceInfo: extension.sourceInfo,\n });\n runtime.refreshTools();\n },\n\n registerCommand(\n name: string,\n options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">,\n ): void {\n runtime.assertActive();\n extension.commands.set(name, {\n name,\n sourceInfo: extension.sourceInfo,\n ...options,\n });\n },\n\n registerShortcut(\n shortcut: KeyId,\n options: {\n description?: string;\n handler: (\n ctx: import(\"./types.ts\").ExtensionContext,\n ) => Promise<void> | void;\n },\n ): void {\n runtime.assertActive();\n extension.shortcuts.set(shortcut, {\n shortcut,\n extensionPath: extension.path,\n ...options,\n });\n },\n\n registerFlag(\n name: string,\n options: {\n description?: string;\n type: \"boolean\" | \"string\";\n default?: boolean | string;\n },\n ): void {\n runtime.assertActive();\n extension.flags.set(name, {\n name,\n extensionPath: extension.path,\n ...options,\n });\n if (options.default !== undefined && !runtime.flagValues.has(name)) {\n runtime.flagValues.set(name, options.default);\n }\n },\n\n registerMessageRenderer<T>(\n customType: string,\n renderer: MessageRenderer<T>,\n ): void {\n runtime.assertActive();\n extension.messageRenderers.set(customType, renderer as MessageRenderer);\n },\n\n // Flag access - checks extension registered it, reads from runtime\n getFlag(name: string): boolean | string | undefined {\n runtime.assertActive();\n if (!extension.flags.has(name)) return undefined;\n return runtime.flagValues.get(name);\n },\n\n getWorkflowResources(): ResolvedResource[] {\n runtime.assertActive();\n return [...workflowResources];\n },\n\n // Action methods - delegate to shared runtime\n sendMessage(message, options): void {\n runtime.assertActive();\n runtime.sendMessage(message, options);\n },\n\n sendUserMessage(content, options): void {\n runtime.assertActive();\n runtime.sendUserMessage(content, options);\n },\n\n appendEntry(customType: string, data?: unknown): void {\n runtime.assertActive();\n runtime.appendEntry(customType, data);\n },\n\n setSessionName(name: string): void {\n runtime.assertActive();\n runtime.setSessionName(name);\n },\n\n getSessionName(): string | undefined {\n runtime.assertActive();\n return runtime.getSessionName();\n },\n\n setLabel(entryId: string, label: string | undefined): void {\n runtime.assertActive();\n runtime.setLabel(entryId, label);\n },\n\n exec(command: string, args: string[], options?: ExecOptions) {\n runtime.assertActive();\n return execCommand(command, args, options?.cwd ?? cwd, options);\n },\n\n getActiveTools(): string[] {\n runtime.assertActive();\n return runtime.getActiveTools();\n },\n\n getAllTools() {\n runtime.assertActive();\n return runtime.getAllTools();\n },\n\n setActiveTools(toolNames: string[]): void {\n runtime.assertActive();\n runtime.setActiveTools(toolNames);\n },\n\n getCommands() {\n runtime.assertActive();\n return runtime.getCommands();\n },\n\n setModel(model) {\n runtime.assertActive();\n return runtime.setModel(model);\n },\n\n getThinkingLevel() {\n runtime.assertActive();\n return runtime.getThinkingLevel();\n },\n\n setThinkingLevel(level) {\n runtime.assertActive();\n runtime.setThinkingLevel(level);\n },\n\n registerProvider(name: string, config: ProviderConfig) {\n runtime.assertActive();\n runtime.registerProvider(name, config, extension.path);\n },\n\n unregisterProvider(name: string) {\n runtime.assertActive();\n runtime.unregisterProvider(name, extension.path);\n },\n\n events: eventBus,\n } as ExtensionAPI;\n\n return api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n const jiti = createJiti(import.meta.url, {\n moduleCache: false,\n // In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n // Also disable tryNative so jiti handles ALL imports (not just the entry point)\n // In Node.js/dev: use aliases to resolve to node_modules paths\n ...(isBunBinary\n ? { virtualModules: VIRTUAL_MODULES, tryNative: false }\n : { alias: getAliases() }),\n });\n\n const module = await jiti.import(extensionPath, { default: true });\n const factory = module as ExtensionFactory;\n return typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(\n extensionPath: string,\n resolvedPath: string,\n): Extension {\n const source =\n extensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n ? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n : \"local\";\n const baseDir = extensionPath.startsWith(\"<\")\n ? undefined\n : path.dirname(resolvedPath);\n\n return {\n path: extensionPath,\n resolvedPath,\n sourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\n handlers: new Map(),\n tools: new Map(),\n messageRenderers: new Map(),\n commands: new Map(),\n flags: new Map(),\n shortcuts: new Map(),\n };\n}\n\nasync function loadExtension(\n extensionPath: string,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n workflowResources: ResolvedResource[] = [],\n): Promise<{ extension: Extension | null; error: string | null }> {\n const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });\n\n try {\n const factory = await loadExtensionModule(resolvedPath);\n if (!factory) {\n return {\n extension: null,\n error: `Extension does not export a valid factory function: ${extensionPath}`,\n };\n }\n\n const extension = createExtension(extensionPath, resolvedPath);\n const api = createExtensionAPI(\n extension,\n runtime,\n cwd,\n eventBus,\n workflowResources,\n );\n await factory(api);\n\n return { extension, error: null };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { extension: null, error: `Failed to load extension: ${message}` };\n }\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n factory: ExtensionFactory,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n extensionPath = \"<inline>\",\n workflowResources: ResolvedResource[] = [],\n): Promise<Extension> {\n const extension = createExtension(extensionPath, extensionPath);\n const resolvedCwd = resolvePath(cwd);\n const api = createExtensionAPI(\n extension,\n runtime,\n resolvedCwd,\n eventBus,\n workflowResources,\n );\n await factory(api);\n return extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(\n paths: string[],\n cwd: string,\n eventBus?: EventBus,\n workflowResources: ResolvedResource[] = [],\n): Promise<LoadExtensionsResult> {\n const extensions: Extension[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n const resolvedCwd = resolvePath(cwd);\n const resolvedEventBus = eventBus ?? createEventBus();\n const runtime = createExtensionRuntime();\n\n for (const extPath of paths) {\n const { extension, error } = await loadExtension(\n extPath,\n resolvedCwd,\n resolvedEventBus,\n runtime,\n workflowResources,\n );\n\n if (error) {\n errors.push({ path: extPath, error });\n continue;\n }\n\n if (extension) {\n extensions.push(extension);\n }\n }\n\n return {\n extensions,\n errors,\n runtime,\n };\n}\n\ninterface PiManifest {\n extensions?: string[];\n themes?: string[];\n skills?: string[];\n prompts?: string[];\n}\n\nfunction manifestFromPackageJson(\n pkg: Record<string, unknown>,\n): PiManifest | null {\n const appManifest = pkg[APP_NAME];\n if (\n appManifest &&\n typeof appManifest === \"object\" &&\n !Array.isArray(appManifest)\n ) {\n return appManifest as PiManifest;\n }\n const legacyManifest = pkg.pi;\n if (\n legacyManifest &&\n typeof legacyManifest === \"object\" &&\n !Array.isArray(legacyManifest)\n ) {\n return legacyManifest as PiManifest;\n }\n return null;\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n try {\n const content = fs.readFileSync(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as Record<string, unknown>;\n return manifestFromPackageJson(pkg);\n } catch {\n return null;\n }\n}\n\nfunction isExtensionFile(name: string): boolean {\n return name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n // Check for package.json with \"pi\" field first\n const packageJsonPath = path.join(dir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const manifest = readPiManifest(packageJsonPath);\n if (manifest?.extensions?.length) {\n const entries: string[] = [];\n for (const extPath of manifest.extensions) {\n const resolvedExtPath = path.resolve(dir, extPath);\n if (fs.existsSync(resolvedExtPath)) {\n entries.push(resolvedExtPath);\n }\n }\n if (entries.length > 0) {\n return entries;\n }\n }\n }\n\n // Check for index.ts or index.js\n const indexTs = path.join(dir, \"index.ts\");\n const indexJs = path.join(dir, \"index.js\");\n if (fs.existsSync(indexTs)) {\n return [indexTs];\n }\n if (fs.existsSync(indexJs)) {\n return [indexJs];\n }\n\n return null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const discovered: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(dir, entry.name);\n\n // 1. Direct files: *.ts or *.js\n if (\n (entry.isFile() || entry.isSymbolicLink()) &&\n isExtensionFile(entry.name)\n ) {\n discovered.push(entryPath);\n continue;\n }\n\n // 2 & 3. Subdirectories\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n const entries = resolveExtensionEntries(entryPath);\n if (entries) {\n discovered.push(...entries);\n }\n }\n }\n } catch {\n return [];\n }\n\n return discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n configuredPaths: string[],\n cwd: string,\n agentDir: string = getAgentDir(),\n eventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n const resolvedCwd = resolvePath(cwd);\n const resolvedAgentDir = resolvePath(agentDir);\n const allPaths: string[] = [];\n const seen = new Set<string>();\n\n const addPaths = (paths: string[]) => {\n for (const p of paths) {\n const resolved = path.resolve(p);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n allPaths.push(p);\n }\n }\n };\n\n // 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/\n const localExtDir = path.join(resolvedCwd, CONFIG_DIR_NAME, \"extensions\");\n addPaths(discoverExtensionsInDir(localExtDir));\n\n // 2. Global extensions: agentDir/extensions/\n const globalExtDir = path.join(resolvedAgentDir, \"extensions\");\n addPaths(discoverExtensionsInDir(globalExtDir));\n\n // 3. Explicitly configured paths\n for (const p of configuredPaths) {\n const resolved = resolvePath(p, resolvedCwd, { normalizeUnicodeSpaces: true });\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n // Check for package.json with pi manifest or index.ts\n const entries = resolveExtensionEntries(resolved);\n if (entries) {\n addPaths(entries);\n continue;\n }\n // No explicit entries - discover individual files in directory\n addPaths(discoverExtensionsInDir(resolved));\n continue;\n }\n\n addPaths([resolved]);\n }\n\n return loadExtensions(allPaths, resolvedCwd, eventBus);\n\n}\n"]}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as _bundledPiAgentCore from \"@earendil-works/pi-agent-core\";\nimport * as _bundledPiAi from \"@earendil-works/pi-ai\";\nimport * as _bundledPiAiOauth from \"@earendil-works/pi-ai/oauth\";\nimport type { KeyId } from \"@earendil-works/pi-tui\";\nimport * as _bundledPiTui from \"@earendil-works/pi-tui\";\nimport { createJiti } from \"jiti/static\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport {\n APP_NAME,\n CONFIG_DIR_NAME,\n getAgentDir,\n isBunBinary,\n} from \"../../config.ts\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from the Atomic package\n// name (or upstream-compatible pi package names).\nimport * as _bundledPiCodingAgent from \"../../index.ts\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { createEventBus, type EventBus } from \"../event-bus.ts\";\nimport type { ExecOptions } from \"../exec.ts\";\nimport type { ResolvedResource } from \"../package-manager.ts\";\nimport { execCommand } from \"../exec.ts\";\nimport { createSyntheticSourceInfo } from \"../source-info.ts\";\nimport type {\n Extension,\n ExtensionAPI,\n ExtensionFactory,\n ExtensionRuntime,\n LoadExtensionsResult,\n MessageRenderer,\n ProviderConfig,\n RegisteredCommand,\n ToolDefinition,\n} from \"./types.ts\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n typebox: _bundledTypebox,\n \"typebox/compile\": _bundledTypeboxCompile,\n \"typebox/value\": _bundledTypeboxValue,\n \"@sinclair/typebox\": _bundledTypebox,\n \"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n \"@sinclair/typebox/value\": _bundledTypeboxValue,\n \"@earendil-works/pi-agent-core\": _bundledPiAgentCore,\n \"@earendil-works/pi-tui\": _bundledPiTui,\n \"@earendil-works/pi-ai\": _bundledPiAi,\n \"@earendil-works/pi-ai/oauth\": _bundledPiAiOauth,\n \"@bastani/atomic\": _bundledPiCodingAgent,\n \"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n \"@mariozechner/pi-tui\": _bundledPiTui,\n \"@mariozechner/pi-ai\": _bundledPiAi,\n \"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\n\nfunction getAliases(): Record<string, string> {\n if (_aliases) return _aliases;\n\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n const typeboxEntry = require.resolve(\"typebox\");\n const typeboxCompileEntry = require.resolve(\"typebox/compile\");\n const typeboxValueEntry = require.resolve(\"typebox/value\");\n\n const packagesRoot = path.resolve(__dirname, \"../../../../\");\n const resolveWorkspaceOrImport = (\n workspaceRelativePath: string,\n specifier: string,\n ): string => {\n const workspacePath = path.join(packagesRoot, workspaceRelativePath);\n if (fs.existsSync(workspacePath)) {\n return workspacePath;\n }\n return fileURLToPath(import.meta.resolve(specifier));\n };\n\n const piCodingAgentEntry = packageIndex;\n const piAgentCoreEntry = resolveWorkspaceOrImport(\n \"agent/dist/index.js\",\n \"@earendil-works/pi-agent-core\",\n );\n const piTuiEntry = resolveWorkspaceOrImport(\n \"tui/dist/index.js\",\n \"@earendil-works/pi-tui\",\n );\n const piAiEntry = resolveWorkspaceOrImport(\n \"ai/dist/index.js\",\n \"@earendil-works/pi-ai\",\n );\n const piAiOauthEntry = resolveWorkspaceOrImport(\n \"ai/dist/oauth.js\",\n \"@earendil-works/pi-ai/oauth\",\n );\n\n _aliases = {\n \"@bastani/atomic\": piCodingAgentEntry,\n \"@earendil-works/pi-coding-agent\": piCodingAgentEntry,\n \"@earendil-works/pi-agent-core\": piAgentCoreEntry,\n \"@earendil-works/pi-tui\": piTuiEntry,\n \"@earendil-works/pi-ai\": piAiEntry,\n \"@earendil-works/pi-ai/oauth\": piAiOauthEntry,\n \"@mariozechner/pi-agent-core\": piAgentCoreEntry,\n \"@mariozechner/pi-tui\": piTuiEntry,\n \"@mariozechner/pi-ai\": piAiEntry,\n \"@mariozechner/pi-ai/oauth\": piAiOauthEntry,\n typebox: typeboxEntry,\n \"typebox/compile\": typeboxCompileEntry,\n \"typebox/value\": typeboxValueEntry,\n \"@sinclair/typebox\": typeboxEntry,\n \"@sinclair/typebox/compile\": typeboxCompileEntry,\n \"@sinclair/typebox/value\": typeboxValueEntry,\n };\n\n return _aliases;\n}\n\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport interface WorkflowResourceProvider {\n get(): ResolvedResource[];\n refresh?(): Promise<ResolvedResource[]>;\n}\n\nexport type WorkflowResourceProviderInput = WorkflowResourceProvider | ResolvedResource[];\n\nfunction createStaticWorkflowResourceProvider(workflowResources: ResolvedResource[]): WorkflowResourceProvider {\n return {\n get: () => workflowResources,\n };\n}\n\nfunction normalizeWorkflowResourceProvider(input: WorkflowResourceProviderInput): WorkflowResourceProvider {\n return Array.isArray(input) ? createStaticWorkflowResourceProvider(input) : input;\n}\n\nconst emptyWorkflowResourceProvider = createStaticWorkflowResourceProvider([]);\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n const notInitialized = () => {\n throw new Error(\n \"Extension runtime not initialized. Action methods cannot be called during extension loading.\",\n );\n };\n const state: { staleMessage?: string } = {};\n const assertActive = () => {\n if (state.staleMessage) {\n throw new Error(state.staleMessage);\n }\n };\n\n const runtime: ExtensionRuntime = {\n sendMessage: notInitialized,\n sendUserMessage: notInitialized,\n appendEntry: notInitialized,\n setSessionName: notInitialized,\n getSessionName: notInitialized,\n setLabel: notInitialized,\n getActiveTools: notInitialized,\n getAllTools: notInitialized,\n setActiveTools: notInitialized,\n // registerTool() is valid during extension load; refresh is only needed post-bind.\n refreshTools: () => {},\n getCommands: notInitialized,\n setModel: () =>\n Promise.reject(new Error(\"Extension runtime not initialized\")),\n getThinkingLevel: notInitialized,\n setThinkingLevel: notInitialized,\n flagValues: new Map(),\n pendingProviderRegistrations: [],\n assertActive,\n invalidate: (message) => {\n state.staleMessage ??=\n message ??\n \"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n },\n // Pre-bind: queue registrations so bindCore() can flush them once the\n // model registry is available. bindCore() replaces both with direct calls.\n registerProvider: (name, config, extensionPath = \"<unknown>\") => {\n runtime.pendingProviderRegistrations.push({\n name,\n config,\n extensionPath,\n });\n },\n unregisterProvider: (name) => {\n runtime.pendingProviderRegistrations =\n runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n },\n };\n\n return runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n extension: Extension,\n runtime: ExtensionRuntime,\n cwd: string,\n eventBus: EventBus,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): ExtensionAPI {\n const workflowResources = normalizeWorkflowResourceProvider(workflowResourceProvider);\n const api = {\n // Registration methods - write to extension\n on(event: string, handler: HandlerFn): void {\n runtime.assertActive();\n const list = extension.handlers.get(event) ?? [];\n list.push(handler);\n extension.handlers.set(event, list);\n },\n\n registerTool(tool: ToolDefinition): void {\n runtime.assertActive();\n extension.tools.set(tool.name, {\n definition: tool,\n sourceInfo: extension.sourceInfo,\n });\n runtime.refreshTools();\n },\n\n registerCommand(\n name: string,\n options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">,\n ): void {\n runtime.assertActive();\n extension.commands.set(name, {\n name,\n sourceInfo: extension.sourceInfo,\n ...options,\n });\n },\n\n registerShortcut(\n shortcut: KeyId,\n options: {\n description?: string;\n handler: (\n ctx: import(\"./types.ts\").ExtensionContext,\n ) => Promise<void> | void;\n },\n ): void {\n runtime.assertActive();\n extension.shortcuts.set(shortcut, {\n shortcut,\n extensionPath: extension.path,\n ...options,\n });\n },\n\n registerFlag(\n name: string,\n options: {\n description?: string;\n type: \"boolean\" | \"string\";\n default?: boolean | string;\n },\n ): void {\n runtime.assertActive();\n extension.flags.set(name, {\n name,\n extensionPath: extension.path,\n ...options,\n });\n if (options.default !== undefined && !runtime.flagValues.has(name)) {\n runtime.flagValues.set(name, options.default);\n }\n },\n\n registerMessageRenderer<T>(\n customType: string,\n renderer: MessageRenderer<T>,\n ): void {\n runtime.assertActive();\n extension.messageRenderers.set(customType, renderer as MessageRenderer);\n },\n\n // Flag access - checks extension registered it, reads from runtime\n getFlag(name: string): boolean | string | undefined {\n runtime.assertActive();\n if (!extension.flags.has(name)) return undefined;\n return runtime.flagValues.get(name);\n },\n\n getWorkflowResources(): ResolvedResource[] {\n runtime.assertActive();\n return [...workflowResources.get()];\n },\n\n async refreshWorkflowResources(): Promise<ResolvedResource[]> {\n runtime.assertActive();\n const refreshed = await workflowResources.refresh?.();\n return [...(refreshed ?? workflowResources.get())];\n },\n\n // Action methods - delegate to shared runtime\n sendMessage(message, options): void {\n runtime.assertActive();\n runtime.sendMessage(message, options);\n },\n\n sendUserMessage(content, options): void {\n runtime.assertActive();\n runtime.sendUserMessage(content, options);\n },\n\n appendEntry(customType: string, data?: unknown): void {\n runtime.assertActive();\n runtime.appendEntry(customType, data);\n },\n\n setSessionName(name: string): void {\n runtime.assertActive();\n runtime.setSessionName(name);\n },\n\n getSessionName(): string | undefined {\n runtime.assertActive();\n return runtime.getSessionName();\n },\n\n setLabel(entryId: string, label: string | undefined): void {\n runtime.assertActive();\n runtime.setLabel(entryId, label);\n },\n\n exec(command: string, args: string[], options?: ExecOptions) {\n runtime.assertActive();\n return execCommand(command, args, options?.cwd ?? cwd, options);\n },\n\n getActiveTools(): string[] {\n runtime.assertActive();\n return runtime.getActiveTools();\n },\n\n getAllTools() {\n runtime.assertActive();\n return runtime.getAllTools();\n },\n\n setActiveTools(toolNames: string[]): void {\n runtime.assertActive();\n runtime.setActiveTools(toolNames);\n },\n\n getCommands() {\n runtime.assertActive();\n return runtime.getCommands();\n },\n\n setModel(model) {\n runtime.assertActive();\n return runtime.setModel(model);\n },\n\n getThinkingLevel() {\n runtime.assertActive();\n return runtime.getThinkingLevel();\n },\n\n setThinkingLevel(level) {\n runtime.assertActive();\n runtime.setThinkingLevel(level);\n },\n\n registerProvider(name: string, config: ProviderConfig) {\n runtime.assertActive();\n runtime.registerProvider(name, config, extension.path);\n },\n\n unregisterProvider(name: string) {\n runtime.assertActive();\n runtime.unregisterProvider(name, extension.path);\n },\n\n events: eventBus,\n } as ExtensionAPI;\n\n return api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n const jiti = createJiti(import.meta.url, {\n moduleCache: false,\n // In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n // Also disable tryNative so jiti handles ALL imports (not just the entry point)\n // In Node.js/dev: use aliases to resolve to node_modules paths\n ...(isBunBinary\n ? { virtualModules: VIRTUAL_MODULES, tryNative: false }\n : { alias: getAliases() }),\n });\n\n const module = await jiti.import(extensionPath, { default: true });\n const factory = module as ExtensionFactory;\n return typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(\n extensionPath: string,\n resolvedPath: string,\n): Extension {\n const source =\n extensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n ? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n : \"local\";\n const baseDir = extensionPath.startsWith(\"<\")\n ? undefined\n : path.dirname(resolvedPath);\n\n return {\n path: extensionPath,\n resolvedPath,\n sourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\n handlers: new Map(),\n tools: new Map(),\n messageRenderers: new Map(),\n commands: new Map(),\n flags: new Map(),\n shortcuts: new Map(),\n };\n}\n\nasync function loadExtension(\n extensionPath: string,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<{ extension: Extension | null; error: string | null }> {\n const resolvedPath = resolvePath(extensionPath, cwd, { normalizeUnicodeSpaces: true });\n\n try {\n const factory = await loadExtensionModule(resolvedPath);\n if (!factory) {\n return {\n extension: null,\n error: `Extension does not export a valid factory function: ${extensionPath}`,\n };\n }\n\n const extension = createExtension(extensionPath, resolvedPath);\n const api = createExtensionAPI(\n extension,\n runtime,\n cwd,\n eventBus,\n workflowResourceProvider,\n );\n await factory(api);\n\n return { extension, error: null };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { extension: null, error: `Failed to load extension: ${message}` };\n }\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n factory: ExtensionFactory,\n cwd: string,\n eventBus: EventBus,\n runtime: ExtensionRuntime,\n extensionPath = \"<inline>\",\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<Extension> {\n const extension = createExtension(extensionPath, extensionPath);\n const resolvedCwd = resolvePath(cwd);\n const api = createExtensionAPI(\n extension,\n runtime,\n resolvedCwd,\n eventBus,\n workflowResourceProvider,\n );\n await factory(api);\n return extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(\n paths: string[],\n cwd: string,\n eventBus?: EventBus,\n workflowResourceProvider: WorkflowResourceProviderInput = emptyWorkflowResourceProvider,\n): Promise<LoadExtensionsResult> {\n const extensions: Extension[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n const resolvedCwd = resolvePath(cwd);\n const resolvedEventBus = eventBus ?? createEventBus();\n const runtime = createExtensionRuntime();\n\n for (const extPath of paths) {\n const { extension, error } = await loadExtension(\n extPath,\n resolvedCwd,\n resolvedEventBus,\n runtime,\n workflowResourceProvider,\n );\n\n if (error) {\n errors.push({ path: extPath, error });\n continue;\n }\n\n if (extension) {\n extensions.push(extension);\n }\n }\n\n return {\n extensions,\n errors,\n runtime,\n };\n}\n\ninterface PiManifest {\n extensions?: string[];\n themes?: string[];\n skills?: string[];\n prompts?: string[];\n}\n\nfunction manifestFromPackageJson(\n pkg: Record<string, unknown>,\n): PiManifest | null {\n const appManifest = pkg[APP_NAME];\n if (\n appManifest &&\n typeof appManifest === \"object\" &&\n !Array.isArray(appManifest)\n ) {\n return appManifest as PiManifest;\n }\n const legacyManifest = pkg.pi;\n if (\n legacyManifest &&\n typeof legacyManifest === \"object\" &&\n !Array.isArray(legacyManifest)\n ) {\n return legacyManifest as PiManifest;\n }\n return null;\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n try {\n const content = fs.readFileSync(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as Record<string, unknown>;\n return manifestFromPackageJson(pkg);\n } catch {\n return null;\n }\n}\n\nfunction isExtensionFile(name: string): boolean {\n return name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n // Check for package.json with \"pi\" field first\n const packageJsonPath = path.join(dir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const manifest = readPiManifest(packageJsonPath);\n if (manifest?.extensions?.length) {\n const entries: string[] = [];\n for (const extPath of manifest.extensions) {\n const resolvedExtPath = path.resolve(dir, extPath);\n if (fs.existsSync(resolvedExtPath)) {\n entries.push(resolvedExtPath);\n }\n }\n if (entries.length > 0) {\n return entries;\n }\n }\n }\n\n // Check for index.ts or index.js\n const indexTs = path.join(dir, \"index.ts\");\n const indexJs = path.join(dir, \"index.js\");\n if (fs.existsSync(indexTs)) {\n return [indexTs];\n }\n if (fs.existsSync(indexJs)) {\n return [indexJs];\n }\n\n return null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const discovered: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(dir, entry.name);\n\n // 1. Direct files: *.ts or *.js\n if (\n (entry.isFile() || entry.isSymbolicLink()) &&\n isExtensionFile(entry.name)\n ) {\n discovered.push(entryPath);\n continue;\n }\n\n // 2 & 3. Subdirectories\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n const entries = resolveExtensionEntries(entryPath);\n if (entries) {\n discovered.push(...entries);\n }\n }\n }\n } catch {\n return [];\n }\n\n return discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n configuredPaths: string[],\n cwd: string,\n agentDir: string = getAgentDir(),\n eventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n const resolvedCwd = resolvePath(cwd);\n const resolvedAgentDir = resolvePath(agentDir);\n const allPaths: string[] = [];\n const seen = new Set<string>();\n\n const addPaths = (paths: string[]) => {\n for (const p of paths) {\n const resolved = path.resolve(p);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n allPaths.push(p);\n }\n }\n };\n\n // 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/\n const localExtDir = path.join(resolvedCwd, CONFIG_DIR_NAME, \"extensions\");\n addPaths(discoverExtensionsInDir(localExtDir));\n\n // 2. Global extensions: agentDir/extensions/\n const globalExtDir = path.join(resolvedAgentDir, \"extensions\");\n addPaths(discoverExtensionsInDir(globalExtDir));\n\n // 3. Explicitly configured paths\n for (const p of configuredPaths) {\n const resolved = resolvePath(p, resolvedCwd, { normalizeUnicodeSpaces: true });\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n // Check for package.json with pi manifest or index.ts\n const entries = resolveExtensionEntries(resolved);\n if (entries) {\n addPaths(entries);\n continue;\n }\n // No explicit entries - discover individual files in directory\n addPaths(discoverExtensionsInDir(resolved));\n continue;\n }\n\n addPaths([resolved]);\n }\n\n return loadExtensions(allPaths, resolvedCwd, eventBus);\n\n}\n"]}
@@ -0,0 +1,58 @@
1
+ import type { ExtensionWidgetOptions } from "./types.ts";
2
+ export interface ReactiveWidgetComponent {
3
+ render(width: number): string[];
4
+ invalidate?(): void;
5
+ dispose?(): void;
6
+ }
7
+ export type ReactiveWidgetFactory<TTheme> = (tui: unknown, theme: TTheme) => ReactiveWidgetComponent;
8
+ export interface ReactiveWidgetUi<TTheme> {
9
+ setWidget(key: string, factory: ReactiveWidgetFactory<TTheme> | undefined, options?: ExtensionWidgetOptions): void;
10
+ requestRender?: () => void;
11
+ }
12
+ export interface ReactiveWidgetTimerHandle {
13
+ unref?: () => void;
14
+ }
15
+ export interface ReactiveWidgetTimerApi {
16
+ setTimeout(handler: () => void, delayMs: number): ReactiveWidgetTimerHandle;
17
+ clearTimeout(handle: ReactiveWidgetTimerHandle): void;
18
+ }
19
+ export interface ReactiveWidgetScheduler {
20
+ queueMicrotask(handler: () => void): void;
21
+ }
22
+ export type ReactiveWidgetAction = "mount" | "unmount" | "update" | "none";
23
+ export type ReactiveWidgetRefreshReason = "initial" | "state" | "clock" | "manual";
24
+ export interface ReactiveWidgetRenderState {
25
+ readonly mounted: boolean;
26
+ readonly lines: readonly string[];
27
+ }
28
+ export interface ReactiveWidgetRenderContext<TTheme> {
29
+ theme: TTheme;
30
+ width: number;
31
+ now: number;
32
+ }
33
+ export interface ReactiveWidgetController {
34
+ refresh(reason?: ReactiveWidgetRefreshReason): void;
35
+ dispose(): void;
36
+ isMounted(): boolean;
37
+ }
38
+ export interface InstallReactiveWidgetOptions<TSnapshot, TTheme> {
39
+ ui: ReactiveWidgetUi<TTheme>;
40
+ key: string;
41
+ placement?: ExtensionWidgetOptions["placement"];
42
+ getSnapshot(): TSnapshot;
43
+ subscribe?(listener: () => void): () => void;
44
+ getPreviewLines(snapshot: TSnapshot, now: number): readonly string[];
45
+ render(snapshot: TSnapshot, context: ReactiveWidgetRenderContext<TTheme>): readonly string[];
46
+ getNextRefreshDelayMs?(snapshot: TSnapshot, now: number): number | undefined;
47
+ now?: () => number;
48
+ timers?: ReactiveWidgetTimerApi;
49
+ scheduler?: ReactiveWidgetScheduler;
50
+ coalesceRenderRequests?: boolean;
51
+ requestRenderOnMount?: boolean;
52
+ requestRenderOnUnmount?: boolean;
53
+ requestRenderOnStateNoop?: boolean;
54
+ isStaleError?: (error: unknown) => boolean;
55
+ }
56
+ export declare function decideReactiveWidgetAction(prev: ReactiveWidgetRenderState, nextLines: readonly string[]): ReactiveWidgetAction;
57
+ export declare function installReactiveWidget<TSnapshot, TTheme = object>(options: InstallReactiveWidgetOptions<TSnapshot, TTheme>): ReactiveWidgetController;
58
+ //# sourceMappingURL=reactive-widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive-widget.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/reactive-widget.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionWidgetOptions } from \"./types.ts\";\n\nexport interface ReactiveWidgetComponent {\n\trender(width: number): string[];\n\tinvalidate?(): void;\n\tdispose?(): void;\n}\n\nexport type ReactiveWidgetFactory<TTheme> = (\n\ttui: unknown,\n\ttheme: TTheme,\n) => ReactiveWidgetComponent;\n\nexport interface ReactiveWidgetUi<TTheme> {\n\tsetWidget(key: string, factory: ReactiveWidgetFactory<TTheme> | undefined, options?: ExtensionWidgetOptions): void;\n\trequestRender?: () => void;\n}\n\nexport interface ReactiveWidgetTimerHandle {\n\tunref?: () => void;\n}\n\nexport interface ReactiveWidgetTimerApi {\n\tsetTimeout(handler: () => void, delayMs: number): ReactiveWidgetTimerHandle;\n\tclearTimeout(handle: ReactiveWidgetTimerHandle): void;\n}\n\nexport interface ReactiveWidgetScheduler {\n\tqueueMicrotask(handler: () => void): void;\n}\n\nexport type ReactiveWidgetAction = \"mount\" | \"unmount\" | \"update\" | \"none\";\nexport type ReactiveWidgetRefreshReason = \"initial\" | \"state\" | \"clock\" | \"manual\";\n\nexport interface ReactiveWidgetRenderState {\n\treadonly mounted: boolean;\n\treadonly lines: readonly string[];\n}\n\nexport interface ReactiveWidgetRenderContext<TTheme> {\n\ttheme: TTheme;\n\twidth: number;\n\tnow: number;\n}\n\nexport interface ReactiveWidgetController {\n\trefresh(reason?: ReactiveWidgetRefreshReason): void;\n\tdispose(): void;\n\tisMounted(): boolean;\n}\n\nexport interface InstallReactiveWidgetOptions<TSnapshot, TTheme> {\n\tui: ReactiveWidgetUi<TTheme>;\n\tkey: string;\n\tplacement?: ExtensionWidgetOptions[\"placement\"];\n\tgetSnapshot(): TSnapshot;\n\tsubscribe?(listener: () => void): () => void;\n\tgetPreviewLines(snapshot: TSnapshot, now: number): readonly string[];\n\trender(snapshot: TSnapshot, context: ReactiveWidgetRenderContext<TTheme>): readonly string[];\n\tgetNextRefreshDelayMs?(snapshot: TSnapshot, now: number): number | undefined;\n\tnow?: () => number;\n\ttimers?: ReactiveWidgetTimerApi;\n\tscheduler?: ReactiveWidgetScheduler;\n\tcoalesceRenderRequests?: boolean;\n\trequestRenderOnMount?: boolean;\n\trequestRenderOnUnmount?: boolean;\n\trequestRenderOnStateNoop?: boolean;\n\tisStaleError?: (error: unknown) => boolean;\n}\n\nconst defaultTimerApi: ReactiveWidgetTimerApi = {\n\tsetTimeout: (handler, delayMs) => setTimeout(handler, delayMs) as ReactiveWidgetTimerHandle,\n\tclearTimeout: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n};\n\nconst defaultScheduler: ReactiveWidgetScheduler = {\n\tqueueMicrotask: (handler) => queueMicrotask(handler),\n};\n\nfunction getRequestRenderFromHost(host: unknown): (() => void) | undefined {\n\tif (typeof host !== \"object\" || host === null) return undefined;\n\tconst candidate = (host as { requestRender?: unknown }).requestRender;\n\tif (typeof candidate !== \"function\") return undefined;\n\treturn () => candidate.call(host);\n}\n\nfunction linesEqual(a: readonly string[], b: readonly string[]): boolean {\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i] !== b[i]) return false;\n\t}\n\treturn true;\n}\n\nexport function decideReactiveWidgetAction(\n\tprev: ReactiveWidgetRenderState,\n\tnextLines: readonly string[],\n): ReactiveWidgetAction {\n\tconst nextVisible = nextLines.length > 0;\n\tif (!prev.mounted) return nextVisible ? \"mount\" : \"none\";\n\tif (!nextVisible) return \"unmount\";\n\treturn linesEqual(prev.lines, nextLines) ? \"none\" : \"update\";\n}\n\nexport function installReactiveWidget<TSnapshot, TTheme = object>(\n\toptions: InstallReactiveWidgetOptions<TSnapshot, TTheme>,\n): ReactiveWidgetController {\n\tconst timers = options.timers ?? defaultTimerApi;\n\tconst scheduler = options.scheduler ?? defaultScheduler;\n\tconst now = options.now ?? Date.now;\n\tconst coalesceRenderRequests = options.coalesceRenderRequests ?? true;\n\tconst requestRenderOnMount = options.requestRenderOnMount ?? true;\n\tconst requestRenderOnUnmount = options.requestRenderOnUnmount ?? true;\n\tconst requestRenderOnStateNoop = options.requestRenderOnStateNoop ?? true;\n\n\tlet disposed = false;\n\tlet mounted = false;\n\tlet renderQueued = false;\n\tlet mountedRequestRender: (() => void) | undefined;\n\tlet refreshTimer: ReactiveWidgetTimerHandle | undefined;\n\tlet currentSnap = options.getSnapshot();\n\tlet currentNow = now();\n\tlet lastLines: readonly string[] = [];\n\n\tconst clearRefreshTimer = (): void => {\n\t\tif (refreshTimer === undefined) return;\n\t\ttimers.clearTimeout(refreshTimer);\n\t\trefreshTimer = undefined;\n\t};\n\n\tconst handleError = (error: unknown): void => {\n\t\tif (options.isStaleError?.(error)) return;\n\t\tthrow error;\n\t};\n\n\tconst invokeRequestRender = (): void => {\n\t\tif (options.ui.requestRender) {\n\t\t\toptions.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\t\tmountedRequestRender?.();\n\t};\n\n\tconst requestRender = (): void => {\n\t\tif (!coalesceRenderRequests) {\n\t\t\ttry {\n\t\t\t\tinvokeRequestRender();\n\t\t\t} catch (error) {\n\t\t\t\thandleError(error);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (renderQueued) return;\n\t\trenderQueued = true;\n\t\tscheduler.queueMicrotask(() => {\n\t\t\trenderQueued = false;\n\t\t\tif (disposed) return;\n\t\t\ttry {\n\t\t\t\tinvokeRequestRender();\n\t\t\t} catch (error) {\n\t\t\t\thandleError(error);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst requestRenderForDispose = (): void => {\n\t\trenderQueued = false;\n\t\tinvokeRequestRender();\n\t};\n\n\tconst scheduleRefresh = (): void => {\n\t\tconst delayMs = options.getNextRefreshDelayMs?.(currentSnap, currentNow);\n\t\tif (delayMs === undefined) return;\n\t\trefreshTimer = timers.setTimeout(() => {\n\t\t\trefreshTimer = undefined;\n\t\t\tcontroller.refresh(\"clock\");\n\t\t}, delayMs);\n\t\trefreshTimer.unref?.();\n\t};\n\n\tconst widgetFactory: ReactiveWidgetFactory<TTheme> = (tui, theme) => {\n\t\tconst fallbackRequestRender = getRequestRenderFromHost(tui);\n\t\tif (fallbackRequestRender) mountedRequestRender = fallbackRequestRender;\n\t\treturn {\n\t\t\trender(width: number): string[] {\n\t\t\t\treturn [...options.render(currentSnap, { theme, width, now: currentNow })];\n\t\t\t},\n\t\t\tinvalidate(): void {\n\t\t\t\t// The component is intentionally stateless; callers should rebuild from the\n\t\t\t\t// latest snapshot/time on every render. This hook exists so pi-tui can still\n\t\t\t\t// invalidate the long-lived component on theme changes.\n\t\t\t},\n\t\t};\n\t};\n\n\tconst controller: ReactiveWidgetController = {\n\t\trefresh(reason: ReactiveWidgetRefreshReason = \"manual\"): void {\n\t\t\tif (disposed) return;\n\t\t\tclearRefreshTimer();\n\t\t\ttry {\n\t\t\t\tcurrentSnap = options.getSnapshot();\n\t\t\t\tcurrentNow = now();\n\t\t\t\tconst nextLines = options.getPreviewLines(currentSnap, currentNow);\n\t\t\t\tconst action = decideReactiveWidgetAction({ mounted, lines: lastLines }, nextLines);\n\n\t\t\t\tswitch (action) {\n\t\t\t\t\tcase \"mount\":\n\t\t\t\t\t\toptions.ui.setWidget(options.key, widgetFactory, options.placement ? { placement: options.placement } : undefined);\n\t\t\t\t\t\tmounted = true;\n\t\t\t\t\t\tif (requestRenderOnMount) requestRender();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"unmount\":\n\t\t\t\t\t\toptions.ui.setWidget(options.key, undefined);\n\t\t\t\t\t\tmounted = false;\n\t\t\t\t\t\tif (requestRenderOnUnmount) requestRender();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"update\":\n\t\t\t\t\t\trequestRender();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"none\":\n\t\t\t\t\t\tif (mounted && reason === \"state\" && requestRenderOnStateNoop) requestRender();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tlastLines = nextLines;\n\t\t\t\tscheduleRefresh();\n\t\t\t} catch (error) {\n\t\t\t\thandleError(error);\n\t\t\t}\n\t\t},\n\t\tdispose(): void {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tclearRefreshTimer();\n\t\t\tunsubscribe?.();\n\t\t\ttry {\n\t\t\t\toptions.ui.setWidget(options.key, undefined);\n\t\t\t\tmounted = false;\n\t\t\t\trequestRenderForDispose();\n\t\t\t} catch (error) {\n\t\t\t\thandleError(error);\n\t\t\t}\n\t\t},\n\t\tisMounted(): boolean {\n\t\t\treturn mounted;\n\t\t},\n\t};\n\n\tconst unsubscribe = options.subscribe?.(() => controller.refresh(\"state\"));\n\tcontroller.refresh(\"initial\");\n\n\treturn controller;\n}\n"]}