@selesai/code 0.5.14 → 0.5.15

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/dist/bun/cli.d.ts.map +1 -1
  2. package/dist/bun/cli.js +2 -0
  3. package/dist/bun/cli.js.map +1 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +3 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/list-models.d.ts +2 -2
  8. package/dist/cli/list-models.d.ts.map +1 -1
  9. package/dist/cli/list-models.js +3 -3
  10. package/dist/cli/list-models.js.map +1 -1
  11. package/dist/config.d.ts +1 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +2 -2
  14. package/dist/config.js.map +1 -1
  15. package/dist/core/agent-session-auto-handoff.test.d.ts.map +1 -1
  16. package/dist/core/agent-session-auto-handoff.test.js +2 -2
  17. package/dist/core/agent-session-auto-handoff.test.js.map +1 -1
  18. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  19. package/dist/core/agent-session-runtime.js +3 -0
  20. package/dist/core/agent-session-runtime.js.map +1 -1
  21. package/dist/core/agent-session-services.d.ts +3 -6
  22. package/dist/core/agent-session-services.d.ts.map +1 -1
  23. package/dist/core/agent-session-services.js +23 -9
  24. package/dist/core/agent-session-services.js.map +1 -1
  25. package/dist/core/agent-session.d.ts +28 -10
  26. package/dist/core/agent-session.d.ts.map +1 -1
  27. package/dist/core/agent-session.js +136 -90
  28. package/dist/core/agent-session.js.map +1 -1
  29. package/dist/core/auth-storage.d.ts +20 -98
  30. package/dist/core/auth-storage.d.ts.map +1 -1
  31. package/dist/core/auth-storage.js +59 -251
  32. package/dist/core/auth-storage.js.map +1 -1
  33. package/dist/core/built-in-extensions.d.ts +3 -0
  34. package/dist/core/built-in-extensions.d.ts.map +1 -0
  35. package/dist/core/built-in-extensions.js +3 -0
  36. package/dist/core/built-in-extensions.js.map +1 -0
  37. package/dist/core/cache-stats.d.ts +2 -2
  38. package/dist/core/cache-stats.d.ts.map +1 -1
  39. package/dist/core/cache-stats.js +1 -1
  40. package/dist/core/cache-stats.js.map +1 -1
  41. package/dist/core/compaction/branch-summarization.d.ts +8 -2
  42. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  43. package/dist/core/compaction/branch-summarization.js +8 -11
  44. package/dist/core/compaction/branch-summarization.js.map +1 -1
  45. package/dist/core/compaction/compaction.d.ts +19 -3
  46. package/dist/core/compaction/compaction.d.ts.map +1 -1
  47. package/dist/core/compaction/compaction.js +63 -26
  48. package/dist/core/compaction/compaction.js.map +1 -1
  49. package/dist/core/compaction/utils.d.ts +1 -1
  50. package/dist/core/compaction/utils.d.ts.map +1 -1
  51. package/dist/core/compaction/utils.js +6 -17
  52. package/dist/core/compaction/utils.js.map +1 -1
  53. package/dist/core/extensions/loader.d.ts.map +1 -1
  54. package/dist/core/extensions/loader.js +21 -4
  55. package/dist/core/extensions/loader.js.map +1 -1
  56. package/dist/core/extensions/runner.d.ts +4 -1
  57. package/dist/core/extensions/runner.d.ts.map +1 -1
  58. package/dist/core/extensions/runner.js +39 -0
  59. package/dist/core/extensions/runner.js.map +1 -1
  60. package/dist/core/extensions/types.d.ts +24 -3
  61. package/dist/core/extensions/types.d.ts.map +1 -1
  62. package/dist/core/extensions/types.js.map +1 -1
  63. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  64. package/dist/core/extensions/wrapper.js +22 -3
  65. package/dist/core/extensions/wrapper.js.map +1 -1
  66. package/dist/core/keybindings.d.ts +8 -3
  67. package/dist/core/keybindings.d.ts.map +1 -1
  68. package/dist/core/keybindings.js +7 -3
  69. package/dist/core/keybindings.js.map +1 -1
  70. package/dist/core/llama/client.d.ts +61 -0
  71. package/dist/core/llama/client.d.ts.map +1 -0
  72. package/dist/core/llama/client.js +302 -0
  73. package/dist/core/llama/client.js.map +1 -0
  74. package/dist/core/llama/huggingface.d.ts +23 -0
  75. package/dist/core/llama/huggingface.d.ts.map +1 -0
  76. package/dist/core/llama/huggingface.js +141 -0
  77. package/dist/core/llama/huggingface.js.map +1 -0
  78. package/dist/core/llama/index.d.ts +3 -0
  79. package/dist/core/llama/index.d.ts.map +1 -0
  80. package/dist/core/llama/index.js +208 -0
  81. package/dist/core/llama/index.js.map +1 -0
  82. package/dist/core/llama/provider.d.ts +10 -0
  83. package/dist/core/llama/provider.d.ts.map +1 -0
  84. package/dist/core/llama/provider.js +102 -0
  85. package/dist/core/llama/provider.js.map +1 -0
  86. package/dist/core/llama/ui.d.ts +42 -0
  87. package/dist/core/llama/ui.d.ts.map +1 -0
  88. package/dist/core/llama/ui.js +416 -0
  89. package/dist/core/llama/ui.js.map +1 -0
  90. package/dist/core/model-config.d.ts +513 -0
  91. package/dist/core/model-config.d.ts.map +1 -0
  92. package/dist/core/model-config.js +272 -0
  93. package/dist/core/model-config.js.map +1 -0
  94. package/dist/core/model-registry.d.ts +20 -126
  95. package/dist/core/model-registry.d.ts.map +1 -1
  96. package/dist/core/model-registry.js +62 -780
  97. package/dist/core/model-registry.js.map +1 -1
  98. package/dist/core/model-resolver.d.ts +6 -6
  99. package/dist/core/model-resolver.d.ts.map +1 -1
  100. package/dist/core/model-resolver.js +21 -18
  101. package/dist/core/model-resolver.js.map +1 -1
  102. package/dist/core/model-runtime.d.ts +83 -0
  103. package/dist/core/model-runtime.d.ts.map +1 -0
  104. package/dist/core/model-runtime.js +451 -0
  105. package/dist/core/model-runtime.js.map +1 -0
  106. package/dist/core/models-store.d.ts +17 -0
  107. package/dist/core/models-store.d.ts.map +1 -0
  108. package/dist/core/models-store.js +45 -0
  109. package/dist/core/models-store.js.map +1 -0
  110. package/dist/core/package-manager.d.ts.map +1 -1
  111. package/dist/core/package-manager.js +7 -2
  112. package/dist/core/package-manager.js.map +1 -1
  113. package/dist/core/prompt-templates.d.ts +1 -0
  114. package/dist/core/prompt-templates.d.ts.map +1 -1
  115. package/dist/core/prompt-templates.js +4 -4
  116. package/dist/core/prompt-templates.js.map +1 -1
  117. package/dist/core/provider-composer.d.ts +55 -0
  118. package/dist/core/provider-composer.d.ts.map +1 -0
  119. package/dist/core/provider-composer.js +375 -0
  120. package/dist/core/provider-composer.js.map +1 -0
  121. package/dist/core/radius.d.ts +2 -0
  122. package/dist/core/radius.d.ts.map +1 -0
  123. package/dist/core/radius.js +2 -0
  124. package/dist/core/radius.js.map +1 -0
  125. package/dist/core/remote-catalog-provider.d.ts +5 -0
  126. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  127. package/dist/core/remote-catalog-provider.js +102 -0
  128. package/dist/core/remote-catalog-provider.js.map +1 -0
  129. package/dist/core/resource-loader.d.ts.map +1 -1
  130. package/dist/core/resource-loader.js +1 -0
  131. package/dist/core/resource-loader.js.map +1 -1
  132. package/dist/core/runtime-credentials.d.ts +17 -0
  133. package/dist/core/runtime-credentials.d.ts.map +1 -0
  134. package/dist/core/runtime-credentials.js +42 -0
  135. package/dist/core/runtime-credentials.js.map +1 -0
  136. package/dist/core/sdk.d.ts +4 -7
  137. package/dist/core/sdk.d.ts.map +1 -1
  138. package/dist/core/sdk.js +18 -25
  139. package/dist/core/sdk.js.map +1 -1
  140. package/dist/core/session-manager.d.ts +12 -7
  141. package/dist/core/session-manager.d.ts.map +1 -1
  142. package/dist/core/session-manager.js +103 -27
  143. package/dist/core/session-manager.js.map +1 -1
  144. package/dist/core/system-prompt.d.ts.map +1 -1
  145. package/dist/core/system-prompt.js +1 -11
  146. package/dist/core/system-prompt.js.map +1 -1
  147. package/dist/core/tools/read.d.ts.map +1 -1
  148. package/dist/core/tools/read.js +1 -1
  149. package/dist/core/tools/read.js.map +1 -1
  150. package/dist/core/usage-totals.d.ts +19 -0
  151. package/dist/core/usage-totals.d.ts.map +1 -0
  152. package/dist/core/usage-totals.js +52 -0
  153. package/dist/core/usage-totals.js.map +1 -0
  154. package/dist/extensions/index.d.ts +3 -0
  155. package/dist/extensions/index.d.ts.map +1 -0
  156. package/dist/extensions/index.js +9 -0
  157. package/dist/extensions/index.js.map +1 -0
  158. package/dist/extensions/llama/client.d.ts +61 -0
  159. package/dist/extensions/llama/client.d.ts.map +1 -0
  160. package/dist/extensions/llama/client.js +309 -0
  161. package/dist/extensions/llama/client.js.map +1 -0
  162. package/dist/extensions/llama/huggingface.d.ts +23 -0
  163. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  164. package/dist/extensions/llama/huggingface.js +146 -0
  165. package/dist/extensions/llama/huggingface.js.map +1 -0
  166. package/dist/extensions/llama/index.d.ts +3 -0
  167. package/dist/extensions/llama/index.d.ts.map +1 -0
  168. package/dist/extensions/llama/index.js +211 -0
  169. package/dist/extensions/llama/index.js.map +1 -0
  170. package/dist/extensions/llama/provider.d.ts +10 -0
  171. package/dist/extensions/llama/provider.d.ts.map +1 -0
  172. package/dist/extensions/llama/provider.js +106 -0
  173. package/dist/extensions/llama/provider.js.map +1 -0
  174. package/dist/extensions/llama/ui.d.ts +42 -0
  175. package/dist/extensions/llama/ui.d.ts.map +1 -0
  176. package/dist/extensions/llama/ui.js +420 -0
  177. package/dist/extensions/llama/ui.js.map +1 -0
  178. package/dist/extensions/tokenin-onboarding.ts +3 -3
  179. package/dist/index.d.ts +4 -3
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +3 -3
  182. package/dist/index.js.map +1 -1
  183. package/dist/main.d.ts.map +1 -1
  184. package/dist/main.js +21 -19
  185. package/dist/main.js.map +1 -1
  186. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  187. package/dist/modes/interactive/components/assistant-message.js +22 -10
  188. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  189. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  190. package/dist/modes/interactive/components/custom-editor.js +1 -1
  191. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  192. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/footer.js +24 -23
  194. package/dist/modes/interactive/components/footer.js.map +1 -1
  195. package/dist/modes/interactive/components/login-dialog.d.ts +5 -5
  196. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/login-dialog.js +17 -8
  198. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  199. package/dist/modes/interactive/components/model-selector.d.ts +11 -4
  200. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  201. package/dist/modes/interactive/components/model-selector.js +72 -41
  202. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  203. package/dist/modes/interactive/components/oauth-selector.d.ts +4 -4
  204. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/oauth-selector.js +14 -27
  206. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  207. package/dist/modes/interactive/components/tree-selector.d.ts +5 -0
  208. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  209. package/dist/modes/interactive/components/tree-selector.js +49 -12
  210. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  211. package/dist/modes/interactive/interactive-mode.d.ts +8 -5
  212. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  213. package/dist/modes/interactive/interactive-mode.js +253 -225
  214. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  215. package/dist/modes/rpc/rpc-client.d.ts +4 -0
  216. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  217. package/dist/modes/rpc/rpc-client.js +7 -0
  218. package/dist/modes/rpc/rpc-client.js.map +1 -1
  219. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  220. package/dist/modes/rpc/rpc-mode.js +6 -2
  221. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  222. package/dist/modes/rpc/rpc-types.d.ts +11 -0
  223. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  224. package/dist/modes/rpc/rpc-types.js.map +1 -1
  225. package/dist/package-manager-cli.d.ts.map +1 -1
  226. package/dist/package-manager-cli.js +67 -5
  227. package/dist/package-manager-cli.js.map +1 -1
  228. package/dist/utils/clipboard-native.d.ts +1 -0
  229. package/dist/utils/clipboard-native.d.ts.map +1 -1
  230. package/dist/utils/clipboard-native.js.map +1 -1
  231. package/dist/utils/clipboard.d.ts +2 -0
  232. package/dist/utils/clipboard.d.ts.map +1 -1
  233. package/dist/utils/clipboard.js +13 -0
  234. package/dist/utils/clipboard.js.map +1 -1
  235. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\nawait import(\"./register-bedrock.ts\");\nawait import(\"../cli.ts\");\n"]}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { registerBunOAuthFlows } from \"@earendil-works/pi-ai/bun-oauth\";\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nregisterBunOAuthFlows();\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\nawait import(\"./register-bedrock.ts\");\nawait import(\"../cli.ts\");\n"]}
package/dist/bun/cli.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { registerBunOAuthFlows } from "@earendil-works/pi-ai/bun-oauth";
2
3
  import { APP_NAME } from "../config.js";
3
4
  process.title = APP_NAME;
4
5
  process.emitWarning = (() => { });
6
+ registerBunOAuthFlows();
5
7
  import { restoreSandboxEnv } from "./restore-sandbox-env.js";
6
8
  restoreSandboxEnv();
7
9
  await import("./register-bedrock.js");
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;AACzB,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAA+B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,iBAAiB,EAAE,CAAC;AAEpB,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;AACtC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\nawait import(\"./register-bedrock.ts\");\nawait import(\"../cli.ts\");\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bun/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;AACzB,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAA+B,CAAC;AAE/D,qBAAqB,EAAE,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,iBAAiB,EAAE,CAAC;AAEpB,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;AACtC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { registerBunOAuthFlows } from \"@earendil-works/pi-ai/bun-oauth\";\nimport { APP_NAME } from \"../config.ts\";\n\nprocess.title = APP_NAME;\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nregisterBunOAuthFlows();\n\nimport { restoreSandboxEnv } from \"./restore-sandbox-env.ts\";\n\nrestoreSandboxEnv();\n\nawait import(\"./register-bedrock.ts\");\nawait import(\"../cli.ts\");\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmJ9C;AAED,wBAAgB,SAAS,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAkLhE","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, ENV_SESSION_DIR } from \"../config.ts\";\nimport type { ExtensionFlag } from \"../core/extensions/types.ts\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string[];\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tname?: string;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionId?: string;\n\tfork?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: string[];\n\texcludeTools?: string[];\n\tnoTools?: boolean;\n\tnoBuiltinTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tnoContextFiles?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\tprojectTrustOverride?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n\tdiagnostics: Array<{ type: \"warning\" | \"error\"; message: string }>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t\tdiagnostics: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = result.appendSystemPrompt ?? [];\n\t\t\tresult.appendSystemPrompt.push(args[++i]);\n\t\t} else if (arg === \"--name\" || arg === \"-n\") {\n\t\t\tif (i + 1 < args.length) {\n\t\t\t\tresult.name = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({ type: \"error\", message: \"--name requires a value\" });\n\t\t\t}\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-id\" && i + 1 < args.length) {\n\t\t\tresult.sessionId = args[++i];\n\t\t} else if (arg === \"--fork\" && i + 1 < args.length) {\n\t\t\tresult.fork = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\" || arg === \"-nt\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--no-builtin-tools\" || arg === \"-nbt\") {\n\t\t\tresult.noBuiltinTools = true;\n\t\t} else if ((arg === \"--tools\" || arg === \"-t\") && i + 1 < args.length) {\n\t\t\tresult.tools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if ((arg === \"--exclude-tools\" || arg === \"-xt\") && i + 1 < args.length) {\n\t\t\tresult.excludeTools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tmessage: `Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t\tconst next = args[i + 1];\n\t\t\tif (next !== undefined && !next.startsWith(\"@\") && (!next.startsWith(\"-\") || next.startsWith(\"---\"))) {\n\t\t\t\tresult.messages.push(next);\n\t\t\t\ti++;\n\t\t\t}\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--no-context-files\" || arg === \"-nc\") {\n\t\t\tresult.noContextFiles = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--approve\" || arg === \"-a\") {\n\t\t\tresult.projectTrustOverride = true;\n\t\t} else if (arg === \"--no-approve\" || arg === \"-na\") {\n\t\t\tresult.projectTrustOverride = false;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\")) {\n\t\t\tconst eqIndex = arg.indexOf(\"=\");\n\t\t\tif (eqIndex !== -1) {\n\t\t\t\tresult.unknownFlags.set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1));\n\t\t\t} else {\n\t\t\t\tconst flagName = arg.slice(2);\n\t\t\t\tconst next = args[i + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\") && !next.startsWith(\"@\")) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, next);\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (arg.startsWith(\"-\") && !arg.startsWith(\"--\")) {\n\t\t\tresult.diagnostics.push({ type: \"error\", message: `Unknown option: ${arg}` });\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(extensionFlags?: ExtensionFlag[]): void {\n\tconst extensionFlagsText =\n\t\textensionFlags && extensionFlags.length > 0\n\t\t\t? `\\n${chalk.bold(\"Extension CLI Flags:\")}\\n${extensionFlags\n\t\t\t\t\t.map((flag) => {\n\t\t\t\t\t\tconst value = flag.type === \"string\" ? \" <value>\" : \"\";\n\t\t\t\t\t\tconst description = flag.description ?? `Registered by ${flag.extensionPath}`;\n\t\t\t\t\t\treturn ` --${flag.name}${value}`.padEnd(30) + description;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")}\\n`\n\t\t\t: \"\";\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} uninstall <source> [-l] Alias for remove\n ${APP_NAME} update [source|self|pi] Update pi (use --all for pi and extensions)\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config [-l] Open TUI to enable/disable package resources (Tab switches scope)\n ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list/config\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path|id> Use specific session file or partial UUID\n --session-id <id> Use exact project session ID, creating it if missing\n --fork <path|id> Fork specific session file or partial UUID into a new session\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --name, -n <name> Set session display name\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools, -nt Disable all tools by default (built-in and extension)\n --no-builtin-tools, -nbt Disable built-in tools by default but keep extension/custom tools enabled\n --tools, -t <tools> Comma-separated allowlist of tool names to enable\n Applies to built-in, extension, and custom tools\n --exclude-tools, -xt <tools> Comma-separated denylist of tool names to disable\n Applies to built-in, extension, and custom tools\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh, max\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --no-context-files, -nc Disable AGENTS.md and CLAUDE.md discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --approve, -a Trust project-local files for this run\n --no-approve, -na Ignore project-local files for this run\n --offline Disable startup network operations (same as PI_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).${extensionFlagsText}\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Start a named session\n ${APP_NAME} --name \"Refactor auth module\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Disable one tool while keeping the rest available\n ${APP_NAME} --exclude-tools ask_question\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n ANT_LING_API_KEY - Ant Ling API key\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI/Cognitive Services base URL (e.g. https://{resource}.openai.azure.com)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n DEEPSEEK_API_KEY - DeepSeek API key\n NVIDIA_API_KEY - NVIDIA NIM API key\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n FIREWORKS_API_KEY - Fireworks API key\n TOGETHER_API_KEY - Together AI API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI Coding Plan API key (Global)\n ZAI_CODING_CN_API_KEY - ZAI Coding Plan API key (China)\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n MOONSHOT_API_KEY - Moonshot AI API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)\n CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)\n CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)\n XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)\n XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)\n XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)\n XIAOMI_TOKEN_PLAN_SGP_API_KEY - Xiaomi MiMo Token Plan API key (Singapore region)\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Config directory (default: ~/${CONFIG_DIR_NAME}/agent)\n ${ENV_SESSION_DIR.padEnd(32)} - Session storage directory (overridden by --session-dir)\n PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n PI_OFFLINE - Disable startup network operations when set to 1/true/yes\n PI_TELEMETRY - Override install telemetry when set to 1/true/yes or 0/false/no\n PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)\n\n${chalk.bold(\"Built-in Tool Names:\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmJ9C;AAED,wBAAgB,SAAS,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAoLhE","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, ENV_SESSION_DIR } from \"../config.ts\";\nimport type { ExtensionFlag } from \"../core/extensions/types.ts\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string[];\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tname?: string;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionId?: string;\n\tfork?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: string[];\n\texcludeTools?: string[];\n\tnoTools?: boolean;\n\tnoBuiltinTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tnoContextFiles?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\tprojectTrustOverride?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n\tdiagnostics: Array<{ type: \"warning\" | \"error\"; message: string }>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t\tdiagnostics: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = result.appendSystemPrompt ?? [];\n\t\t\tresult.appendSystemPrompt.push(args[++i]);\n\t\t} else if (arg === \"--name\" || arg === \"-n\") {\n\t\t\tif (i + 1 < args.length) {\n\t\t\t\tresult.name = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({ type: \"error\", message: \"--name requires a value\" });\n\t\t\t}\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-id\" && i + 1 < args.length) {\n\t\t\tresult.sessionId = args[++i];\n\t\t} else if (arg === \"--fork\" && i + 1 < args.length) {\n\t\t\tresult.fork = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\" || arg === \"-nt\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--no-builtin-tools\" || arg === \"-nbt\") {\n\t\t\tresult.noBuiltinTools = true;\n\t\t} else if ((arg === \"--tools\" || arg === \"-t\") && i + 1 < args.length) {\n\t\t\tresult.tools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if ((arg === \"--exclude-tools\" || arg === \"-xt\") && i + 1 < args.length) {\n\t\t\tresult.excludeTools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tmessage: `Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t\tconst next = args[i + 1];\n\t\t\tif (next !== undefined && !next.startsWith(\"@\") && (!next.startsWith(\"-\") || next.startsWith(\"---\"))) {\n\t\t\t\tresult.messages.push(next);\n\t\t\t\ti++;\n\t\t\t}\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--no-context-files\" || arg === \"-nc\") {\n\t\t\tresult.noContextFiles = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--approve\" || arg === \"-a\") {\n\t\t\tresult.projectTrustOverride = true;\n\t\t} else if (arg === \"--no-approve\" || arg === \"-na\") {\n\t\t\tresult.projectTrustOverride = false;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\")) {\n\t\t\tconst eqIndex = arg.indexOf(\"=\");\n\t\t\tif (eqIndex !== -1) {\n\t\t\t\tresult.unknownFlags.set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1));\n\t\t\t} else {\n\t\t\t\tconst flagName = arg.slice(2);\n\t\t\t\tconst next = args[i + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\") && !next.startsWith(\"@\")) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, next);\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (arg.startsWith(\"-\") && !arg.startsWith(\"--\")) {\n\t\t\tresult.diagnostics.push({ type: \"error\", message: `Unknown option: ${arg}` });\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(extensionFlags?: ExtensionFlag[]): void {\n\tconst extensionFlagsText =\n\t\textensionFlags && extensionFlags.length > 0\n\t\t\t? `\\n${chalk.bold(\"Extension CLI Flags:\")}\\n${extensionFlags\n\t\t\t\t\t.map((flag) => {\n\t\t\t\t\t\tconst value = flag.type === \"string\" ? \" <value>\" : \"\";\n\t\t\t\t\t\tconst description = flag.description ?? `Registered by ${flag.extensionPath}`;\n\t\t\t\t\t\treturn ` --${flag.name}${value}`.padEnd(30) + description;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")}\\n`\n\t\t\t: \"\";\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} uninstall <source> [-l] Alias for remove\n ${APP_NAME} update [source|self|pi] Update pi, extensions, or model catalogs\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config [-l] Open TUI to enable/disable package resources (Tab switches scope)\n ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list/config\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path|id> Use specific session file or partial UUID\n --session-id <id> Use exact project session ID, creating it if missing\n --fork <path|id> Fork specific session file or partial UUID into a new session\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --name, -n <name> Set session display name\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools, -nt Disable all tools by default (built-in and extension)\n --no-builtin-tools, -nbt Disable built-in tools by default but keep extension/custom tools enabled\n --tools, -t <tools> Comma-separated allowlist of tool names to enable\n Applies to built-in, extension, and custom tools\n --exclude-tools, -xt <tools> Comma-separated denylist of tool names to disable\n Applies to built-in, extension, and custom tools\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh, max\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --no-context-files, -nc Disable AGENTS.md and CLAUDE.md discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --approve, -a Trust project-local files for this run\n --no-approve, -na Ignore project-local files for this run\n --offline Disable startup network operations (same as PI_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).${extensionFlagsText}\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Start a named session\n ${APP_NAME} --name \"Refactor auth module\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Disable one tool while keeping the rest available\n ${APP_NAME} --exclude-tools ask_question\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n ANT_LING_API_KEY - Ant Ling API key\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI/Cognitive Services base URL (e.g. https://{resource}.openai.azure.com)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n DEEPSEEK_API_KEY - DeepSeek API key\n NVIDIA_API_KEY - NVIDIA NIM API key\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n FIREWORKS_API_KEY - Fireworks API key\n TOGETHER_API_KEY - Together AI API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI Coding Plan API key (Global)\n ZAI_CODING_CN_API_KEY - ZAI Coding Plan API key (China)\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n MOONSHOT_API_KEY - Moonshot AI API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)\n CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)\n CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)\n QWEN_TOKEN_PLAN_API_KEY - Qwen Token Plan API key (international region)\n QWEN_TOKEN_PLAN_CN_API_KEY - Qwen Token Plan API key (China region)\n XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)\n XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)\n XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)\n XIAOMI_TOKEN_PLAN_SGP_API_KEY - Xiaomi MiMo Token Plan API key (Singapore region)\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Config directory (default: ~/${CONFIG_DIR_NAME}/agent)\n ${ENV_SESSION_DIR.padEnd(32)} - Session storage directory (overridden by --session-dir)\n PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n PI_OFFLINE - Disable startup network operations when set to 1/true/yes\n PI_TELEMETRY - Override install telemetry when set to 1/true/yes or 0/false/no\n PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)\n\n${chalk.bold(\"Built-in Tool Names:\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
package/dist/cli/args.js CHANGED
@@ -217,7 +217,7 @@ ${chalk.bold("Commands:")}
217
217
  ${APP_NAME} install <source> [-l] Install extension source and add to settings
218
218
  ${APP_NAME} remove <source> [-l] Remove extension source from settings
219
219
  ${APP_NAME} uninstall <source> [-l] Alias for remove
220
- ${APP_NAME} update [source|self|pi] Update pi (use --all for pi and extensions)
220
+ ${APP_NAME} update [source|self|pi] Update pi, extensions, or model catalogs
221
221
  ${APP_NAME} list List installed extensions from settings
222
222
  ${APP_NAME} config [-l] Open TUI to enable/disable package resources (Tab switches scope)
223
223
  ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list/config
@@ -350,6 +350,8 @@ ${chalk.bold("Environment Variables:")}
350
350
  CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)
351
351
  CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)
352
352
  CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)
353
+ QWEN_TOKEN_PLAN_API_KEY - Qwen Token Plan API key (international region)
354
+ QWEN_TOKEN_PLAN_CN_API_KEY - Qwen Token Plan API key (China region)
353
355
  XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)
354
356
  XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)
355
357
  XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, ENV_SESSION_DIR } from \"../config.ts\";\nimport type { ExtensionFlag } from \"../core/extensions/types.ts\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string[];\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tname?: string;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionId?: string;\n\tfork?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: string[];\n\texcludeTools?: string[];\n\tnoTools?: boolean;\n\tnoBuiltinTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tnoContextFiles?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\tprojectTrustOverride?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n\tdiagnostics: Array<{ type: \"warning\" | \"error\"; message: string }>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t\tdiagnostics: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = result.appendSystemPrompt ?? [];\n\t\t\tresult.appendSystemPrompt.push(args[++i]);\n\t\t} else if (arg === \"--name\" || arg === \"-n\") {\n\t\t\tif (i + 1 < args.length) {\n\t\t\t\tresult.name = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({ type: \"error\", message: \"--name requires a value\" });\n\t\t\t}\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-id\" && i + 1 < args.length) {\n\t\t\tresult.sessionId = args[++i];\n\t\t} else if (arg === \"--fork\" && i + 1 < args.length) {\n\t\t\tresult.fork = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\" || arg === \"-nt\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--no-builtin-tools\" || arg === \"-nbt\") {\n\t\t\tresult.noBuiltinTools = true;\n\t\t} else if ((arg === \"--tools\" || arg === \"-t\") && i + 1 < args.length) {\n\t\t\tresult.tools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if ((arg === \"--exclude-tools\" || arg === \"-xt\") && i + 1 < args.length) {\n\t\t\tresult.excludeTools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tmessage: `Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t\tconst next = args[i + 1];\n\t\t\tif (next !== undefined && !next.startsWith(\"@\") && (!next.startsWith(\"-\") || next.startsWith(\"---\"))) {\n\t\t\t\tresult.messages.push(next);\n\t\t\t\ti++;\n\t\t\t}\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--no-context-files\" || arg === \"-nc\") {\n\t\t\tresult.noContextFiles = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--approve\" || arg === \"-a\") {\n\t\t\tresult.projectTrustOverride = true;\n\t\t} else if (arg === \"--no-approve\" || arg === \"-na\") {\n\t\t\tresult.projectTrustOverride = false;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\")) {\n\t\t\tconst eqIndex = arg.indexOf(\"=\");\n\t\t\tif (eqIndex !== -1) {\n\t\t\t\tresult.unknownFlags.set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1));\n\t\t\t} else {\n\t\t\t\tconst flagName = arg.slice(2);\n\t\t\t\tconst next = args[i + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\") && !next.startsWith(\"@\")) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, next);\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (arg.startsWith(\"-\") && !arg.startsWith(\"--\")) {\n\t\t\tresult.diagnostics.push({ type: \"error\", message: `Unknown option: ${arg}` });\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(extensionFlags?: ExtensionFlag[]): void {\n\tconst extensionFlagsText =\n\t\textensionFlags && extensionFlags.length > 0\n\t\t\t? `\\n${chalk.bold(\"Extension CLI Flags:\")}\\n${extensionFlags\n\t\t\t\t\t.map((flag) => {\n\t\t\t\t\t\tconst value = flag.type === \"string\" ? \" <value>\" : \"\";\n\t\t\t\t\t\tconst description = flag.description ?? `Registered by ${flag.extensionPath}`;\n\t\t\t\t\t\treturn ` --${flag.name}${value}`.padEnd(30) + description;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")}\\n`\n\t\t\t: \"\";\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} uninstall <source> [-l] Alias for remove\n ${APP_NAME} update [source|self|pi] Update pi (use --all for pi and extensions)\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config [-l] Open TUI to enable/disable package resources (Tab switches scope)\n ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list/config\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path|id> Use specific session file or partial UUID\n --session-id <id> Use exact project session ID, creating it if missing\n --fork <path|id> Fork specific session file or partial UUID into a new session\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --name, -n <name> Set session display name\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools, -nt Disable all tools by default (built-in and extension)\n --no-builtin-tools, -nbt Disable built-in tools by default but keep extension/custom tools enabled\n --tools, -t <tools> Comma-separated allowlist of tool names to enable\n Applies to built-in, extension, and custom tools\n --exclude-tools, -xt <tools> Comma-separated denylist of tool names to disable\n Applies to built-in, extension, and custom tools\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh, max\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --no-context-files, -nc Disable AGENTS.md and CLAUDE.md discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --approve, -a Trust project-local files for this run\n --no-approve, -na Ignore project-local files for this run\n --offline Disable startup network operations (same as PI_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).${extensionFlagsText}\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Start a named session\n ${APP_NAME} --name \"Refactor auth module\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Disable one tool while keeping the rest available\n ${APP_NAME} --exclude-tools ask_question\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n ANT_LING_API_KEY - Ant Ling API key\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI/Cognitive Services base URL (e.g. https://{resource}.openai.azure.com)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n DEEPSEEK_API_KEY - DeepSeek API key\n NVIDIA_API_KEY - NVIDIA NIM API key\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n FIREWORKS_API_KEY - Fireworks API key\n TOGETHER_API_KEY - Together AI API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI Coding Plan API key (Global)\n ZAI_CODING_CN_API_KEY - ZAI Coding Plan API key (China)\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n MOONSHOT_API_KEY - Moonshot AI API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)\n CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)\n CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)\n XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)\n XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)\n XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)\n XIAOMI_TOKEN_PLAN_SGP_API_KEY - Xiaomi MiMo Token Plan API key (Singapore region)\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Config directory (default: ~/${CONFIG_DIR_NAME}/agent)\n ${ENV_SESSION_DIR.padEnd(32)} - Session storage directory (overridden by --session-dir)\n PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n PI_OFFLINE - Disable startup network operations when set to 1/true/yes\n PI_TELEMETRY - Override install telemetry when set to 1/true/yes or 0/false/no\n PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)\n\n${chalk.bold(\"Built-in Tool Names:\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CLI argument parsing and help display\n */\n\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport chalk from \"chalk\";\nimport { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, ENV_SESSION_DIR } from \"../config.ts\";\nimport type { ExtensionFlag } from \"../core/extensions/types.ts\";\n\nexport type Mode = \"text\" | \"json\" | \"rpc\";\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string[];\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tmode?: Mode;\n\tname?: string;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionId?: string;\n\tfork?: string;\n\tsessionDir?: string;\n\tmodels?: string[];\n\ttools?: string[];\n\texcludeTools?: string[];\n\tnoTools?: boolean;\n\tnoBuiltinTools?: boolean;\n\textensions?: string[];\n\tnoExtensions?: boolean;\n\tprint?: boolean;\n\texport?: string;\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tpromptTemplates?: string[];\n\tnoPromptTemplates?: boolean;\n\tthemes?: string[];\n\tnoThemes?: boolean;\n\tnoContextFiles?: boolean;\n\tlistModels?: string | true;\n\toffline?: boolean;\n\tverbose?: boolean;\n\tprojectTrustOverride?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n\t/** Unknown flags (potentially extension flags) - map of flag name to value */\n\tunknownFlags: Map<string, boolean | string>;\n\tdiagnostics: Array<{ type: \"warning\" | \"error\"; message: string }>;\n}\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t\tunknownFlags: new Map(),\n\t\tdiagnostics: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = result.appendSystemPrompt ?? [];\n\t\t\tresult.appendSystemPrompt.push(args[++i]);\n\t\t} else if (arg === \"--name\" || arg === \"-n\") {\n\t\t\tif (i + 1 < args.length) {\n\t\t\t\tresult.name = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({ type: \"error\", message: \"--name requires a value\" });\n\t\t\t}\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-id\" && i + 1 < args.length) {\n\t\t\tresult.sessionId = args[++i];\n\t\t} else if (arg === \"--fork\" && i + 1 < args.length) {\n\t\t\tresult.fork = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--models\" && i + 1 < args.length) {\n\t\t\tresult.models = args[++i].split(\",\").map((s) => s.trim());\n\t\t} else if (arg === \"--no-tools\" || arg === \"-nt\") {\n\t\t\tresult.noTools = true;\n\t\t} else if (arg === \"--no-builtin-tools\" || arg === \"-nbt\") {\n\t\t\tresult.noBuiltinTools = true;\n\t\t} else if ((arg === \"--tools\" || arg === \"-t\") && i + 1 < args.length) {\n\t\t\tresult.tools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if ((arg === \"--exclude-tools\" || arg === \"-xt\") && i + 1 < args.length) {\n\t\t\tresult.excludeTools = args[++i]\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((name) => name.length > 0);\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (isValidThinkingLevel(level)) {\n\t\t\t\tresult.thinking = level;\n\t\t\t} else {\n\t\t\t\tresult.diagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tmessage: `Invalid thinking level \"${level}\". Valid values: ${VALID_THINKING_LEVELS.join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t\tconst next = args[i + 1];\n\t\t\tif (next !== undefined && !next.startsWith(\"@\") && (!next.startsWith(\"-\") || next.startsWith(\"---\"))) {\n\t\t\t\tresult.messages.push(next);\n\t\t\t\ti++;\n\t\t\t}\n\t\t} else if (arg === \"--export\" && i + 1 < args.length) {\n\t\t\tresult.export = args[++i];\n\t\t} else if ((arg === \"--extension\" || arg === \"-e\") && i + 1 < args.length) {\n\t\t\tresult.extensions = result.extensions ?? [];\n\t\t\tresult.extensions.push(args[++i]);\n\t\t} else if (arg === \"--no-extensions\" || arg === \"-ne\") {\n\t\t\tresult.noExtensions = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--prompt-template\" && i + 1 < args.length) {\n\t\t\tresult.promptTemplates = result.promptTemplates ?? [];\n\t\t\tresult.promptTemplates.push(args[++i]);\n\t\t} else if (arg === \"--theme\" && i + 1 < args.length) {\n\t\t\tresult.themes = result.themes ?? [];\n\t\t\tresult.themes.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\" || arg === \"-ns\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--no-prompt-templates\" || arg === \"-np\") {\n\t\t\tresult.noPromptTemplates = true;\n\t\t} else if (arg === \"--no-themes\") {\n\t\t\tresult.noThemes = true;\n\t\t} else if (arg === \"--no-context-files\" || arg === \"-nc\") {\n\t\t\tresult.noContextFiles = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\t// Check if next arg is a search pattern (not a flag or file arg)\n\t\t\tif (i + 1 < args.length && !args[i + 1].startsWith(\"-\") && !args[i + 1].startsWith(\"@\")) {\n\t\t\t\tresult.listModels = args[++i];\n\t\t\t} else {\n\t\t\t\tresult.listModels = true;\n\t\t\t}\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg === \"--approve\" || arg === \"-a\") {\n\t\t\tresult.projectTrustOverride = true;\n\t\t} else if (arg === \"--no-approve\" || arg === \"-na\") {\n\t\t\tresult.projectTrustOverride = false;\n\t\t} else if (arg === \"--offline\") {\n\t\t\tresult.offline = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1)); // Remove @ prefix\n\t\t} else if (arg.startsWith(\"--\")) {\n\t\t\tconst eqIndex = arg.indexOf(\"=\");\n\t\t\tif (eqIndex !== -1) {\n\t\t\t\tresult.unknownFlags.set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1));\n\t\t\t} else {\n\t\t\t\tconst flagName = arg.slice(2);\n\t\t\t\tconst next = args[i + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\") && !next.startsWith(\"@\")) {\n\t\t\t\t\tresult.unknownFlags.set(flagName, next);\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\tresult.unknownFlags.set(flagName, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (arg.startsWith(\"-\") && !arg.startsWith(\"--\")) {\n\t\t\tresult.diagnostics.push({ type: \"error\", message: `Unknown option: ${arg}` });\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(extensionFlags?: ExtensionFlag[]): void {\n\tconst extensionFlagsText =\n\t\textensionFlags && extensionFlags.length > 0\n\t\t\t? `\\n${chalk.bold(\"Extension CLI Flags:\")}\\n${extensionFlags\n\t\t\t\t\t.map((flag) => {\n\t\t\t\t\t\tconst value = flag.type === \"string\" ? \" <value>\" : \"\";\n\t\t\t\t\t\tconst description = flag.description ?? `Registered by ${flag.extensionPath}`;\n\t\t\t\t\t\treturn ` --${flag.name}${value}`.padEnd(30) + description;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")}\\n`\n\t\t\t: \"\";\n\tconsole.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n ${APP_NAME} [options] [@files...] [messages...]\n\n${chalk.bold(\"Commands:\")}\n ${APP_NAME} install <source> [-l] Install extension source and add to settings\n ${APP_NAME} remove <source> [-l] Remove extension source from settings\n ${APP_NAME} uninstall <source> [-l] Alias for remove\n ${APP_NAME} update [source|self|pi] Update pi, extensions, or model catalogs\n ${APP_NAME} list List installed extensions from settings\n ${APP_NAME} config [-l] Open TUI to enable/disable package resources (Tab switches scope)\n ${APP_NAME} <command> --help Show help for install/remove/uninstall/update/list/config\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <pattern> Model pattern or ID (supports \"provider/id\" and optional \":<thinking>\")\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)\n --mode <mode> Output mode: text (default), json, or rpc\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path|id> Use specific session file or partial UUID\n --session-id <id> Use exact project session ID, creating it if missing\n --fork <path|id> Fork specific session file or partial UUID into a new session\n --session-dir <dir> Directory for session storage and lookup\n --no-session Don't save session (ephemeral)\n --name, -n <name> Set session display name\n --models <patterns> Comma-separated model patterns for Ctrl+P cycling\n Supports globs (anthropic/*, *sonnet*) and fuzzy matching\n --no-tools, -nt Disable all tools by default (built-in and extension)\n --no-builtin-tools, -nbt Disable built-in tools by default but keep extension/custom tools enabled\n --tools, -t <tools> Comma-separated allowlist of tool names to enable\n Applies to built-in, extension, and custom tools\n --exclude-tools, -xt <tools> Comma-separated denylist of tool names to disable\n Applies to built-in, extension, and custom tools\n --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh, max\n --extension, -e <path> Load an extension file (can be used multiple times)\n --no-extensions, -ne Disable extension discovery (explicit -e paths still work)\n --skill <path> Load a skill file or directory (can be used multiple times)\n --no-skills, -ns Disable skills discovery and loading\n --prompt-template <path> Load a prompt template file or directory (can be used multiple times)\n --no-prompt-templates, -np Disable prompt template discovery and loading\n --theme <path> Load a theme file or directory (can be used multiple times)\n --no-themes Disable theme discovery and loading\n --no-context-files, -nc Disable AGENTS.md and CLAUDE.md discovery and loading\n --export <file> Export session file to HTML and exit\n --list-models [search] List available models (with optional fuzzy search)\n --verbose Force verbose startup (overrides quietStartup setting)\n --approve, -a Trust project-local files for this run\n --no-approve, -na Ignore project-local files for this run\n --offline Disable startup network operations (same as PI_OFFLINE=1)\n --help, -h Show this help\n --version, -v Show version number\n\nExtensions can register additional flags (e.g., --plan from plan-mode extension).${extensionFlagsText}\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n ${APP_NAME}\n\n # Interactive mode with initial prompt\n ${APP_NAME} \"List all .ts files in src/\"\n\n # Include files in initial message\n ${APP_NAME} @prompt.md @image.png \"What color is the sky?\"\n\n # Non-interactive mode (process and exit)\n ${APP_NAME} -p \"List all .ts files in src/\"\n\n # Multiple messages (interactive)\n ${APP_NAME} \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n ${APP_NAME} --continue \"What did we discuss?\"\n\n # Start a named session\n ${APP_NAME} --name \"Refactor auth module\"\n\n # Use different model\n ${APP_NAME} --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use model with provider prefix (no --provider needed)\n ${APP_NAME} --model openai/gpt-4o \"Help me refactor this code\"\n\n # Use model with thinking level shorthand\n ${APP_NAME} --model sonnet:high \"Solve this complex problem\"\n\n # Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o\n\n # Limit to a specific provider with glob pattern\n ${APP_NAME} --models \"github-copilot/*\"\n\n # Cycle models with fixed thinking levels\n ${APP_NAME} --models sonnet:high,haiku:low\n\n # Start with a specific thinking level\n ${APP_NAME} --thinking high \"Solve this complex problem\"\n\n # Read-only mode (no file modifications possible)\n ${APP_NAME} --tools read,grep,find,ls -p \"Review the code in src/\"\n\n # Disable one tool while keeping the rest available\n ${APP_NAME} --exclude-tools ask_question\n\n # Export a session file to HTML\n ${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl\n ${APP_NAME} --export session.jsonl output.html\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY - Anthropic Claude API key\n ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)\n ANT_LING_API_KEY - Ant Ling API key\n OPENAI_API_KEY - OpenAI GPT API key\n AZURE_OPENAI_API_KEY - Azure OpenAI API key\n AZURE_OPENAI_BASE_URL - Azure OpenAI/Cognitive Services base URL (e.g. https://{resource}.openai.azure.com)\n AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)\n AZURE_OPENAI_API_VERSION - Azure OpenAI API version (default: v1)\n AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)\n DEEPSEEK_API_KEY - DeepSeek API key\n NVIDIA_API_KEY - NVIDIA NIM API key\n GEMINI_API_KEY - Google Gemini API key\n GROQ_API_KEY - Groq API key\n CEREBRAS_API_KEY - Cerebras API key\n XAI_API_KEY - xAI Grok API key\n FIREWORKS_API_KEY - Fireworks API key\n TOGETHER_API_KEY - Together AI API key\n OPENROUTER_API_KEY - OpenRouter API key\n AI_GATEWAY_API_KEY - Vercel AI Gateway API key\n ZAI_API_KEY - ZAI Coding Plan API key (Global)\n ZAI_CODING_CN_API_KEY - ZAI Coding Plan API key (China)\n MISTRAL_API_KEY - Mistral API key\n MINIMAX_API_KEY - MiniMax API key\n MOONSHOT_API_KEY - Moonshot AI API key\n OPENCODE_API_KEY - OpenCode Zen/OpenCode Go API key\n KIMI_API_KEY - Kimi For Coding API key\n CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)\n CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)\n CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)\n QWEN_TOKEN_PLAN_API_KEY - Qwen Token Plan API key (international region)\n QWEN_TOKEN_PLAN_CN_API_KEY - Qwen Token Plan API key (China region)\n XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)\n XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)\n XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)\n XIAOMI_TOKEN_PLAN_SGP_API_KEY - Xiaomi MiMo Token Plan API key (Singapore region)\n AWS_PROFILE - AWS profile for Amazon Bedrock\n AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock\n AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock\n AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)\n AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)\n ${ENV_AGENT_DIR.padEnd(32)} - Config directory (default: ~/${CONFIG_DIR_NAME}/agent)\n ${ENV_SESSION_DIR.padEnd(32)} - Session storage directory (overridden by --session-dir)\n PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)\n PI_OFFLINE - Disable startup network operations when set to 1/true/yes\n PI_TELEMETRY - Override install telemetry when set to 1/true/yes or 0/false/no\n PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)\n\n${chalk.bold(\"Built-in Tool Names:\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n grep - Search file contents (read-only, off by default)\n find - Find files by glob pattern (read-only, off by default)\n ls - List directory contents (read-only, off by default)\n`);\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * List available models with optional fuzzy search
3
3
  */
4
- import type { ModelRegistry } from "../core/model-registry.ts";
4
+ import type { ModelRuntime } from "../core/model-runtime.ts";
5
5
  /**
6
6
  * List available models, optionally filtered by search pattern
7
7
  */
8
- export declare function listModels(modelRegistry: ModelRegistry, searchPattern?: string): Promise<void>;
8
+ export declare function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void>;
9
9
  //# sourceMappingURL=list-models.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-models.d.ts","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAiB/D;;GAEG;AACH,wBAAsB,UAAU,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFpG","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { fuzzyFilter } from \"@earendil-works/pi-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRegistry } from \"../core/model-registry.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRegistry: ModelRegistry, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRegistry.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = modelRegistry.getAvailable();\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
1
+ {"version":3,"file":"list-models.d.ts","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAiB7D;;GAEG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFlG","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { fuzzyFilter } from \"@earendil-works/pi-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
@@ -21,12 +21,12 @@ function formatTokenCount(count) {
21
21
  /**
22
22
  * List available models, optionally filtered by search pattern
23
23
  */
24
- export async function listModels(modelRegistry, searchPattern) {
25
- const loadError = modelRegistry.getError();
24
+ export async function listModels(modelRuntime, searchPattern) {
25
+ const loadError = modelRuntime.getError();
26
26
  if (loadError) {
27
27
  console.error(chalk.yellow(`Warning: errors loading models.json:\n${loadError}`));
28
28
  }
29
- const models = modelRegistry.getAvailable();
29
+ const models = [...(await modelRuntime.getAvailable())];
30
30
  if (models.length === 0) {
31
31
  console.log(formatNoModelsAvailableMessage());
32
32
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { fuzzyFilter } from \"@earendil-works/pi-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRegistry } from \"../core/model-registry.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRegistry: ModelRegistry, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRegistry.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = modelRegistry.getAvailable();\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
1
+ {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { fuzzyFilter } from \"@earendil-works/pi-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
package/dist/config.d.ts CHANGED
@@ -96,7 +96,7 @@ export declare const ENV_SESSION_DIR: string;
96
96
  export declare function expandTildePath(path: string): string;
97
97
  /** Get the share viewer URL for a gist ID */
98
98
  export declare function getShareViewerUrl(gistId: string): string;
99
- /** Get the agent config directory (e.g., ~/.pi/agent/) */
99
+ /** Get the agent config directory (e.g., ~/.selesai/agent/) */
100
100
  export declare function getAgentDir(): string;
101
101
  /** Get path to user's custom themes directory */
102
102
  export declare function getCustomThemesDir(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\taccessSync,\n\tchmodSync,\n\tconstants,\n\tcopyFileSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trealpathSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join, resolve, sep, win32 } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { spawnProcessSync } from \"./utils/child-process.ts\";\nimport { normalizePath } from \"./utils/paths.ts\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"source\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\ninterface SelfUpdateCommandStep {\n\tcommand: string;\n\targs: string[];\n\tdisplay: string;\n}\n\nexport interface SelfUpdateCommand extends SelfUpdateCommandStep {\n\tsteps?: SelfUpdateCommandStep[];\n}\n\nexport type SelfUpdatePackageTarget = string | { packageName: string; installSpec?: string };\n\nfunction normalizeSelfUpdatePackageTarget(target: SelfUpdatePackageTarget): {\n\tpackageName: string;\n\tinstallSpec: string;\n} {\n\tif (typeof target === \"string\") {\n\t\treturn { packageName: target, installSpec: target };\n\t}\n\treturn { packageName: target.packageName, installSpec: target.installSpec ?? target.packageName };\n}\n\nfunction makeSelfUpdateCommand(\n\tinstallStep: SelfUpdateCommandStep,\n\tuninstallStep?: SelfUpdateCommandStep,\n): SelfUpdateCommand {\n\tif (!uninstallStep) return installStep;\n\treturn {\n\t\t...installStep,\n\t\tdisplay: `${uninstallStep.display} && ${installStep.display}`,\n\t\tsteps: [uninstallStep, installStep],\n\t};\n}\n\nfunction makeSelfUpdateCommandStep(command: string, args: string[]): SelfUpdateCommandStep {\n\treturn {\n\t\tcommand,\n\t\targs,\n\t\tdisplay: [command, ...args].map((arg) => (/\\s/.test(arg) ? `\"${arg}\"` : arg)).join(\" \"),\n\t};\n}\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tif (existsSync(join(getPackageDir(), \".git\"))) {\n\t\treturn \"source\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase().replace(/\\\\/g, \"/\");\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime || resolvedPath.includes(\"/install/global/node_modules/\")) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nfunction getInferredNpmInstall(): { root: string; prefix: string } | undefined {\n\tconst packageDir = getPackageDir();\n\tconst path = process.platform === \"win32\" || packageDir.includes(\"\\\\\") ? win32 : { basename, dirname };\n\tconst parent = path.dirname(packageDir);\n\tlet root: string | undefined;\n\tif (path.basename(parent).startsWith(\"@\") && path.basename(path.dirname(parent)) === \"node_modules\") {\n\t\troot = path.dirname(parent);\n\t} else if (path.basename(parent) === \"node_modules\") {\n\t\troot = parent;\n\t}\n\tif (!root) return undefined;\n\tconst rootParent = path.dirname(root);\n\tif (path.basename(rootParent) === \"lib\") return { root, prefix: path.dirname(rootParent) };\n\t// Windows global npm prefixes use `<prefix>\\\\node_modules`, which is\n\t// indistinguishable from local project installs by path shape alone. Do not\n\t// infer unsupported Windows custom prefixes without `npm root -g` evidence.\n\treturn undefined;\n}\n\nfunction getSelfUpdateCommandForMethod(\n\tmethod: InstallMethod,\n\tinstalledPackageName: string,\n\tupdatePackageTarget: SelfUpdatePackageTarget = installedPackageName,\n\tnpmCommand?: string[],\n): SelfUpdateCommand | undefined {\n\tconst target = normalizeSelfUpdatePackageTarget(updatePackageTarget);\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn undefined;\n\t\tcase \"source\": {\n\t\t\tif (target.packageName !== installedPackageName) return undefined;\n\t\t\tconst packageDir = getPackageDir();\n\t\t\tconst steps = [\n\t\t\t\tmakeSelfUpdateCommandStep(\"git\", [\"-C\", packageDir, \"pull\", \"--ff-only\"]),\n\t\t\t\tmakeSelfUpdateCommandStep(\"npm\", [\"--prefix\", packageDir, \"install\"]),\n\t\t\t\tmakeSelfUpdateCommandStep(\"npm\", [\"--prefix\", packageDir, \"run\", \"build\"]),\n\t\t\t];\n\t\t\treturn { ...steps[0], display: steps.map((step) => step.display).join(\" && \"), steps };\n\t\t}\n\t\tcase \"pnpm\": {\n\t\t\tconst match = readCommandOutput(\"pnpm\", [\"root\", \"-g\"])\n\t\t\t\t? undefined\n\t\t\t\t: /^(.*[\\\\/]global[\\\\/][^\\\\/]+)[\\\\/]\\.pnpm[\\\\/]/.exec(getPackageDir());\n\t\t\tconst binDirArgs = match\n\t\t\t\t? [`--config.global-bin-dir=${process.env.PNPM_HOME || dirname(dirname(match[1]))}`]\n\t\t\t\t: [];\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"pnpm\", [\n\t\t\t\t\t\"install\",\n\t\t\t\t\t\"-g\",\n\t\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\t\"--config.minimumReleaseAge=0\",\n\t\t\t\t\t...binDirArgs,\n\t\t\t\t\ttarget.installSpec,\n\t\t\t\t]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"pnpm\", [\"remove\", \"-g\", ...binDirArgs, installedPackageName]),\n\t\t\t);\n\t\t}\n\t\tcase \"yarn\":\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"yarn\", [\"global\", \"add\", \"--ignore-scripts\", target.installSpec]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"yarn\", [\"global\", \"remove\", installedPackageName]),\n\t\t\t);\n\t\tcase \"bun\":\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"bun\", [\n\t\t\t\t\t\"install\",\n\t\t\t\t\t\"-g\",\n\t\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\t\"--minimum-release-age=0\",\n\t\t\t\t\ttarget.installSpec,\n\t\t\t\t]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"bun\", [\"uninstall\", \"-g\", installedPackageName]),\n\t\t\t);\n\t\tcase \"npm\": {\n\t\t\tconst [command = \"npm\", ...npmArgs] = npmCommand ?? [];\n\t\t\tconst inferred = npmCommand?.length ? undefined : getInferredNpmInstall();\n\t\t\tconst prefixArgs = [...npmArgs, ...(inferred ? [\"--prefix\", inferred.prefix] : [])];\n\t\t\tconst installStep = makeSelfUpdateCommandStep(command, [\n\t\t\t\t...prefixArgs,\n\t\t\t\t\"install\",\n\t\t\t\t\"-g\",\n\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\"--min-release-age=0\",\n\t\t\t\ttarget.installSpec,\n\t\t\t]);\n\t\t\tconst uninstallStep =\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(command, [...prefixArgs, \"uninstall\", \"-g\", installedPackageName]);\n\t\t\treturn makeSelfUpdateCommand(installStep, uninstallStep);\n\t\t}\n\t\tcase \"unknown\":\n\t\t\treturn undefined;\n\t}\n}\n\nfunction readCommandOutput(\n\tcommand: string,\n\targs: string[],\n\toptions: { requireSuccess?: boolean } = {},\n): string | undefined {\n\tconst result = spawnProcessSync(command, args, {\n\t\tencoding: \"utf-8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t});\n\tif (result.status === 0) return result.stdout.trim() || undefined;\n\tif (options.requireSuccess) {\n\t\tconst reason = result.error?.message || result.stderr.trim() || `exit code ${result.status ?? \"unknown\"}`;\n\t\tthrow new Error(`Failed to run ${[command, ...args].join(\" \")}: ${reason}`);\n\t}\n\treturn undefined;\n}\n\nfunction getGlobalPackageRoots(method: InstallMethod, _packageName: string, npmCommand?: string[]): string[] {\n\tswitch (method) {\n\t\tcase \"npm\": {\n\t\t\tconst configured = !!npmCommand?.length;\n\t\t\tconst [command = \"npm\", ...npmArgs] = npmCommand ?? [];\n\t\t\tif (configured && command === \"bun\") {\n\t\t\t\tconst bunBin = readCommandOutput(command, [...npmArgs, \"pm\", \"bin\", \"-g\"], {\n\t\t\t\t\trequireSuccess: true,\n\t\t\t\t});\n\t\t\t\tconst roots = [join(homedir(), \".bun\", \"install\", \"global\", \"node_modules\")];\n\t\t\t\tif (bunBin) {\n\t\t\t\t\troots.push(join(dirname(bunBin), \"install\", \"global\", \"node_modules\"));\n\t\t\t\t}\n\t\t\t\treturn roots;\n\t\t\t}\n\t\t\tconst root = readCommandOutput(command, [...npmArgs, \"root\", \"-g\"], {\n\t\t\t\trequireSuccess: configured,\n\t\t\t});\n\t\t\tconst inferred = configured ? undefined : getInferredNpmInstall();\n\t\t\treturn [root, inferred?.root].filter((x): x is string => !!x);\n\t\t}\n\t\tcase \"pnpm\": {\n\t\t\tconst root = readCommandOutput(\"pnpm\", [\"root\", \"-g\"]);\n\t\t\tif (root) return [root, dirname(root)];\n\t\t\tconst match = /^(.*[\\\\/]global[\\\\/][^\\\\/]+)[\\\\/]\\.pnpm[\\\\/]/.exec(getPackageDir());\n\t\t\treturn match ? [match[1]] : [];\n\t\t}\n\t\tcase \"yarn\": {\n\t\t\tconst dir = readCommandOutput(\"yarn\", [\"global\", \"dir\"]);\n\t\t\treturn dir ? [dir, join(dir, \"node_modules\")] : [];\n\t\t}\n\t\tcase \"bun\": {\n\t\t\tconst bunBin = readCommandOutput(\"bun\", [\"pm\", \"bin\", \"-g\"]);\n\t\t\tconst roots = [join(homedir(), \".bun\", \"install\", \"global\", \"node_modules\")];\n\t\t\tif (bunBin) {\n\t\t\t\troots.push(join(dirname(bunBin), \"install\", \"global\", \"node_modules\"));\n\t\t\t}\n\t\t\treturn roots;\n\t\t}\n\t\tcase \"bun-binary\":\n\t\tcase \"source\":\n\t\tcase \"unknown\":\n\t\t\treturn [];\n\t}\n}\n\nfunction normalizeExistingPathForComparison(path: string, resolveSymlinks: boolean): string | undefined {\n\tconst resolvedPath = resolve(path);\n\tif (!existsSync(resolvedPath)) {\n\t\treturn undefined;\n\t}\n\tlet normalizedPath = resolvedPath;\n\tif (resolveSymlinks) {\n\t\ttry {\n\t\t\tnormalizedPath = realpathSync(resolvedPath);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\tif (process.platform === \"win32\") {\n\t\tnormalizedPath = normalizedPath.toLowerCase();\n\t}\n\treturn normalizedPath;\n}\n\nfunction getPathComparisonCandidates(path: string): string[] {\n\treturn Array.from(\n\t\tnew Set(\n\t\t\t[normalizeExistingPathForComparison(path, false), normalizeExistingPathForComparison(path, true)].filter(\n\t\t\t\t(candidate): candidate is string => !!candidate,\n\t\t\t),\n\t\t),\n\t);\n}\n\nfunction getEntrypointPackageDir(): string | undefined {\n\tconst entrypoint = process.argv[1];\n\tif (!entrypoint) return undefined;\n\tlet dir = dirname(entrypoint);\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\treturn undefined;\n}\n\nfunction isSelfUpdatePathWritable(): boolean {\n\tconst packageDir = getPackageDir();\n\ttry {\n\t\taccessSync(packageDir, constants.W_OK);\n\t\taccessSync(dirname(packageDir), constants.W_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isManagedByGlobalPackageManager(method: InstallMethod, packageName: string, npmCommand?: string[]): boolean {\n\tconst packageDirs = [getPackageDir(), getEntrypointPackageDir()].filter((dir): dir is string => !!dir);\n\tconst packageDirCandidates = packageDirs.flatMap((dir) => getPathComparisonCandidates(dir));\n\treturn getGlobalPackageRoots(method, packageName, npmCommand).some((root) => {\n\t\treturn getPathComparisonCandidates(root).some((normalizedRoot) => {\n\t\t\tconst rootPrefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;\n\t\t\treturn packageDirCandidates.some((packageDir) => packageDir.startsWith(rootPrefix));\n\t\t});\n\t});\n}\n\nexport function getSelfUpdateCommand(\n\tpackageName: string,\n\tnpmCommand?: string[],\n\tupdatePackageTarget: SelfUpdatePackageTarget = packageName,\n): SelfUpdateCommand | undefined {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName, updatePackageTarget, npmCommand);\n\tif (!command || !isSelfUpdatePathWritable()) {\n\t\treturn undefined;\n\t}\n\tif (method !== \"source\" && !isManagedByGlobalPackageManager(method, packageName, npmCommand)) {\n\t\treturn undefined;\n\t}\n\treturn command;\n}\n\nexport function getSelfUpdateUnavailableInstruction(\n\tpackageName: string,\n\tnpmCommand?: string[],\n\tupdatePackageTarget: SelfUpdatePackageTarget = packageName,\n): string {\n\tconst method = detectInstallMethod();\n\tconst target = normalizeSelfUpdatePackageTarget(updatePackageTarget);\n\tif (method === \"bun-binary\") {\n\t\treturn `Download from: https://github.com/earendil-works/pi-mono/releases/latest`;\n\t}\n\tconst command = getSelfUpdateCommandForMethod(method, packageName, target, npmCommand);\n\tif (command) {\n\t\tif (method === \"source\") {\n\t\t\treturn isSelfUpdatePathWritable()\n\t\t\t\t? `Update the source checkout yourself with: ${command.display}`\n\t\t\t\t: `This source checkout is not writable. Update it yourself with: ${command.display}`;\n\t\t}\n\t\tif (isManagedByGlobalPackageManager(method, packageName, npmCommand) && !isSelfUpdatePathWritable()) {\n\t\t\treturn `This installation is managed by a global ${method} install, but the install path is not writable. Update it yourself with: ${command.display}`;\n\t\t}\n\t\treturn `This installation is not managed by a global ${method} install. Update it with the package manager, wrapper, or source checkout that provides it.`;\n\t}\n\treturn `Update ${target.installSpec} using the package manager, wrapper, or source checkout that provides this installation.`;\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName);\n\tif (command) {\n\t\treturn `Run: ${command.display}`;\n\t}\n\treturn getSelfUpdateUnavailableInstruction(packageName);\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.PI_PACKAGE_DIR;\n\tif (envDir) {\n\t\treturn normalizePath(envDir);\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n/**\n * Get path to built-in interactive assets directory.\n * - For Bun binary: assets/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/assets/\n * - For tsx (src/): src/modes/interactive/assets/\n */\nexport function getInteractiveAssetsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"assets\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"assets\");\n}\n\n/**\n * Resolve a bundled subdirectory shipped with the package (defaults/extensions/themes).\n * - For Bun binary: <dir>/ next to executable\n * - For Node.js (dist/): dist/<dir>/\n * - For tsx (src/): src/<dir>/\n */\nfunction getBundledSubdir(name: string): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), name);\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, name);\n}\n\n/**\n * Get path to bundled default config directory (shipped with package).\n * Holds bundled defaults. settings.json is copied on first run; models.json is loaded directly.\n */\nexport function getBundledDefaultsDir(): string {\n\treturn getBundledSubdir(\"defaults\");\n}\n\n/**\n * Get path to bundled built-in extensions directory (shipped with package).\n * Loaded directly via additionalExtensionPaths at boot (not copied into the\n * user agent dir) — same hook as CLI --extension. .ts ships as-is (jiti loads it).\n * - For Bun binary: extensions/ next to executable\n * - For Node.js (dist/): dist/extensions/\n * - For tsx (src/): src/extensions/\n */\nexport function getBundledExtensionsDir(): string {\n\treturn getBundledSubdir(\"extensions\");\n}\n\n/**\n * Get path to bundled built-in themes directory (shipped with package).\n * Loaded directly via additionalThemePaths at boot.\n */\nexport function getBundledThemesDir(): string {\n\treturn getBundledSubdir(\"themes\");\n}\n\n/**\n * Get path to bundled built-in skills directory (shipped with package).\n * Loaded directly via additionalSkillPaths at boot.\n */\nexport function getBundledSkillsDir(): string {\n\treturn getBundledSubdir(\"skills\");\n}\n\n/** Get path to a bundled interactive asset */\nexport function getBundledInteractiveAssetPath(name: string): string {\n\treturn join(getInteractiveAssetsDir(), name);\n}\n\n// =============================================================================\n// App Config (from package.json piConfig)\n// =============================================================================\n\ninterface PackageJson {\n\tname?: string;\n\tversion?: string;\n\tpiConfig?: {\n\t\tname?: string;\n\t\tconfigDir?: string;\n\t};\n}\n\nlet pkg: PackageJson = {};\ntry {\n\tpkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\")) as PackageJson;\n} catch (e: unknown) {\n\tconst err = e as NodeJS.ErrnoException;\n\tif (err.code !== \"ENOENT\") throw e;\n}\n\nconst piConfigName: string | undefined = pkg.piConfig?.name;\nexport const PACKAGE_NAME: string = pkg.name || \"@earendil-works/pi-coding-agent\";\nexport const APP_NAME: string = piConfigName || \"pi\";\nexport const APP_TITLE: string = piConfigName ? APP_NAME : \"π\";\nexport const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || \".pi\";\nexport const VERSION: string = pkg.version || \"0.0.0\";\n\n// e.g., PI_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\nexport const ENV_SESSION_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;\n\nexport function expandTildePath(path: string): string {\n\treturn normalizePath(path);\n}\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://pi.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.PI_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.pi/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.pi/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\treturn expandTildePath(envDir);\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n\n/**\n * Marker file written once first-time onboarding completes. Decouples the\n * first-run dialog gate from settings.json existence so that bootstrapping a\n * bundled default settings.json does not suppress the dialog.\n */\nexport function getFirstRunMarkerPath(agentDir: string = getAgentDir()): string {\n\treturn join(agentDir, \".firstRunComplete\");\n}\n\n/**\n * Mark first-run onboarding as complete. Safe to call repeatedly.\n */\nexport function markFirstRunComplete(agentDir: string = getAgentDir()): void {\n\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\twriteFileSync(getFirstRunMarkerPath(agentDir), \"1\", { mode: 0o600 });\n}\n\n// =============================================================================\n// Agent Dir Bootstrap (first-run seeding)\n// =============================================================================\n\n/** Subdirectories created under the agent dir on first run. */\nconst AGENT_SUBDIRS = [\n\t\"themes\",\n\t\"tools\",\n\t\"bin\",\n\t\"prompts\",\n\t\"sessions\",\n\t\"extensions\",\n\t\"skills\",\n] as const;\n\n/**\n * Ensure the agent dir and standard subdirs exist (mode 0o700 for privacy).\n * Safe to call on every startup; no-op when dirs already exist.\n */\nexport function ensureAgentDir(agentDir: string = getAgentDir()): void {\n\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\tfor (const sub of AGENT_SUBDIRS) {\n\t\tmkdirSync(join(agentDir, sub), { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Seed a default config file from the bundled defaults dir if it does not yet\n * exist. Never overwrites an existing user file. Returns the destination path\n * when a seed was written, undefined when the file already existed or the\n * bundled source is missing.\n */\nexport function seedDefaultConfigFile(\n\tdestPath: string,\n\tbundledName: string,\n\tbundledDefaultsDir: string = getBundledDefaultsDir(),\n): string | undefined {\n\tif (existsSync(destPath)) return undefined;\n\tconst source = join(bundledDefaultsDir, bundledName);\n\tif (!existsSync(source)) return undefined;\n\tmkdirSync(dirname(destPath), { recursive: true, mode: 0o700 });\n\tcopyFileSync(source, destPath);\n\ttry {\n\t\tchmodSync(destPath, 0o600);\n\t} catch {\n\t\t// chmod is best-effort (no-op on platforms that don't support it).\n\t}\n\treturn destPath;\n}\n\n/**\n * Recursively copy a bundled directory tree into the user's agent dir, skipping\n * any file that already exists (user edits survive). Never overwrites. Used to\n * seed bundled skills/themes so the user can inspect and edit them.\n * Returns the list of destination paths that were written.\n */\nfunction seedBundledDir(\n\tdestDir: string,\n\tbundledDir: string,\n): string[] {\n\tif (!existsSync(bundledDir)) return [];\n\tmkdirSync(destDir, { recursive: true, mode: 0o700 });\n\tconst written: string[] = [];\n\tconst stack: Array<{ src: string; dst: string }> = [{ src: bundledDir, dst: destDir }];\n\twhile (stack.length > 0) {\n\t\tconst { src, dst } = stack.pop()!;\n\t\tmkdirSync(dst, { recursive: true, mode: 0o700 });\n\t\tfor (const entry of readdirSync(src, { withFileTypes: true })) {\n\t\t\tif (entry.name === \".DS_Store\" || entry.name === \"node_modules\") continue;\n\t\t\tconst srcPath = join(src, entry.name);\n\t\t\tconst dstPath = join(dst, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (!existsSync(dstPath)) mkdirSync(dstPath, { recursive: true, mode: 0o700 });\n\t\t\t\tstack.push({ src: srcPath, dst: dstPath });\n\t\t\t} else if (entry.isFile() || entry.isSymbolicLink()) {\n\t\t\t\tif (existsSync(dstPath)) continue;\n\t\t\t\tcopyFileSync(srcPath, dstPath);\n\t\t\t\ttry {\n\t\t\t\t\tchmodSync(dstPath, 0o600);\n\t\t\t\t} catch {\n\t\t\t\t\t// best-effort\n\t\t\t\t}\n\t\t\t\twritten.push(dstPath);\n\t\t\t}\n\t\t}\n\t}\n\treturn written;\n}\n\nfunction removeIdenticalBundledFiles(destDir: string, bundledDir: string): string[] {\n\tif (!existsSync(destDir) || !existsSync(bundledDir)) return [];\n\tconst removed: string[] = [];\n\tconst stack: Array<{ src: string; dst: string }> = [{ src: bundledDir, dst: destDir }];\n\twhile (stack.length > 0) {\n\t\tconst { src, dst } = stack.pop()!;\n\t\tif (!existsSync(dst)) continue;\n\t\tfor (const entry of readdirSync(src, { withFileTypes: true })) {\n\t\t\tif (entry.name === \".DS_Store\" || entry.name === \"node_modules\") continue;\n\t\t\tconst srcPath = join(src, entry.name);\n\t\t\tconst dstPath = join(dst, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tstack.push({ src: srcPath, dst: dstPath });\n\t\t\t} else if (existsSync(dstPath) && readFileSync(srcPath).equals(readFileSync(dstPath))) {\n\t\t\t\tunlinkSync(dstPath);\n\t\t\t\tremoved.push(dstPath);\n\t\t\t}\n\t\t}\n\t}\n\treturn removed;\n}\n\n/**\n * Bundled extensions load directly from the installed package. Do not copy them\n * into the user's agent dir, otherwise startup discovers both copies and tool\n * registration conflicts with itself.\n * Remove files copied by older releases only when they are byte-identical to\n * bundled files, so user-edited extensions survive.\n */\nexport function seedDefaultExtensions(\n\tagentDir: string,\n\tbundledExtensionsDir: string = getBundledExtensionsDir(),\n): string[] {\n\tremoveIdenticalBundledFiles(join(agentDir, \"extensions\"), bundledExtensionsDir);\n\treturn [];\n}\n\n/**\n * Seed bundled built-in skills into the user's agent dir/skills.\n * Skips existing files (user edits survive). Never overwrites.\n * Returns the list of destination paths that were written.\n */\nexport function seedDefaultSkills(\n\tagentDir: string,\n\tbundledSkillsDir: string = getBundledSkillsDir(),\n): string[] {\n\treturn seedBundledDir(join(agentDir, \"skills\"), bundledSkillsDir);\n}\n\n/**\n * Seed bundled built-in themes into the user's agent dir/themes.\n * Skips existing files (user edits survive). Never overwrites.\n * Returns the list of destination paths that were written.\n */\nexport function seedDefaultThemes(\n\tagentDir: string,\n\tbundledThemesDir: string = getBundledThemesDir(),\n): string[] {\n\treturn seedBundledDir(join(agentDir, \"themes\"), bundledThemesDir);\n}\n\n/**\n * Run full first-run bootstrap for the agent dir: ensure directories and seed\n * settings.json from bundled defaults. Idempotent — safe on every startup.\n * Bundled models load package-locally; copying them would expose internal\n * providers as user config. Bundled extensions also stay package-local.\n */\nexport function bootstrapAgentDir(agentDir: string = getAgentDir()): void {\n\tensureAgentDir(agentDir);\n\tseedDefaultConfigFile(join(agentDir, \"settings.json\"), \"settings.json\");\n\tseedDefaultExtensions(agentDir);\n\tseedDefaultSkills(agentDir);\n\tseedDefaultThemes(agentDir);\n}\n"]}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\taccessSync,\n\tchmodSync,\n\tconstants,\n\tcopyFileSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trealpathSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join, resolve, sep, win32 } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { spawnProcessSync } from \"./utils/child-process.ts\";\nimport { normalizePath } from \"./utils/paths.ts\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"source\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\ninterface SelfUpdateCommandStep {\n\tcommand: string;\n\targs: string[];\n\tdisplay: string;\n}\n\nexport interface SelfUpdateCommand extends SelfUpdateCommandStep {\n\tsteps?: SelfUpdateCommandStep[];\n}\n\nexport type SelfUpdatePackageTarget = string | { packageName: string; installSpec?: string };\n\nfunction normalizeSelfUpdatePackageTarget(target: SelfUpdatePackageTarget): {\n\tpackageName: string;\n\tinstallSpec: string;\n} {\n\tif (typeof target === \"string\") {\n\t\treturn { packageName: target, installSpec: target };\n\t}\n\treturn { packageName: target.packageName, installSpec: target.installSpec ?? target.packageName };\n}\n\nfunction makeSelfUpdateCommand(\n\tinstallStep: SelfUpdateCommandStep,\n\tuninstallStep?: SelfUpdateCommandStep,\n): SelfUpdateCommand {\n\tif (!uninstallStep) return installStep;\n\treturn {\n\t\t...installStep,\n\t\tdisplay: `${uninstallStep.display} && ${installStep.display}`,\n\t\tsteps: [uninstallStep, installStep],\n\t};\n}\n\nfunction makeSelfUpdateCommandStep(command: string, args: string[]): SelfUpdateCommandStep {\n\treturn {\n\t\tcommand,\n\t\targs,\n\t\tdisplay: [command, ...args].map((arg) => (/\\s/.test(arg) ? `\"${arg}\"` : arg)).join(\" \"),\n\t};\n}\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tif (existsSync(join(getPackageDir(), \".git\"))) {\n\t\treturn \"source\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase().replace(/\\\\/g, \"/\");\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime || resolvedPath.includes(\"/install/global/node_modules/\")) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nfunction getInferredNpmInstall(): { root: string; prefix: string } | undefined {\n\tconst packageDir = getPackageDir();\n\tconst path = process.platform === \"win32\" || packageDir.includes(\"\\\\\") ? win32 : { basename, dirname };\n\tconst parent = path.dirname(packageDir);\n\tlet root: string | undefined;\n\tif (path.basename(parent).startsWith(\"@\") && path.basename(path.dirname(parent)) === \"node_modules\") {\n\t\troot = path.dirname(parent);\n\t} else if (path.basename(parent) === \"node_modules\") {\n\t\troot = parent;\n\t}\n\tif (!root) return undefined;\n\tconst rootParent = path.dirname(root);\n\tif (path.basename(rootParent) === \"lib\") return { root, prefix: path.dirname(rootParent) };\n\t// Windows global npm prefixes use `<prefix>\\\\node_modules`, which is\n\t// indistinguishable from local project installs by path shape alone. Do not\n\t// infer unsupported Windows custom prefixes without `npm root -g` evidence.\n\treturn undefined;\n}\n\nfunction getSelfUpdateCommandForMethod(\n\tmethod: InstallMethod,\n\tinstalledPackageName: string,\n\tupdatePackageTarget: SelfUpdatePackageTarget = installedPackageName,\n\tnpmCommand?: string[],\n): SelfUpdateCommand | undefined {\n\tconst target = normalizeSelfUpdatePackageTarget(updatePackageTarget);\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn undefined;\n\t\tcase \"source\": {\n\t\t\tif (target.packageName !== installedPackageName) return undefined;\n\t\t\tconst packageDir = getPackageDir();\n\t\t\tconst steps = [\n\t\t\t\tmakeSelfUpdateCommandStep(\"git\", [\"-C\", packageDir, \"pull\", \"--ff-only\"]),\n\t\t\t\tmakeSelfUpdateCommandStep(\"npm\", [\"--prefix\", packageDir, \"install\"]),\n\t\t\t\tmakeSelfUpdateCommandStep(\"npm\", [\"--prefix\", packageDir, \"run\", \"build\"]),\n\t\t\t];\n\t\t\treturn { ...steps[0], display: steps.map((step) => step.display).join(\" && \"), steps };\n\t\t}\n\t\tcase \"pnpm\": {\n\t\t\tconst match = readCommandOutput(\"pnpm\", [\"root\", \"-g\"])\n\t\t\t\t? undefined\n\t\t\t\t: /^(.*[\\\\/]global[\\\\/][^\\\\/]+)[\\\\/]\\.pnpm[\\\\/]/.exec(getPackageDir());\n\t\t\tconst binDirArgs = match\n\t\t\t\t? [`--config.global-bin-dir=${process.env.PNPM_HOME || dirname(dirname(match[1]))}`]\n\t\t\t\t: [];\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"pnpm\", [\n\t\t\t\t\t\"install\",\n\t\t\t\t\t\"-g\",\n\t\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\t\"--config.minimumReleaseAge=0\",\n\t\t\t\t\t...binDirArgs,\n\t\t\t\t\ttarget.installSpec,\n\t\t\t\t]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"pnpm\", [\"remove\", \"-g\", ...binDirArgs, installedPackageName]),\n\t\t\t);\n\t\t}\n\t\tcase \"yarn\":\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"yarn\", [\"global\", \"add\", \"--ignore-scripts\", target.installSpec]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"yarn\", [\"global\", \"remove\", installedPackageName]),\n\t\t\t);\n\t\tcase \"bun\":\n\t\t\treturn makeSelfUpdateCommand(\n\t\t\t\tmakeSelfUpdateCommandStep(\"bun\", [\n\t\t\t\t\t\"install\",\n\t\t\t\t\t\"-g\",\n\t\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\t\"--minimum-release-age=0\",\n\t\t\t\t\ttarget.installSpec,\n\t\t\t\t]),\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(\"bun\", [\"uninstall\", \"-g\", installedPackageName]),\n\t\t\t);\n\t\tcase \"npm\": {\n\t\t\tconst [command = \"npm\", ...npmArgs] = npmCommand ?? [];\n\t\t\tconst inferred = npmCommand?.length ? undefined : getInferredNpmInstall();\n\t\t\tconst prefixArgs = [...npmArgs, ...(inferred ? [\"--prefix\", inferred.prefix] : [])];\n\t\t\tconst installStep = makeSelfUpdateCommandStep(command, [\n\t\t\t\t...prefixArgs,\n\t\t\t\t\"install\",\n\t\t\t\t\"-g\",\n\t\t\t\t\"--ignore-scripts\",\n\t\t\t\t\"--min-release-age=0\",\n\t\t\t\ttarget.installSpec,\n\t\t\t]);\n\t\t\tconst uninstallStep =\n\t\t\t\ttarget.packageName === installedPackageName\n\t\t\t\t\t? undefined\n\t\t\t\t\t: makeSelfUpdateCommandStep(command, [...prefixArgs, \"uninstall\", \"-g\", installedPackageName]);\n\t\t\treturn makeSelfUpdateCommand(installStep, uninstallStep);\n\t\t}\n\t\tcase \"unknown\":\n\t\t\treturn undefined;\n\t}\n}\n\nfunction readCommandOutput(\n\tcommand: string,\n\targs: string[],\n\toptions: { requireSuccess?: boolean } = {},\n): string | undefined {\n\tconst result = spawnProcessSync(command, args, {\n\t\tencoding: \"utf-8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t});\n\tif (result.status === 0) return result.stdout.trim() || undefined;\n\tif (options.requireSuccess) {\n\t\tconst reason = result.error?.message || result.stderr.trim() || `exit code ${result.status ?? \"unknown\"}`;\n\t\tthrow new Error(`Failed to run ${[command, ...args].join(\" \")}: ${reason}`);\n\t}\n\treturn undefined;\n}\n\nfunction getGlobalPackageRoots(method: InstallMethod, _packageName: string, npmCommand?: string[]): string[] {\n\tswitch (method) {\n\t\tcase \"npm\": {\n\t\t\tconst configured = !!npmCommand?.length;\n\t\t\tconst [command = \"npm\", ...npmArgs] = npmCommand ?? [];\n\t\t\tif (configured && command === \"bun\") {\n\t\t\t\tconst bunBin = readCommandOutput(command, [...npmArgs, \"pm\", \"bin\", \"-g\"], {\n\t\t\t\t\trequireSuccess: true,\n\t\t\t\t});\n\t\t\t\tconst roots = [join(homedir(), \".bun\", \"install\", \"global\", \"node_modules\")];\n\t\t\t\tif (bunBin) {\n\t\t\t\t\troots.push(join(dirname(bunBin), \"install\", \"global\", \"node_modules\"));\n\t\t\t\t}\n\t\t\t\treturn roots;\n\t\t\t}\n\t\t\tconst root = readCommandOutput(command, [...npmArgs, \"root\", \"-g\"], {\n\t\t\t\trequireSuccess: configured,\n\t\t\t});\n\t\t\tconst inferred = configured ? undefined : getInferredNpmInstall();\n\t\t\treturn [root, inferred?.root].filter((x): x is string => !!x);\n\t\t}\n\t\tcase \"pnpm\": {\n\t\t\tconst root = readCommandOutput(\"pnpm\", [\"root\", \"-g\"]);\n\t\t\tif (root) return [root, dirname(root)];\n\t\t\tconst match = /^(.*[\\\\/]global[\\\\/][^\\\\/]+)[\\\\/]\\.pnpm[\\\\/]/.exec(getPackageDir());\n\t\t\treturn match ? [match[1]] : [];\n\t\t}\n\t\tcase \"yarn\": {\n\t\t\tconst dir = readCommandOutput(\"yarn\", [\"global\", \"dir\"]);\n\t\t\treturn dir ? [dir, join(dir, \"node_modules\")] : [];\n\t\t}\n\t\tcase \"bun\": {\n\t\t\tconst bunBin = readCommandOutput(\"bun\", [\"pm\", \"bin\", \"-g\"]);\n\t\t\tconst roots = [join(homedir(), \".bun\", \"install\", \"global\", \"node_modules\")];\n\t\t\tif (bunBin) {\n\t\t\t\troots.push(join(dirname(bunBin), \"install\", \"global\", \"node_modules\"));\n\t\t\t}\n\t\t\treturn roots;\n\t\t}\n\t\tcase \"bun-binary\":\n\t\tcase \"source\":\n\t\tcase \"unknown\":\n\t\t\treturn [];\n\t}\n}\n\nfunction normalizeExistingPathForComparison(path: string, resolveSymlinks: boolean): string | undefined {\n\tconst resolvedPath = resolve(path);\n\tif (!existsSync(resolvedPath)) {\n\t\treturn undefined;\n\t}\n\tlet normalizedPath = resolvedPath;\n\tif (resolveSymlinks) {\n\t\ttry {\n\t\t\tnormalizedPath = realpathSync(resolvedPath);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\tif (process.platform === \"win32\") {\n\t\tnormalizedPath = normalizedPath.toLowerCase();\n\t}\n\treturn normalizedPath;\n}\n\nfunction getPathComparisonCandidates(path: string): string[] {\n\treturn Array.from(\n\t\tnew Set(\n\t\t\t[normalizeExistingPathForComparison(path, false), normalizeExistingPathForComparison(path, true)].filter(\n\t\t\t\t(candidate): candidate is string => !!candidate,\n\t\t\t),\n\t\t),\n\t);\n}\n\nfunction getEntrypointPackageDir(): string | undefined {\n\tconst entrypoint = process.argv[1];\n\tif (!entrypoint) return undefined;\n\tlet dir = dirname(entrypoint);\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\treturn undefined;\n}\n\nfunction isSelfUpdatePathWritable(): boolean {\n\tconst packageDir = getPackageDir();\n\ttry {\n\t\taccessSync(packageDir, constants.W_OK);\n\t\taccessSync(dirname(packageDir), constants.W_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isManagedByGlobalPackageManager(method: InstallMethod, packageName: string, npmCommand?: string[]): boolean {\n\tconst packageDirs = [getPackageDir(), getEntrypointPackageDir()].filter((dir): dir is string => !!dir);\n\tconst packageDirCandidates = packageDirs.flatMap((dir) => getPathComparisonCandidates(dir));\n\treturn getGlobalPackageRoots(method, packageName, npmCommand).some((root) => {\n\t\treturn getPathComparisonCandidates(root).some((normalizedRoot) => {\n\t\t\tconst rootPrefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;\n\t\t\treturn packageDirCandidates.some((packageDir) => packageDir.startsWith(rootPrefix));\n\t\t});\n\t});\n}\n\nexport function getSelfUpdateCommand(\n\tpackageName: string,\n\tnpmCommand?: string[],\n\tupdatePackageTarget: SelfUpdatePackageTarget = packageName,\n): SelfUpdateCommand | undefined {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName, updatePackageTarget, npmCommand);\n\tif (!command || !isSelfUpdatePathWritable()) {\n\t\treturn undefined;\n\t}\n\tif (method !== \"source\" && !isManagedByGlobalPackageManager(method, packageName, npmCommand)) {\n\t\treturn undefined;\n\t}\n\treturn command;\n}\n\nexport function getSelfUpdateUnavailableInstruction(\n\tpackageName: string,\n\tnpmCommand?: string[],\n\tupdatePackageTarget: SelfUpdatePackageTarget = packageName,\n): string {\n\tconst method = detectInstallMethod();\n\tconst target = normalizeSelfUpdatePackageTarget(updatePackageTarget);\n\tif (method === \"bun-binary\") {\n\t\treturn `Download from: https://github.com/earendil-works/pi-mono/releases/latest`;\n\t}\n\tconst command = getSelfUpdateCommandForMethod(method, packageName, target, npmCommand);\n\tif (command) {\n\t\tif (method === \"source\") {\n\t\t\treturn isSelfUpdatePathWritable()\n\t\t\t\t? `Update the source checkout yourself with: ${command.display}`\n\t\t\t\t: `This source checkout is not writable. Update it yourself with: ${command.display}`;\n\t\t}\n\t\tif (isManagedByGlobalPackageManager(method, packageName, npmCommand) && !isSelfUpdatePathWritable()) {\n\t\t\treturn `This installation is managed by a global ${method} install, but the install path is not writable. Update it yourself with: ${command.display}`;\n\t\t}\n\t\treturn `This installation is not managed by a global ${method} install. Update it with the package manager, wrapper, or source checkout that provides it.`;\n\t}\n\treturn `Update ${target.installSpec} using the package manager, wrapper, or source checkout that provides this installation.`;\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName);\n\tif (command) {\n\t\treturn `Run: ${command.display}`;\n\t}\n\treturn getSelfUpdateUnavailableInstruction(packageName);\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.PI_PACKAGE_DIR;\n\tif (envDir) {\n\t\treturn normalizePath(envDir);\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n/**\n * Get path to built-in interactive assets directory.\n * - For Bun binary: assets/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/assets/\n * - For tsx (src/): src/modes/interactive/assets/\n */\nexport function getInteractiveAssetsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"assets\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"assets\");\n}\n\n/**\n * Resolve a bundled subdirectory shipped with the package (defaults/extensions/themes).\n * - For Bun binary: <dir>/ next to executable\n * - For Node.js (dist/): dist/<dir>/\n * - For tsx (src/): src/<dir>/\n */\nfunction getBundledSubdir(name: string): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), name);\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, name);\n}\n\n/**\n * Get path to bundled default config directory (shipped with package).\n * Holds bundled defaults. settings.json is copied on first run; models.json is loaded directly.\n */\nexport function getBundledDefaultsDir(): string {\n\treturn getBundledSubdir(\"defaults\");\n}\n\n/**\n * Get path to bundled built-in extensions directory (shipped with package).\n * Loaded directly via additionalExtensionPaths at boot (not copied into the\n * user agent dir) — same hook as CLI --extension. .ts ships as-is (jiti loads it).\n * - For Bun binary: extensions/ next to executable\n * - For Node.js (dist/): dist/extensions/\n * - For tsx (src/): src/extensions/\n */\nexport function getBundledExtensionsDir(): string {\n\treturn getBundledSubdir(\"extensions\");\n}\n\n/**\n * Get path to bundled built-in themes directory (shipped with package).\n * Loaded directly via additionalThemePaths at boot.\n */\nexport function getBundledThemesDir(): string {\n\treturn getBundledSubdir(\"themes\");\n}\n\n/**\n * Get path to bundled built-in skills directory (shipped with package).\n * Loaded directly via additionalSkillPaths at boot.\n */\nexport function getBundledSkillsDir(): string {\n\treturn getBundledSubdir(\"skills\");\n}\n\n/** Get path to a bundled interactive asset */\nexport function getBundledInteractiveAssetPath(name: string): string {\n\treturn join(getInteractiveAssetsDir(), name);\n}\n\n// =============================================================================\n// App Config (from package.json piConfig)\n// =============================================================================\n\ninterface PackageJson {\n\tname?: string;\n\tversion?: string;\n\tpiConfig?: {\n\t\tname?: string;\n\t\tconfigDir?: string;\n\t};\n}\n\nlet pkg: PackageJson = {};\ntry {\n\tpkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\")) as PackageJson;\n} catch (e: unknown) {\n\tconst err = e as NodeJS.ErrnoException;\n\tif (err.code !== \"ENOENT\") throw e;\n}\n\nconst piConfigName: string | undefined = pkg.piConfig?.name;\nexport const PACKAGE_NAME: string = pkg.name || \"@earendil-works/pi-coding-agent\";\nexport const APP_NAME: string = piConfigName || \"pi\";\nexport const APP_TITLE: string = piConfigName ? APP_NAME : \"π\";\nexport const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || \".pi\";\nexport const VERSION: string = pkg.version || \"0.0.0\";\n\n// e.g., PI_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR\nexport const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;\nexport const ENV_SESSION_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;\n\nexport function expandTildePath(path: string): string {\n\treturn normalizePath(path);\n}\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://pi.dev/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.PI_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/<configured-dir>/agent/*)\n// =============================================================================\n\n/** Get the agent config directory (e.g., ~/.selesai/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\treturn expandTildePath(envDir);\n\t}\n\treturn join(homedir(), CONFIG_DIR_NAME, \"agent\");\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n\n/**\n * Marker file written once first-time onboarding completes. Decouples the\n * first-run dialog gate from settings.json existence so that bootstrapping a\n * bundled default settings.json does not suppress the dialog.\n */\nexport function getFirstRunMarkerPath(agentDir: string = getAgentDir()): string {\n\treturn join(agentDir, \".firstRunComplete\");\n}\n\n/**\n * Mark first-run onboarding as complete. Safe to call repeatedly.\n */\nexport function markFirstRunComplete(agentDir: string = getAgentDir()): void {\n\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\twriteFileSync(getFirstRunMarkerPath(agentDir), \"1\", { mode: 0o600 });\n}\n\n// =============================================================================\n// Agent Dir Bootstrap (first-run seeding)\n// =============================================================================\n\n/** Subdirectories created under the agent dir on first run. */\nconst AGENT_SUBDIRS = [\n\t\"themes\",\n\t\"tools\",\n\t\"bin\",\n\t\"prompts\",\n\t\"sessions\",\n\t\"extensions\",\n\t\"skills\",\n] as const;\n\n/**\n * Ensure the agent dir and standard subdirs exist (mode 0o700 for privacy).\n * Safe to call on every startup; no-op when dirs already exist.\n */\nexport function ensureAgentDir(agentDir: string = getAgentDir()): void {\n\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\tfor (const sub of AGENT_SUBDIRS) {\n\t\tmkdirSync(join(agentDir, sub), { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Seed a default config file from the bundled defaults dir if it does not yet\n * exist. Never overwrites an existing user file. Returns the destination path\n * when a seed was written, undefined when the file already existed or the\n * bundled source is missing.\n */\nexport function seedDefaultConfigFile(\n\tdestPath: string,\n\tbundledName: string,\n\tbundledDefaultsDir: string = getBundledDefaultsDir(),\n): string | undefined {\n\tif (existsSync(destPath)) return undefined;\n\tconst source = join(bundledDefaultsDir, bundledName);\n\tif (!existsSync(source)) return undefined;\n\tmkdirSync(dirname(destPath), { recursive: true, mode: 0o700 });\n\tcopyFileSync(source, destPath);\n\ttry {\n\t\tchmodSync(destPath, 0o600);\n\t} catch {\n\t\t// chmod is best-effort (no-op on platforms that don't support it).\n\t}\n\treturn destPath;\n}\n\n/**\n * Recursively copy a bundled directory tree into the user's agent dir, skipping\n * any file that already exists (user edits survive). Never overwrites. Used to\n * seed bundled skills/themes so the user can inspect and edit them.\n * Returns the list of destination paths that were written.\n */\nfunction seedBundledDir(\n\tdestDir: string,\n\tbundledDir: string,\n): string[] {\n\tif (!existsSync(bundledDir)) return [];\n\tmkdirSync(destDir, { recursive: true, mode: 0o700 });\n\tconst written: string[] = [];\n\tconst stack: Array<{ src: string; dst: string }> = [{ src: bundledDir, dst: destDir }];\n\twhile (stack.length > 0) {\n\t\tconst { src, dst } = stack.pop()!;\n\t\tmkdirSync(dst, { recursive: true, mode: 0o700 });\n\t\tfor (const entry of readdirSync(src, { withFileTypes: true })) {\n\t\t\tif (entry.name === \".DS_Store\" || entry.name === \"node_modules\") continue;\n\t\t\tconst srcPath = join(src, entry.name);\n\t\t\tconst dstPath = join(dst, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (!existsSync(dstPath)) mkdirSync(dstPath, { recursive: true, mode: 0o700 });\n\t\t\t\tstack.push({ src: srcPath, dst: dstPath });\n\t\t\t} else if (entry.isFile() || entry.isSymbolicLink()) {\n\t\t\t\tif (existsSync(dstPath)) continue;\n\t\t\t\tcopyFileSync(srcPath, dstPath);\n\t\t\t\ttry {\n\t\t\t\t\tchmodSync(dstPath, 0o600);\n\t\t\t\t} catch {\n\t\t\t\t\t// best-effort\n\t\t\t\t}\n\t\t\t\twritten.push(dstPath);\n\t\t\t}\n\t\t}\n\t}\n\treturn written;\n}\n\nfunction removeIdenticalBundledFiles(destDir: string, bundledDir: string): string[] {\n\tif (!existsSync(destDir) || !existsSync(bundledDir)) return [];\n\tconst removed: string[] = [];\n\tconst stack: Array<{ src: string; dst: string }> = [{ src: bundledDir, dst: destDir }];\n\twhile (stack.length > 0) {\n\t\tconst { src, dst } = stack.pop()!;\n\t\tif (!existsSync(dst)) continue;\n\t\tfor (const entry of readdirSync(src, { withFileTypes: true })) {\n\t\t\tif (entry.name === \".DS_Store\" || entry.name === \"node_modules\") continue;\n\t\t\tconst srcPath = join(src, entry.name);\n\t\t\tconst dstPath = join(dst, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tstack.push({ src: srcPath, dst: dstPath });\n\t\t\t} else if (existsSync(dstPath) && readFileSync(srcPath).equals(readFileSync(dstPath))) {\n\t\t\t\tunlinkSync(dstPath);\n\t\t\t\tremoved.push(dstPath);\n\t\t\t}\n\t\t}\n\t}\n\treturn removed;\n}\n\n/**\n * Bundled extensions load directly from the installed package. Do not copy them\n * into the user's agent dir, otherwise startup discovers both copies and tool\n * registration conflicts with itself.\n * Remove files copied by older releases only when they are byte-identical to\n * bundled files, so user-edited extensions survive.\n */\nexport function seedDefaultExtensions(\n\tagentDir: string,\n\tbundledExtensionsDir: string = getBundledExtensionsDir(),\n): string[] {\n\tremoveIdenticalBundledFiles(join(agentDir, \"extensions\"), bundledExtensionsDir);\n\treturn [];\n}\n\n/**\n * Seed bundled built-in skills into the user's agent dir/skills.\n * Skips existing files (user edits survive). Never overwrites.\n * Returns the list of destination paths that were written.\n */\nexport function seedDefaultSkills(\n\tagentDir: string,\n\tbundledSkillsDir: string = getBundledSkillsDir(),\n): string[] {\n\treturn seedBundledDir(join(agentDir, \"skills\"), bundledSkillsDir);\n}\n\n/**\n * Seed bundled built-in themes into the user's agent dir/themes.\n * Skips existing files (user edits survive). Never overwrites.\n * Returns the list of destination paths that were written.\n */\nexport function seedDefaultThemes(\n\tagentDir: string,\n\tbundledThemesDir: string = getBundledThemesDir(),\n): string[] {\n\treturn seedBundledDir(join(agentDir, \"themes\"), bundledThemesDir);\n}\n\n/**\n * Run full first-run bootstrap for the agent dir: ensure directories and seed\n * settings.json from bundled defaults. Idempotent — safe on every startup.\n * Bundled models load package-locally; copying them would expose internal\n * providers as user config. Bundled extensions also stay package-local.\n */\nexport function bootstrapAgentDir(agentDir: string = getAgentDir()): void {\n\tensureAgentDir(agentDir);\n\tseedDefaultConfigFile(join(agentDir, \"settings.json\"), \"settings.json\");\n\tseedDefaultExtensions(agentDir);\n\tseedDefaultSkills(agentDir);\n\tseedDefaultThemes(agentDir);\n}\n"]}
package/dist/config.js CHANGED
@@ -475,9 +475,9 @@ export function getShareViewerUrl(gistId) {
475
475
  return `${baseUrl}#${gistId}`;
476
476
  }
477
477
  // =============================================================================
478
- // User Config Paths (~/.pi/agent/*)
478
+ // User Config Paths (~/<configured-dir>/agent/*)
479
479
  // =============================================================================
480
- /** Get the agent config directory (e.g., ~/.pi/agent/) */
480
+ /** Get the agent config directory (e.g., ~/.selesai/agent/) */
481
481
  export function getAgentDir() {
482
482
  const envDir = process.env[ENV_AGENT_DIR];
483
483
  if (envDir) {