@code-yeongyu/senpi 2026.5.29 → 2026.6.3

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 (310) hide show
  1. package/CHANGELOG.md +131 -1
  2. package/README.md +12 -2
  3. package/dist/cli/args.d.ts +3 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +28 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +9 -1
  9. package/dist/config.js.map +1 -1
  10. package/dist/core/agent-session-services.d.ts +1 -0
  11. package/dist/core/agent-session-services.d.ts.map +1 -1
  12. package/dist/core/agent-session-services.js +1 -0
  13. package/dist/core/agent-session-services.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +9 -2
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +36 -13
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/compaction/branch-summarization.d.ts +3 -1
  19. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  20. package/dist/core/compaction/branch-summarization.js +9 -3
  21. package/dist/core/compaction/branch-summarization.js.map +1 -1
  22. package/dist/core/extensions/index.d.ts +1 -1
  23. package/dist/core/extensions/index.d.ts.map +1 -1
  24. package/dist/core/extensions/index.js.map +1 -1
  25. package/dist/core/extensions/runner.d.ts +5 -3
  26. package/dist/core/extensions/runner.d.ts.map +1 -1
  27. package/dist/core/extensions/runner.js +21 -3
  28. package/dist/core/extensions/runner.js.map +1 -1
  29. package/dist/core/extensions/types.d.ts +14 -6
  30. package/dist/core/extensions/types.d.ts.map +1 -1
  31. package/dist/core/extensions/types.js.map +1 -1
  32. package/dist/core/footer-data-provider.d.ts +2 -0
  33. package/dist/core/footer-data-provider.d.ts.map +1 -1
  34. package/dist/core/footer-data-provider.js +29 -1
  35. package/dist/core/footer-data-provider.js.map +1 -1
  36. package/dist/core/model-registry.d.ts.map +1 -1
  37. package/dist/core/model-registry.js +82 -21
  38. package/dist/core/model-registry.js.map +1 -1
  39. package/dist/core/model-resolver.d.ts.map +1 -1
  40. package/dist/core/model-resolver.js +2 -1
  41. package/dist/core/model-resolver.js.map +1 -1
  42. package/dist/core/provider-attribution.d.ts +4 -0
  43. package/dist/core/provider-attribution.d.ts.map +1 -0
  44. package/dist/core/provider-attribution.js +73 -0
  45. package/dist/core/provider-attribution.js.map +1 -0
  46. package/dist/core/provider-display-names.d.ts.map +1 -1
  47. package/dist/core/provider-display-names.js +1 -0
  48. package/dist/core/provider-display-names.js.map +1 -1
  49. package/dist/core/resolve-config-value.d.ts +9 -1
  50. package/dist/core/resolve-config-value.d.ts.map +1 -1
  51. package/dist/core/resolve-config-value.js +134 -11
  52. package/dist/core/resolve-config-value.js.map +1 -1
  53. package/dist/core/sdk.d.ts +2 -0
  54. package/dist/core/sdk.d.ts.map +1 -1
  55. package/dist/core/sdk.js +18 -40
  56. package/dist/core/sdk.js.map +1 -1
  57. package/dist/core/session-manager.d.ts +6 -7
  58. package/dist/core/session-manager.d.ts.map +1 -1
  59. package/dist/core/session-manager.js +167 -96
  60. package/dist/core/session-manager.js.map +1 -1
  61. package/dist/core/settings-manager.d.ts +3 -1
  62. package/dist/core/settings-manager.d.ts.map +1 -1
  63. package/dist/core/settings-manager.js +15 -11
  64. package/dist/core/settings-manager.js.map +1 -1
  65. package/dist/core/system-prompt.d.ts.map +1 -1
  66. package/dist/core/system-prompt.js +0 -3
  67. package/dist/core/system-prompt.js.map +1 -1
  68. package/dist/core/thinking-levels.d.ts.map +1 -1
  69. package/dist/core/thinking-levels.js +6 -2
  70. package/dist/core/thinking-levels.js.map +1 -1
  71. package/dist/core/tools/edit.d.ts.map +1 -1
  72. package/dist/core/tools/edit.js +7 -10
  73. package/dist/core/tools/edit.js.map +1 -1
  74. package/dist/core/tools/find.d.ts.map +1 -1
  75. package/dist/core/tools/find.js.map +1 -1
  76. package/dist/core/tools/grep.d.ts.map +1 -1
  77. package/dist/core/tools/grep.js.map +1 -1
  78. package/dist/core/tools/ls.d.ts.map +1 -1
  79. package/dist/core/tools/ls.js +5 -7
  80. package/dist/core/tools/ls.js.map +1 -1
  81. package/dist/core/tools/read.d.ts.map +1 -1
  82. package/dist/core/tools/read.js +6 -7
  83. package/dist/core/tools/read.js.map +1 -1
  84. package/dist/core/tools/render-utils.d.ts +5 -2
  85. package/dist/core/tools/render-utils.d.ts.map +1 -1
  86. package/dist/core/tools/render-utils.js +17 -1
  87. package/dist/core/tools/render-utils.js.map +1 -1
  88. package/dist/core/tools/write.d.ts.map +1 -1
  89. package/dist/core/tools/write.js +5 -6
  90. package/dist/core/tools/write.js.map +1 -1
  91. package/dist/index.d.ts +2 -0
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +2 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/main.d.ts.map +1 -1
  96. package/dist/main.js +76 -16
  97. package/dist/main.js.map +1 -1
  98. package/dist/migrations.d.ts.map +1 -1
  99. package/dist/migrations.js +118 -1
  100. package/dist/migrations.js.map +1 -1
  101. package/dist/modes/interactive/components/login-dialog.d.ts +1 -3
  102. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  103. package/dist/modes/interactive/components/login-dialog.js +2 -4
  104. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  105. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  106. package/dist/modes/interactive/components/tool-execution.js +25 -1
  107. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  108. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  109. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  110. package/dist/modes/interactive/interactive-mode.js +64 -6
  111. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  112. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  113. package/dist/modes/interactive/theme/theme.js +10 -0
  114. package/dist/modes/interactive/theme/theme.js.map +1 -1
  115. package/dist/modes/print-mode.d.ts.map +1 -1
  116. package/dist/modes/print-mode.js +1 -0
  117. package/dist/modes/print-mode.js.map +1 -1
  118. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  119. package/dist/modes/rpc/rpc-mode.js +4 -1
  120. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  121. package/dist/modes/rpc/rpc-types.d.ts +1 -0
  122. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  123. package/dist/modes/rpc/rpc-types.js.map +1 -1
  124. package/dist/utils/deprecation.d.ts +4 -0
  125. package/dist/utils/deprecation.d.ts.map +1 -0
  126. package/dist/utils/deprecation.js +13 -0
  127. package/dist/utils/deprecation.js.map +1 -0
  128. package/dist/utils/json.d.ts +3 -0
  129. package/dist/utils/json.d.ts.map +1 -0
  130. package/dist/utils/json.js +7 -0
  131. package/dist/utils/json.js.map +1 -0
  132. package/docs/custom-provider.md +13 -10
  133. package/docs/extensions.md +47 -17
  134. package/docs/models.md +25 -12
  135. package/docs/providers.md +15 -5
  136. package/docs/quickstart.md +1 -0
  137. package/docs/rpc.md +3 -2
  138. package/docs/sdk.md +6 -0
  139. package/docs/session-format.md +1 -1
  140. package/docs/sessions.md +8 -0
  141. package/docs/settings.md +4 -2
  142. package/docs/terminal-setup.md +2 -0
  143. package/docs/tui.md +12 -3
  144. package/docs/usage.md +10 -1
  145. package/examples/extensions/README.md +1 -0
  146. package/examples/extensions/custom-header.ts +1 -1
  147. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  148. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  149. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  150. package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  151. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  152. package/examples/extensions/doom-overlay/index.ts +1 -1
  153. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  154. package/examples/extensions/handoff.ts +1 -1
  155. package/examples/extensions/input-transform-streaming.ts +39 -0
  156. package/examples/extensions/interactive-shell.ts +1 -1
  157. package/examples/extensions/overlay-qa-tests.ts +152 -81
  158. package/examples/extensions/qna.ts +1 -1
  159. package/examples/extensions/question.ts +1 -1
  160. package/examples/extensions/questionnaire.ts +1 -1
  161. package/examples/extensions/sandbox/package-lock.json +2 -2
  162. package/examples/extensions/sandbox/package.json +1 -1
  163. package/examples/extensions/snake.ts +1 -1
  164. package/examples/extensions/space-invaders.ts +1 -1
  165. package/examples/extensions/summarize.ts +1 -1
  166. package/examples/extensions/tic-tac-toe.ts +1 -1
  167. package/examples/extensions/todo.ts +1 -1
  168. package/examples/extensions/tools.ts +5 -0
  169. package/examples/extensions/with-deps/package-lock.json +2 -2
  170. package/examples/extensions/with-deps/package.json +1 -1
  171. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +1 -0
  172. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  173. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +15 -0
  174. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  175. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts +5 -2
  176. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  177. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +81 -18
  178. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  179. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  180. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +1 -0
  181. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js.map +1 -1
  182. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
  183. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +1 -0
  184. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
  185. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts +1 -0
  186. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts.map +1 -1
  187. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +14 -1
  188. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js.map +1 -1
  189. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +22 -8
  190. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  191. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
  192. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  193. package/node_modules/@earendil-works/pi-ai/README.md +5 -3
  194. package/node_modules/@earendil-works/pi-ai/dist/cli.js +0 -0
  195. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  196. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -0
  197. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
  198. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -0
  199. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  200. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -0
  201. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  202. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +2 -2
  203. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  204. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +1294 -412
  205. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  206. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +1278 -652
  207. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  208. package/node_modules/@earendil-works/pi-ai/dist/models.js +9 -4
  209. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts +1 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  212. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +89 -21
  213. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  214. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  215. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +27 -14
  216. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  217. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  218. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +5 -9
  219. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  220. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
  221. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +1 -1
  222. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/providers/google.d.ts.map +1 -1
  224. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +5 -3
  225. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.d.ts.map +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +2 -3
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js.map +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.d.ts.map +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js +2 -3
  231. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +118 -52
  234. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  235. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  236. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +27 -17
  237. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
  238. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts +1 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +5 -1
  241. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  242. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  243. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +5 -9
  244. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
  245. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  246. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +1 -0
  247. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
  248. package/node_modules/@earendil-works/pi-ai/dist/providers/transform-messages.d.ts +7 -0
  249. package/node_modules/@earendil-works/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/providers/transform-messages.js +8 -4
  251. package/node_modules/@earendil-works/pi-ai/dist/providers/transform-messages.js.map +1 -1
  252. package/node_modules/@earendil-works/pi-ai/dist/stream.d.ts.map +1 -1
  253. package/node_modules/@earendil-works/pi-ai/dist/stream.js +18 -4
  254. package/node_modules/@earendil-works/pi-ai/dist/stream.js.map +1 -1
  255. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +21 -5
  256. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  258. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts +6 -0
  259. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts.map +1 -0
  260. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js +34 -0
  261. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js.map +1 -0
  262. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +9 -7
  263. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +8 -7
  265. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  267. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +1 -1
  270. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
  271. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -1
  272. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +10 -1
  274. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +179 -79
  276. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +1 -1
  277. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  278. package/node_modules/@earendil-works/pi-tui/README.md +15 -3
  279. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  280. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +9 -53
  281. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  282. package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +1 -1
  283. package/node_modules/@earendil-works/pi-tui/dist/components/input.js +6 -54
  284. package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +1 -1
  285. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  286. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  287. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  288. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +1 -1
  289. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
  290. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +34 -7
  291. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
  292. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +33 -10
  293. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  294. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +173 -39
  295. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  296. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +18 -3
  297. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  298. package/node_modules/@earendil-works/pi-tui/dist/tui.js +166 -22
  299. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  300. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +1 -0
  301. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
  302. package/node_modules/@earendil-works/pi-tui/dist/utils.js +11 -3
  303. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  304. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +25 -0
  305. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +1 -0
  306. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +96 -0
  307. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +1 -0
  308. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  309. package/npm-shrinkwrap.json +56 -56
  310. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-config-value.js","sourceRoot":"","sources":["../../src/core/resolve-config-value.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolve configuration values that may be shell commands, environment variables, or literals.\n * Used by auth-storage.ts and model-registry.ts.\n */\n\nimport { execSync, spawnSync } from \"child_process\";\nimport { getShellConfig } from \"../utils/shell.ts\";\n\n// Cache for shell command results (persists for process lifetime)\nconst commandResultCache = new Map<string, string | undefined>();\n\n/**\n * Resolve a config value (API key, header value, etc.) to an actual value.\n * - If starts with \"!\", executes the rest as a shell command and uses stdout (cached)\n * - Otherwise checks environment variable first, then treats as literal (not cached)\n */\nexport function resolveConfigValue(config: string): string | undefined {\n\tif (config.startsWith(\"!\")) {\n\t\treturn executeCommand(config);\n\t}\n\tconst envValue = process.env[config];\n\treturn envValue || config;\n}\n\nfunction executeWithConfiguredShell(command: string): { executed: boolean; value: string | undefined } {\n\ttry {\n\t\tconst { shell, args } = getShellConfig();\n\t\tconst result = spawnSync(shell, [...args, command], {\n\t\t\tencoding: \"utf-8\",\n\t\t\ttimeout: 10000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tconst error = result.error as NodeJS.ErrnoException;\n\t\t\tif (error.code === \"ENOENT\") {\n\t\t\t\treturn { executed: false, value: undefined };\n\t\t\t}\n\t\t\treturn { executed: true, value: undefined };\n\t\t}\n\n\t\tif (result.status !== 0) {\n\t\t\treturn { executed: true, value: undefined };\n\t\t}\n\n\t\tconst value = (result.stdout ?? \"\").trim();\n\t\treturn { executed: true, value: value || undefined };\n\t} catch {\n\t\treturn { executed: false, value: undefined };\n\t}\n}\n\nfunction executeWithDefaultShell(command: string): string | undefined {\n\ttry {\n\t\tconst output = execSync(command, {\n\t\t\tencoding: \"utf-8\",\n\t\t\ttimeout: 10000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t});\n\t\treturn output.trim() || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction executeCommandUncached(commandConfig: string): string | undefined {\n\tconst command = commandConfig.slice(1);\n\treturn process.platform === \"win32\"\n\t\t? (() => {\n\t\t\t\tconst configuredResult = executeWithConfiguredShell(command);\n\t\t\t\treturn configuredResult.executed ? configuredResult.value : executeWithDefaultShell(command);\n\t\t\t})()\n\t\t: executeWithDefaultShell(command);\n}\n\nfunction executeCommand(commandConfig: string): string | undefined {\n\tif (commandResultCache.has(commandConfig)) {\n\t\treturn commandResultCache.get(commandConfig);\n\t}\n\n\tconst result = executeCommandUncached(commandConfig);\n\tcommandResultCache.set(commandConfig, result);\n\treturn result;\n}\n\n/**\n * Resolve all header values using the same resolution logic as API keys.\n */\nexport function resolveConfigValueUncached(config: string): string | undefined {\n\tif (config.startsWith(\"!\")) {\n\t\treturn executeCommandUncached(config);\n\t}\n\tconst envValue = process.env[config];\n\treturn envValue || config;\n}\n\nexport function resolveConfigValueOrThrow(config: string, description: string): string {\n\tconst resolvedValue = resolveConfigValueUncached(config);\n\tif (resolvedValue !== undefined) {\n\t\treturn resolvedValue;\n\t}\n\n\tif (config.startsWith(\"!\")) {\n\t\tthrow new Error(`Failed to resolve ${description} from shell command: ${config.slice(1)}`);\n\t}\n\n\tthrow new Error(`Failed to resolve ${description}`);\n}\n\n/**\n * Resolve all header values using the same resolution logic as API keys.\n */\nexport function resolveHeaders(headers: Record<string, string> | undefined): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst resolved: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tconst resolvedValue = resolveConfigValue(value);\n\t\tif (resolvedValue) {\n\t\t\tresolved[key] = resolvedValue;\n\t\t}\n\t}\n\treturn Object.keys(resolved).length > 0 ? resolved : undefined;\n}\n\nexport function resolveHeadersOrThrow(\n\theaders: Record<string, string> | undefined,\n\tdescription: string,\n): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst resolved: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tresolved[key] = resolveConfigValueOrThrow(value, `${description} header \"${key}\"`);\n\t}\n\treturn Object.keys(resolved).length > 0 ? resolved : undefined;\n}\n\n/** Clear the config value command cache. Exported for testing. */\nexport function clearConfigValueCache(): void {\n\tcommandResultCache.clear();\n}\n"]}
1
+ {"version":3,"file":"resolve-config-value.js","sourceRoot":"","sources":["../../src/core/resolve-config-value.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolve configuration values that may be shell commands, environment variables, or literals.\n * Used by auth-storage.ts and model-registry.ts.\n */\n\nimport { execSync, spawnSync } from \"child_process\";\nimport { getShellConfig } from \"../utils/shell.ts\";\n\n// Cache for shell command results (persists for process lifetime)\nconst commandResultCache = new Map<string, string | undefined>();\nconst ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst ENV_VAR_NAME_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*/;\nconst LEGACY_ENV_VAR_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;\n\ntype TemplatePart = { type: \"literal\"; value: string } | { type: \"env\"; name: string };\n\ntype ConfigValueReference = { type: \"command\"; config: string } | { type: \"template\"; parts: TemplatePart[] };\n\nfunction appendLiteral(parts: TemplatePart[], value: string): void {\n\tif (!value) return;\n\tconst previousPart = parts[parts.length - 1];\n\tif (previousPart?.type === \"literal\") {\n\t\tpreviousPart.value += value;\n\t\treturn;\n\t}\n\tparts.push({ type: \"literal\", value });\n}\n\nfunction parseConfigValueTemplate(config: string): TemplatePart[] {\n\tconst parts: TemplatePart[] = [];\n\tlet index = 0;\n\n\twhile (index < config.length) {\n\t\tconst dollarIndex = config.indexOf(\"$\", index);\n\t\tif (dollarIndex < 0) {\n\t\t\tappendLiteral(parts, config.slice(index));\n\t\t\tbreak;\n\t\t}\n\n\t\tappendLiteral(parts, config.slice(index, dollarIndex));\n\t\tconst nextChar = config[dollarIndex + 1];\n\n\t\tif (nextChar === \"$\" || nextChar === \"!\") {\n\t\t\tappendLiteral(parts, nextChar);\n\t\t\tindex = dollarIndex + 2;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (nextChar === \"{\") {\n\t\t\tconst endIndex = config.indexOf(\"}\", dollarIndex + 2);\n\t\t\tif (endIndex < 0) {\n\t\t\t\tappendLiteral(parts, \"$\");\n\t\t\t\tindex = dollarIndex + 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst name = config.slice(dollarIndex + 2, endIndex);\n\t\t\tif (ENV_VAR_NAME_RE.test(name)) {\n\t\t\t\tparts.push({ type: \"env\", name });\n\t\t\t} else {\n\t\t\t\tappendLiteral(parts, config.slice(dollarIndex, endIndex + 1));\n\t\t\t}\n\t\t\tindex = endIndex + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst match = config.slice(dollarIndex + 1).match(ENV_VAR_NAME_PREFIX_RE);\n\t\tif (match) {\n\t\t\tparts.push({ type: \"env\", name: match[0] });\n\t\t\tindex = dollarIndex + 1 + match[0].length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tappendLiteral(parts, \"$\");\n\t\tindex = dollarIndex + 1;\n\t}\n\n\treturn parts;\n}\n\nfunction parseConfigValueReference(config: string): ConfigValueReference {\n\tif (config.startsWith(\"!\")) {\n\t\treturn { type: \"command\", config };\n\t}\n\n\treturn { type: \"template\", parts: parseConfigValueTemplate(config) };\n}\n\nfunction resolveEnvConfigValue(name: string): string | undefined {\n\treturn process.env[name] || undefined;\n}\n\nfunction getTemplateEnvVarNames(parts: TemplatePart[]): string[] {\n\tconst names: string[] = [];\n\tfor (const part of parts) {\n\t\tif (part.type !== \"env\" || names.includes(part.name)) continue;\n\t\tnames.push(part.name);\n\t}\n\treturn names;\n}\n\nfunction resolveTemplate(parts: TemplatePart[]): string | undefined {\n\tlet resolved = \"\";\n\tfor (const part of parts) {\n\t\tif (part.type === \"literal\") {\n\t\t\tresolved += part.value;\n\t\t\tcontinue;\n\t\t}\n\t\tconst envValue = resolveEnvConfigValue(part.name);\n\t\tif (envValue === undefined) return undefined;\n\t\tresolved += envValue;\n\t}\n\treturn resolved;\n}\n\nexport function getConfigValueEnvVarName(config: string): string | undefined {\n\tconst reference = parseConfigValueReference(config);\n\tif (reference.type !== \"template\") return undefined;\n\treturn reference.parts.length === 1 && reference.parts[0]?.type === \"env\" ? reference.parts[0].name : undefined;\n}\n\nexport function getConfigValueEnvVarNames(config: string): string[] {\n\tconst reference = parseConfigValueReference(config);\n\treturn reference.type === \"template\" ? getTemplateEnvVarNames(reference.parts) : [];\n}\n\nexport function getMissingConfigValueEnvVarNames(config: string): string[] {\n\treturn getConfigValueEnvVarNames(config).filter((name) => resolveEnvConfigValue(name) === undefined);\n}\n\nexport function isCommandConfigValue(config: string): boolean {\n\treturn parseConfigValueReference(config).type === \"command\";\n}\n\nexport function isConfigValueConfigured(config: string): boolean {\n\treturn getMissingConfigValueEnvVarNames(config).length === 0;\n}\n\nexport function isLegacyEnvVarNameConfigValue(config: string): boolean {\n\treturn LEGACY_ENV_VAR_NAME_RE.test(config);\n}\n\n/**\n * Resolve a config value (API key, header value, etc.) to an actual value.\n * - If starts with \"!\", executes the rest as a shell command and uses stdout (cached)\n * - Interpolates \"$ENV_VAR\" or \"${ENV_VAR}\" references with the named environment variable\n * - In non-command values, \"$$\" escapes a literal \"$\" and \"$!\" escapes a literal \"!\"\n * - Otherwise treats the value as a literal\n */\nexport function resolveConfigValue(config: string): string | undefined {\n\tconst reference = parseConfigValueReference(config);\n\tif (reference.type === \"command\") {\n\t\treturn executeCommand(reference.config);\n\t}\n\treturn resolveTemplate(reference.parts);\n}\n\nfunction executeWithConfiguredShell(command: string): { executed: boolean; value: string | undefined } {\n\ttry {\n\t\tconst { shell, args } = getShellConfig();\n\t\tconst result = spawnSync(shell, [...args, command], {\n\t\t\tencoding: \"utf-8\",\n\t\t\ttimeout: 10000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tconst error = result.error as NodeJS.ErrnoException;\n\t\t\tif (error.code === \"ENOENT\") {\n\t\t\t\treturn { executed: false, value: undefined };\n\t\t\t}\n\t\t\treturn { executed: true, value: undefined };\n\t\t}\n\n\t\tif (result.status !== 0) {\n\t\t\treturn { executed: true, value: undefined };\n\t\t}\n\n\t\tconst value = (result.stdout ?? \"\").trim();\n\t\treturn { executed: true, value: value || undefined };\n\t} catch {\n\t\treturn { executed: false, value: undefined };\n\t}\n}\n\nfunction executeWithDefaultShell(command: string): string | undefined {\n\ttry {\n\t\tconst output = execSync(command, {\n\t\t\tencoding: \"utf-8\",\n\t\t\ttimeout: 10000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t});\n\t\treturn output.trim() || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction executeCommandUncached(commandConfig: string): string | undefined {\n\tconst command = commandConfig.slice(1);\n\treturn process.platform === \"win32\"\n\t\t? (() => {\n\t\t\t\tconst configuredResult = executeWithConfiguredShell(command);\n\t\t\t\treturn configuredResult.executed ? configuredResult.value : executeWithDefaultShell(command);\n\t\t\t})()\n\t\t: executeWithDefaultShell(command);\n}\n\nfunction executeCommand(commandConfig: string): string | undefined {\n\tif (commandResultCache.has(commandConfig)) {\n\t\treturn commandResultCache.get(commandConfig);\n\t}\n\n\tconst result = executeCommandUncached(commandConfig);\n\tcommandResultCache.set(commandConfig, result);\n\treturn result;\n}\n\n/**\n * Resolve all header values using the same resolution logic as API keys.\n */\nexport function resolveConfigValueUncached(config: string): string | undefined {\n\tconst reference = parseConfigValueReference(config);\n\tif (reference.type === \"command\") {\n\t\treturn executeCommandUncached(reference.config);\n\t}\n\treturn resolveTemplate(reference.parts);\n}\n\nexport function resolveConfigValueOrThrow(config: string, description: string): string {\n\tconst resolvedValue = resolveConfigValueUncached(config);\n\tif (resolvedValue !== undefined) {\n\t\treturn resolvedValue;\n\t}\n\n\tconst reference = parseConfigValueReference(config);\n\tif (reference.type === \"command\") {\n\t\tthrow new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);\n\t}\n\n\tif (reference.type === \"template\") {\n\t\tconst missingEnvVars = getMissingConfigValueEnvVarNames(config);\n\t\tif (missingEnvVars.length === 1) {\n\t\t\tthrow new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);\n\t\t}\n\t\tif (missingEnvVars.length > 1) {\n\t\t\tthrow new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(\", \")}`);\n\t\t}\n\t}\n\n\tthrow new Error(`Failed to resolve ${description}`);\n}\n\n/**\n * Resolve all header values using the same resolution logic as API keys.\n */\nexport function resolveHeaders(headers: Record<string, string> | undefined): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst resolved: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tconst resolvedValue = resolveConfigValue(value);\n\t\tif (resolvedValue) {\n\t\t\tresolved[key] = resolvedValue;\n\t\t}\n\t}\n\treturn Object.keys(resolved).length > 0 ? resolved : undefined;\n}\n\nexport function resolveHeadersOrThrow(\n\theaders: Record<string, string> | undefined,\n\tdescription: string,\n): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst resolved: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tresolved[key] = resolveConfigValueOrThrow(value, `${description} header \"${key}\"`);\n\t}\n\treturn Object.keys(resolved).length > 0 ? resolved : undefined;\n}\n\n/** Clear the config value command cache. Exported for testing. */\nexport function clearConfigValueCache(): void {\n\tcommandResultCache.clear();\n}\n"]}
@@ -50,6 +50,8 @@ export interface CreateAgentSessionOptions {
50
50
  * When provided, only the listed tool names are enabled.
51
51
  */
52
52
  tools?: string[];
53
+ /** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */
54
+ excludeTools?: string[];
53
55
  /** Custom tools to register (in addition to built-in tools). */
54
56
  customTools?: ToolDefinition[];
55
57
  /** Resource loader. When omitted, DefaultResourceLoader is used. */
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai\";\nimport { APP_NAME, getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ServiceTier } from \"./extensions/builtin/service-tier.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel, getModelNarrowingPatterns, resolveModelScope } from \"./model-resolver.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { isInstallTelemetryEnabled } from \"./telemetry.ts\";\nimport { getSupportedThinkingLevels } from \"./thinking-levels.ts\";\nimport { time } from \"./timings.ts\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.senpi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Global model narrowing for selectors and startup model choice */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\t/** Favorite models for Ctrl+P cycling */\n\tfavoriteModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\t// Tool factories (for custom cwd)\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\twithFileMutationQueue,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\nfunction getAttributionHeaders(\n\tmodel: Model<any>,\n\tsettingsManager: SettingsManager,\n\tsessionId?: string,\n): Record<string, string> | undefined {\n\tif (\n\t\tsessionId &&\n\t\t(model.provider === \"opencode\" || model.provider === \"opencode-go\" || model.baseUrl.includes(\"opencode.ai\"))\n\t) {\n\t\treturn { \"x-opencode-session\": sessionId, \"x-opencode-client\": \"pi\" };\n\t}\n\n\tif (!isInstallTelemetryEnabled(settingsManager)) {\n\t\treturn undefined;\n\t}\n\n\tif (model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\")) {\n\t\treturn {\n\t\t\t\"HTTP-Referer\": \"https://pi.dev\",\n\t\t\t\"X-OpenRouter-Title\": APP_NAME,\n\t\t\t\"X-OpenRouter-Categories\": \"cli-agent\",\n\t\t};\n\t}\n\n\tif (\n\t\tmodel.provider === \"cloudflare-workers-ai\" ||\n\t\tmodel.provider === \"cloudflare-ai-gateway\" ||\n\t\tmodel.baseUrl.includes(\"api.cloudflare.com\") ||\n\t\tmodel.baseUrl.includes(\"gateway.ai.cloudflare.com\")\n\t) {\n\t\treturn {\n\t\t\t\"User-Agent\": `${APP_NAME}-coding-agent`,\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst scopedModels =\n\t\toptions.scopedModels ??\n\t\t(await resolveModelScope(\n\t\t\tgetModelNarrowingPatterns({\n\t\t\t\tlegacyEnabledPatterns: settingsManager.getEnabledModels(),\n\t\t\t}),\n\t\t\tmodelRegistry,\n\t\t));\n\tconst favoriteModels =\n\t\toptions.favoriteModels ?? (await resolveModelScope(settingsManager.getFavoriteModels() ?? [], modelRegistry));\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels,\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tthinkingLevel = clampThinkingLevelToModel(thinkingLevel, model);\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst initialActiveToolNames: string[] = options.tools\n\t\t? [...options.tools]\n\t\t: options.noTools\n\t\t\t? []\n\t\t\t: defaultActiveToolNames;\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;\n\t\t\tconst requestRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst attributionHeaders = getAttributionHeaders(model, settingsManager, options?.sessionId);\n\t\t\tconst streamOptions = {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\tserviceTier: auth.serviceTier,\n\t\t\t\ttimeoutMs: options?.timeoutMs ?? requestRetrySettings.timeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? requestRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? requestRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders:\n\t\t\t\t\tattributionHeaders || auth.headers || options?.headers\n\t\t\t\t\t\t? { ...attributionHeaders, ...auth.headers, ...options?.headers }\n\t\t\t\t\t\t: undefined,\n\t\t\t\textraBody: auth.extraBody || options?.extraBody ? { ...auth.extraBody, ...options?.extraBody } : undefined,\n\t\t\t};\n\t\t\treturn streamSimple(requestModel, context, streamOptions);\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\ttimeoutMs: providerRetrySettings.timeoutMs,\n\t\tmaxRetryDelayMs: providerRetrySettings.maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels,\n\t\tfavoriteModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n\n/**\n * Clamp a requested thinking level to what the resolved model actually exposes.\n *\n * Capability tiers:\n * - Non-reasoning model: everything collapses to \"off\".\n * - Model metadata can disable individual levels via thinkingLevelMap.\n * - No xhigh support: xhigh and max both collapse to \"high\".\n * - xhigh but no max: max collapses to \"xhigh\" (currently GPT-5.2/5.3/5.4).\n * - Native max support: xhigh and max are both preserved (Opus 4.6 / 4.7).\n *\n * This keeps session state aligned with `getAvailableThinkingLevels()` so the\n * UI never claims a tier the provider will silently downgrade at request time.\n */\nexport function clampThinkingLevelToModel(\n\tlevel: ThinkingLevel | undefined,\n\tmodel: Model<Api> | undefined,\n): ThinkingLevel {\n\tif (!model?.reasoning) return \"off\";\n\n\tconst requestedLevel = level ?? \"off\";\n\tconst availableLevels = getSupportedThinkingLevels(model);\n\tif (availableLevels.includes(requestedLevel)) return requestedLevel;\n\n\tconst clampedLevels: ThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"];\n\tconst requestedIndex = clampedLevels.indexOf(requestedLevel === \"max\" ? \"xhigh\" : requestedLevel);\n\tif (requestedIndex === -1) return availableLevels[0] ?? \"off\";\n\n\tfor (let index = requestedIndex; index < clampedLevels.length; index++) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\tfor (let index = requestedIndex - 1; index >= 0; index--) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\treturn availableLevels[0] ?? \"off\";\n}\n"]}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ServiceTier } from \"./extensions/builtin/service-tier.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel, getModelNarrowingPatterns, resolveModelScope } from \"./model-resolver.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { getSupportedThinkingLevels } from \"./thinking-levels.ts\";\nimport { time } from \"./timings.ts\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.senpi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Global model narrowing for selectors and startup model choice */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\t/** Favorite models for Ctrl+P cycling */\n\tfavoriteModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\t// Tool factories (for custom cwd)\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\twithFileMutationQueue,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst scopedModels =\n\t\toptions.scopedModels ??\n\t\t(await resolveModelScope(\n\t\t\tgetModelNarrowingPatterns({\n\t\t\t\tlegacyEnabledPatterns: settingsManager.getEnabledModels(),\n\t\t\t}),\n\t\t\tmodelRegistry,\n\t\t));\n\tconst favoriteModels =\n\t\toptions.favoriteModels ?? (await resolveModelScope(settingsManager.getFavoriteModels() ?? [], modelRegistry));\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels,\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tthinkingLevel = clampThinkingLevelToModel(thinkingLevel, model);\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames: string[] = (\n\t\toptions.tools ? [...options.tools] : options.noTools ? [] : defaultActiveToolNames\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\tconst streamOptions = {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\tserviceTier: auth.serviceTier,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\t\tmodel,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\tauth.headers,\n\t\t\t\t\toptions?.headers,\n\t\t\t\t),\n\t\t\t\textraBody: auth.extraBody || options?.extraBody ? { ...auth.extraBody, ...options?.extraBody } : undefined,\n\t\t\t};\n\t\t\treturn streamSimple(requestModel, context, streamOptions);\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\ttimeoutMs: providerRetrySettings.timeoutMs,\n\t\tmaxRetryDelayMs: providerRetrySettings.maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels,\n\t\tfavoriteModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n\n/**\n * Clamp a requested thinking level to what the resolved model actually exposes.\n *\n * Capability tiers:\n * - Non-reasoning model: everything collapses to \"off\".\n * - Model metadata can disable individual levels via thinkingLevelMap.\n * - No xhigh support: xhigh and max both collapse to \"high\".\n * - xhigh but no max: max collapses to \"xhigh\" (currently GPT-5.2/5.3/5.4).\n * - Native max support: xhigh and max are both preserved (Opus 4.6 / 4.7).\n *\n * This keeps session state aligned with `getAvailableThinkingLevels()` so the\n * UI never claims a tier the provider will silently downgrade at request time.\n */\nexport function clampThinkingLevelToModel(\n\tlevel: ThinkingLevel | undefined,\n\tmodel: Model<Api> | undefined,\n): ThinkingLevel {\n\tif (!model?.reasoning) return \"off\";\n\n\tconst requestedLevel = level ?? \"off\";\n\tconst availableLevels = getSupportedThinkingLevels(model);\n\tif (availableLevels.includes(requestedLevel)) return requestedLevel;\n\n\tconst clampedLevels: ThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"];\n\tconst requestedIndex = clampedLevels.indexOf(requestedLevel === \"max\" ? \"xhigh\" : requestedLevel);\n\tif (requestedIndex === -1) return availableLevels[0] ?? \"off\";\n\n\tfor (let index = requestedIndex; index < clampedLevels.length; index++) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\tfor (let index = requestedIndex - 1; index >= 0; index--) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\treturn availableLevels[0] ?? \"off\";\n}\n"]}
package/dist/core/sdk.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
  import { Agent } from "@earendil-works/pi-agent-core";
3
3
  import { streamSimple } from "@earendil-works/pi-ai";
4
- import { APP_NAME, getAgentDir } from "../config.js";
4
+ import { getAgentDir } from "../config.js";
5
5
  import { resolvePath } from "../utils/paths.js";
6
6
  import { AgentSession } from "./agent-session.js";
7
7
  import { formatNoModelsAvailableMessage } from "./auth-guidance.js";
@@ -10,10 +10,10 @@ import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
10
10
  import { convertToLlm } from "./messages.js";
11
11
  import { ModelRegistry } from "./model-registry.js";
12
12
  import { findInitialModel, getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.js";
13
+ import { mergeProviderAttributionHeaders } from "./provider-attribution.js";
13
14
  import { DefaultResourceLoader } from "./resource-loader.js";
14
15
  import { getDefaultSessionDir, SessionManager } from "./session-manager.js";
15
16
  import { SettingsManager } from "./settings-manager.js";
16
- import { isInstallTelemetryEnabled } from "./telemetry.js";
17
17
  import { getSupportedThinkingLevels } from "./thinking-levels.js";
18
18
  import { time } from "./timings.js";
19
19
  import { createBashTool, createCodingTools, createEditTool, createFindTool, createGrepTool, createLsTool, createReadOnlyTools, createReadTool, createWriteTool, withFileMutationQueue, } from "./tools/index.js";
@@ -26,31 +26,6 @@ createBashTool, createCodingTools, createEditTool, createFindTool, createGrepToo
26
26
  function getDefaultAgentDir() {
27
27
  return getAgentDir();
28
28
  }
29
- function getAttributionHeaders(model, settingsManager, sessionId) {
30
- if (sessionId &&
31
- (model.provider === "opencode" || model.provider === "opencode-go" || model.baseUrl.includes("opencode.ai"))) {
32
- return { "x-opencode-session": sessionId, "x-opencode-client": "pi" };
33
- }
34
- if (!isInstallTelemetryEnabled(settingsManager)) {
35
- return undefined;
36
- }
37
- if (model.provider === "openrouter" || model.baseUrl.includes("openrouter.ai")) {
38
- return {
39
- "HTTP-Referer": "https://pi.dev",
40
- "X-OpenRouter-Title": APP_NAME,
41
- "X-OpenRouter-Categories": "cli-agent",
42
- };
43
- }
44
- if (model.provider === "cloudflare-workers-ai" ||
45
- model.provider === "cloudflare-ai-gateway" ||
46
- model.baseUrl.includes("api.cloudflare.com") ||
47
- model.baseUrl.includes("gateway.ai.cloudflare.com")) {
48
- return {
49
- "User-Agent": `${APP_NAME}-coding-agent`,
50
- };
51
- }
52
- return undefined;
53
- }
54
29
  /**
55
30
  * Create an AgentSession with the specified options.
56
31
  *
@@ -156,11 +131,9 @@ export async function createAgentSession(options = {}) {
156
131
  thinkingLevel = clampThinkingLevelToModel(thinkingLevel, model);
157
132
  const defaultActiveToolNames = ["read", "bash", "edit", "write"];
158
133
  const allowedToolNames = options.tools ?? (options.noTools === "all" ? [] : undefined);
159
- const initialActiveToolNames = options.tools
160
- ? [...options.tools]
161
- : options.noTools
162
- ? []
163
- : defaultActiveToolNames;
134
+ const excludedToolNames = options.excludeTools;
135
+ const excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;
136
+ const initialActiveToolNames = (options.tools ? [...options.tools] : options.noTools ? [] : defaultActiveToolNames).filter((name) => !excludedToolNameSet?.has(name));
164
137
  let agent;
165
138
  // Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)
166
139
  const convertToLlmWithBlockImages = (messages) => {
@@ -208,18 +181,22 @@ export async function createAgentSession(options = {}) {
208
181
  throw new Error(auth.error);
209
182
  }
210
183
  const requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;
211
- const requestRetrySettings = settingsManager.getProviderRetrySettings();
212
- const attributionHeaders = getAttributionHeaders(model, settingsManager, options?.sessionId);
184
+ const providerRetrySettings = settingsManager.getProviderRetrySettings();
185
+ const httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();
186
+ // SDKs treat timeout=0 as 0ms (immediate timeout), not "no timeout".
187
+ // Use max int32 to effectively disable the timeout.
188
+ const effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;
189
+ const timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;
190
+ const websocketConnectTimeoutMs = options?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();
213
191
  const streamOptions = {
214
192
  ...options,
215
193
  apiKey: auth.apiKey,
216
194
  serviceTier: auth.serviceTier,
217
- timeoutMs: options?.timeoutMs ?? requestRetrySettings.timeoutMs,
218
- maxRetries: options?.maxRetries ?? requestRetrySettings.maxRetries,
219
- maxRetryDelayMs: options?.maxRetryDelayMs ?? requestRetrySettings.maxRetryDelayMs,
220
- headers: attributionHeaders || auth.headers || options?.headers
221
- ? { ...attributionHeaders, ...auth.headers, ...options?.headers }
222
- : undefined,
195
+ timeoutMs,
196
+ websocketConnectTimeoutMs,
197
+ maxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,
198
+ maxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,
199
+ headers: mergeProviderAttributionHeaders(model, settingsManager, options?.sessionId, auth.headers, options?.headers),
223
200
  extraBody: auth.extraBody || options?.extraBody ? { ...auth.extraBody, ...options?.extraBody } : undefined,
224
201
  };
225
202
  return streamSimple(requestModel, context, streamOptions);
@@ -282,6 +259,7 @@ export async function createAgentSession(options = {}) {
282
259
  modelRegistry,
283
260
  initialActiveToolNames,
284
261
  allowedToolNames,
262
+ excludedToolNames,
285
263
  extensionRunnerRef,
286
264
  sessionStartEvent: options.sessionStartEvent,
287
265
  });
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai\";\nimport { APP_NAME, getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ServiceTier } from \"./extensions/builtin/service-tier.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel, getModelNarrowingPatterns, resolveModelScope } from \"./model-resolver.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { isInstallTelemetryEnabled } from \"./telemetry.ts\";\nimport { getSupportedThinkingLevels } from \"./thinking-levels.ts\";\nimport { time } from \"./timings.ts\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.senpi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Global model narrowing for selectors and startup model choice */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\t/** Favorite models for Ctrl+P cycling */\n\tfavoriteModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\t// Tool factories (for custom cwd)\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\twithFileMutationQueue,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\nfunction getAttributionHeaders(\n\tmodel: Model<any>,\n\tsettingsManager: SettingsManager,\n\tsessionId?: string,\n): Record<string, string> | undefined {\n\tif (\n\t\tsessionId &&\n\t\t(model.provider === \"opencode\" || model.provider === \"opencode-go\" || model.baseUrl.includes(\"opencode.ai\"))\n\t) {\n\t\treturn { \"x-opencode-session\": sessionId, \"x-opencode-client\": \"pi\" };\n\t}\n\n\tif (!isInstallTelemetryEnabled(settingsManager)) {\n\t\treturn undefined;\n\t}\n\n\tif (model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\")) {\n\t\treturn {\n\t\t\t\"HTTP-Referer\": \"https://pi.dev\",\n\t\t\t\"X-OpenRouter-Title\": APP_NAME,\n\t\t\t\"X-OpenRouter-Categories\": \"cli-agent\",\n\t\t};\n\t}\n\n\tif (\n\t\tmodel.provider === \"cloudflare-workers-ai\" ||\n\t\tmodel.provider === \"cloudflare-ai-gateway\" ||\n\t\tmodel.baseUrl.includes(\"api.cloudflare.com\") ||\n\t\tmodel.baseUrl.includes(\"gateway.ai.cloudflare.com\")\n\t) {\n\t\treturn {\n\t\t\t\"User-Agent\": `${APP_NAME}-coding-agent`,\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst scopedModels =\n\t\toptions.scopedModels ??\n\t\t(await resolveModelScope(\n\t\t\tgetModelNarrowingPatterns({\n\t\t\t\tlegacyEnabledPatterns: settingsManager.getEnabledModels(),\n\t\t\t}),\n\t\t\tmodelRegistry,\n\t\t));\n\tconst favoriteModels =\n\t\toptions.favoriteModels ?? (await resolveModelScope(settingsManager.getFavoriteModels() ?? [], modelRegistry));\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels,\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tthinkingLevel = clampThinkingLevelToModel(thinkingLevel, model);\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst initialActiveToolNames: string[] = options.tools\n\t\t? [...options.tools]\n\t\t: options.noTools\n\t\t\t? []\n\t\t\t: defaultActiveToolNames;\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;\n\t\t\tconst requestRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst attributionHeaders = getAttributionHeaders(model, settingsManager, options?.sessionId);\n\t\t\tconst streamOptions = {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\tserviceTier: auth.serviceTier,\n\t\t\t\ttimeoutMs: options?.timeoutMs ?? requestRetrySettings.timeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? requestRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? requestRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders:\n\t\t\t\t\tattributionHeaders || auth.headers || options?.headers\n\t\t\t\t\t\t? { ...attributionHeaders, ...auth.headers, ...options?.headers }\n\t\t\t\t\t\t: undefined,\n\t\t\t\textraBody: auth.extraBody || options?.extraBody ? { ...auth.extraBody, ...options?.extraBody } : undefined,\n\t\t\t};\n\t\t\treturn streamSimple(requestModel, context, streamOptions);\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\ttimeoutMs: providerRetrySettings.timeoutMs,\n\t\tmaxRetryDelayMs: providerRetrySettings.maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels,\n\t\tfavoriteModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n\n/**\n * Clamp a requested thinking level to what the resolved model actually exposes.\n *\n * Capability tiers:\n * - Non-reasoning model: everything collapses to \"off\".\n * - Model metadata can disable individual levels via thinkingLevelMap.\n * - No xhigh support: xhigh and max both collapse to \"high\".\n * - xhigh but no max: max collapses to \"xhigh\" (currently GPT-5.2/5.3/5.4).\n * - Native max support: xhigh and max are both preserved (Opus 4.6 / 4.7).\n *\n * This keeps session state aligned with `getAvailableThinkingLevels()` so the\n * UI never claims a tier the provider will silently downgrade at request time.\n */\nexport function clampThinkingLevelToModel(\n\tlevel: ThinkingLevel | undefined,\n\tmodel: Model<Api> | undefined,\n): ThinkingLevel {\n\tif (!model?.reasoning) return \"off\";\n\n\tconst requestedLevel = level ?? \"off\";\n\tconst availableLevels = getSupportedThinkingLevels(model);\n\tif (availableLevels.includes(requestedLevel)) return requestedLevel;\n\n\tconst clampedLevels: ThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"];\n\tconst requestedIndex = clampedLevels.indexOf(requestedLevel === \"max\" ? \"xhigh\" : requestedLevel);\n\tif (requestedIndex === -1) return availableLevels[0] ?? \"off\";\n\n\tfor (let index = requestedIndex; index < clampedLevels.length; index++) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\tfor (let index = requestedIndex - 1; index >= 0; index--) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\treturn availableLevels[0] ?? \"off\";\n}\n"]}
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, type Message, type Model, streamSimple } from \"@earendil-works/pi-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ServiceTier } from \"./extensions/builtin/service-tier.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel, getModelNarrowingPatterns, resolveModelScope } from \"./model-resolver.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { getSupportedThinkingLevels } from \"./thinking-levels.ts\";\nimport { time } from \"./timings.ts\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.senpi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Global model narrowing for selectors and startup model choice */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\t/** Favorite models for Ctrl+P cycling */\n\tfavoriteModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel; serviceTier?: ServiceTier }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, pi enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\t// Tool factories (for custom cwd)\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\twithFileMutationQueue,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@earendil-works/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tconst scopedModels =\n\t\toptions.scopedModels ??\n\t\t(await resolveModelScope(\n\t\t\tgetModelNarrowingPatterns({\n\t\t\t\tlegacyEnabledPatterns: settingsManager.getEnabledModels(),\n\t\t\t}),\n\t\t\tmodelRegistry,\n\t\t));\n\tconst favoriteModels =\n\t\toptions.favoriteModels ?? (await resolveModelScope(settingsManager.getFavoriteModels() ?? [], modelRegistry));\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels,\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tthinkingLevel = clampThinkingLevelToModel(thinkingLevel, model);\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames: string[] = (\n\t\toptions.tools ? [...options.tools] : options.noTools ? [] : defaultActiveToolNames\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\tconst streamOptions = {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\tserviceTier: auth.serviceTier,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\t\tmodel,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\tauth.headers,\n\t\t\t\t\toptions?.headers,\n\t\t\t\t),\n\t\t\t\textraBody: auth.extraBody || options?.extraBody ? { ...auth.extraBody, ...options?.extraBody } : undefined,\n\t\t\t};\n\t\t\treturn streamSimple(requestModel, context, streamOptions);\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\ttimeoutMs: providerRetrySettings.timeoutMs,\n\t\tmaxRetryDelayMs: providerRetrySettings.maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels,\n\t\tfavoriteModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n\n/**\n * Clamp a requested thinking level to what the resolved model actually exposes.\n *\n * Capability tiers:\n * - Non-reasoning model: everything collapses to \"off\".\n * - Model metadata can disable individual levels via thinkingLevelMap.\n * - No xhigh support: xhigh and max both collapse to \"high\".\n * - xhigh but no max: max collapses to \"xhigh\" (currently GPT-5.2/5.3/5.4).\n * - Native max support: xhigh and max are both preserved (Opus 4.6 / 4.7).\n *\n * This keeps session state aligned with `getAvailableThinkingLevels()` so the\n * UI never claims a tier the provider will silently downgrade at request time.\n */\nexport function clampThinkingLevelToModel(\n\tlevel: ThinkingLevel | undefined,\n\tmodel: Model<Api> | undefined,\n): ThinkingLevel {\n\tif (!model?.reasoning) return \"off\";\n\n\tconst requestedLevel = level ?? \"off\";\n\tconst availableLevels = getSupportedThinkingLevels(model);\n\tif (availableLevels.includes(requestedLevel)) return requestedLevel;\n\n\tconst clampedLevels: ThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"];\n\tconst requestedIndex = clampedLevels.indexOf(requestedLevel === \"max\" ? \"xhigh\" : requestedLevel);\n\tif (requestedIndex === -1) return availableLevels[0] ?? \"off\";\n\n\tfor (let index = requestedIndex; index < clampedLevels.length; index++) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\tfor (let index = requestedIndex - 1; index >= 0; index--) {\n\t\tconst candidate = clampedLevels[index];\n\t\tif (candidate !== undefined && availableLevels.includes(candidate)) return candidate;\n\t}\n\treturn availableLevels[0] ?? \"off\";\n}\n"]}
@@ -134,6 +134,7 @@ export interface SessionInfo {
134
134
  allMessagesText: string;
135
135
  }
136
136
  export type ReadonlySessionManager = Pick<SessionManager, "getCwd" | "getSessionDir" | "getSessionId" | "getSessionFile" | "getLeafId" | "getLeafEntry" | "getEntry" | "getLabel" | "getBranch" | "getHeader" | "getEntries" | "getTree" | "getSessionName">;
137
+ export declare function assertValidSessionId(id: string): void;
137
138
  /** Exported for testing */
138
139
  export declare function migrateSessionEntries(entries: FileEntry[]): void;
139
140
  /** Exported for compaction.test.ts */
@@ -145,15 +146,11 @@ export declare function getLatestCompactionEntry(entries: SessionEntry[]): Compa
145
146
  * Handles compaction and branch summaries along the path.
146
147
  */
147
148
  export declare function buildSessionContext(entries: SessionEntry[], leafId?: string | null, byId?: Map<string, SessionEntry>): SessionContext;
148
- /**
149
- * Compute the default session directory for a cwd.
150
- * Encodes cwd into a safe directory name under ~/.senpi/agent/sessions/.
151
- */
152
149
  export declare function getDefaultSessionDir(cwd: string, agentDir?: string): string;
153
150
  /** Exported for testing */
154
151
  export declare function loadEntriesFromFile(filePath: string): FileEntry[];
155
152
  /** Exported for testing */
156
- export declare function findMostRecentSession(sessionDir: string): string | null;
153
+ export declare function findMostRecentSession(sessionDir: string, cwd?: string): string | null;
157
154
  export type SessionListProgress = (loaded: number, total: number) => void;
158
155
  /**
159
156
  * Manages conversation sessions as append-only trees stored in JSONL files.
@@ -187,6 +184,7 @@ export declare class SessionManager {
187
184
  isPersisted(): boolean;
188
185
  getCwd(): string;
189
186
  getSessionDir(): string;
187
+ usesDefaultSessionDir(): boolean;
190
188
  getSessionId(): string;
191
189
  getSessionFile(): string | undefined;
192
190
  _persist(entry: SessionEntry): void;
@@ -293,7 +291,7 @@ export declare class SessionManager {
293
291
  * @param cwd Working directory (stored in session header)
294
292
  * @param sessionDir Optional session directory. If omitted, uses default (~/.senpi/agent/sessions/<encoded-cwd>/).
295
293
  */
296
- static create(cwd: string, sessionDir?: string): SessionManager;
294
+ static create(cwd: string, sessionDir?: string, options?: NewSessionOptions): SessionManager;
297
295
  /**
298
296
  * Open a specific session file.
299
297
  * @param path Path to session file
@@ -316,7 +314,7 @@ export declare class SessionManager {
316
314
  * @param targetCwd Target working directory (where the new session will be stored)
317
315
  * @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
318
316
  */
319
- static forkFrom(sourcePath: string, targetCwd: string, sessionDir?: string): SessionManager;
317
+ static forkFrom(sourcePath: string, targetCwd: string, sessionDir?: string, options?: NewSessionOptions): SessionManager;
320
318
  /**
321
319
  * List all sessions for a directory.
322
320
  * @param cwd Working directory (used to compute default session directory)
@@ -329,5 +327,6 @@ export declare class SessionManager {
329
327
  * @param onProgress Optional callback for progress updates (loaded, total)
330
328
  */
331
329
  static listAll(onProgress?: SessionListProgress): Promise<SessionInfo[]>;
330
+ static listAll(sessionDir?: string, onProgress?: SessionListProgress): Promise<SessionInfo[]>;
332
331
  }
333
332
  //# sourceMappingURL=session-manager.d.ts.map