@code-yeongyu/senpi 2026.7.14 → 2026.7.16-2

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 (455) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/README.md +6 -6
  3. package/dist/bun/cli.js +2 -0
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/cli/args.js +1 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/list-models.d.ts +2 -2
  8. package/dist/cli/list-models.d.ts.map +1 -1
  9. package/dist/cli/list-models.js +3 -3
  10. package/dist/cli/list-models.js.map +1 -1
  11. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  12. package/dist/core/agent-session-runtime.js +3 -0
  13. package/dist/core/agent-session-runtime.js.map +1 -1
  14. package/dist/core/agent-session-services.d.ts +4 -3
  15. package/dist/core/agent-session-services.d.ts.map +1 -1
  16. package/dist/core/agent-session-services.js +14 -5
  17. package/dist/core/agent-session-services.js.map +1 -1
  18. package/dist/core/agent-session.d.ts +8 -4
  19. package/dist/core/agent-session.d.ts.map +1 -1
  20. package/dist/core/agent-session.js +81 -30
  21. package/dist/core/agent-session.js.map +1 -1
  22. package/dist/core/auth-providers.js +1 -1
  23. package/dist/core/auth-providers.js.map +1 -1
  24. package/dist/core/auth-storage.d.ts +32 -87
  25. package/dist/core/auth-storage.d.ts.map +1 -1
  26. package/dist/core/auth-storage.js +158 -221
  27. package/dist/core/auth-storage.js.map +1 -1
  28. package/dist/core/cache-stats.d.ts +2 -2
  29. package/dist/core/cache-stats.d.ts.map +1 -1
  30. package/dist/core/cache-stats.js +1 -1
  31. package/dist/core/cache-stats.js.map +1 -1
  32. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  33. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  34. package/dist/core/compaction/branch-summarization.js.map +1 -1
  35. package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
  36. package/dist/core/dynamic-prompt/build.js +6 -1
  37. package/dist/core/dynamic-prompt/build.js.map +1 -1
  38. package/dist/core/extensions/builtin/bash-timeout/timeout.js +2 -2
  39. package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
  40. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +22 -13
  42. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  43. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +1 -1
  44. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/terminal/runtime-session.js +3 -2
  46. package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
  47. package/dist/core/extensions/loader.d.ts.map +1 -1
  48. package/dist/core/extensions/loader.js +8 -2
  49. package/dist/core/extensions/loader.js.map +1 -1
  50. package/dist/core/extensions/runner.d.ts +1 -0
  51. package/dist/core/extensions/runner.d.ts.map +1 -1
  52. package/dist/core/extensions/runner.js +3 -0
  53. package/dist/core/extensions/runner.js.map +1 -1
  54. package/dist/core/extensions/types.d.ts +15 -2
  55. package/dist/core/extensions/types.d.ts.map +1 -1
  56. package/dist/core/extensions/types.js.map +1 -1
  57. package/dist/core/model-config.d.ts +589 -0
  58. package/dist/core/model-config.d.ts.map +1 -0
  59. package/dist/core/model-config.js +288 -0
  60. package/dist/core/model-config.js.map +1 -0
  61. package/dist/core/model-registry.d.ts +17 -146
  62. package/dist/core/model-registry.d.ts.map +1 -1
  63. package/dist/core/model-registry.js +69 -943
  64. package/dist/core/model-registry.js.map +1 -1
  65. package/dist/core/model-resolver.d.ts +8 -5
  66. package/dist/core/model-resolver.d.ts.map +1 -1
  67. package/dist/core/model-resolver.js +19 -18
  68. package/dist/core/model-resolver.js.map +1 -1
  69. package/dist/core/model-runtime.d.ts +81 -0
  70. package/dist/core/model-runtime.d.ts.map +1 -0
  71. package/dist/core/model-runtime.js +442 -0
  72. package/dist/core/model-runtime.js.map +1 -0
  73. package/dist/core/models-store.d.ts +17 -0
  74. package/dist/core/models-store.d.ts.map +1 -0
  75. package/dist/core/models-store.js +46 -0
  76. package/dist/core/models-store.js.map +1 -0
  77. package/dist/core/package-manager.d.ts.map +1 -1
  78. package/dist/core/package-manager.js +7 -2
  79. package/dist/core/package-manager.js.map +1 -1
  80. package/dist/core/provider-composer.d.ts +64 -0
  81. package/dist/core/provider-composer.d.ts.map +1 -0
  82. package/dist/core/provider-composer.js +406 -0
  83. package/dist/core/provider-composer.js.map +1 -0
  84. package/dist/core/provider-display-names.d.ts.map +1 -1
  85. package/dist/core/provider-display-names.js +2 -1
  86. package/dist/core/provider-display-names.js.map +1 -1
  87. package/dist/core/radius.d.ts +2 -0
  88. package/dist/core/radius.d.ts.map +1 -0
  89. package/dist/core/radius.js +2 -0
  90. package/dist/core/radius.js.map +1 -0
  91. package/dist/core/remote-catalog-provider.d.ts +5 -0
  92. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  93. package/dist/core/remote-catalog-provider.js +83 -0
  94. package/dist/core/remote-catalog-provider.js.map +1 -0
  95. package/dist/core/runtime-credentials.d.ts +15 -0
  96. package/dist/core/runtime-credentials.d.ts.map +1 -0
  97. package/dist/core/runtime-credentials.js +35 -0
  98. package/dist/core/runtime-credentials.js.map +1 -0
  99. package/dist/core/sdk.d.ts +11 -20
  100. package/dist/core/sdk.d.ts.map +1 -1
  101. package/dist/core/sdk.js +61 -89
  102. package/dist/core/sdk.js.map +1 -1
  103. package/dist/core/skills.js +1 -1
  104. package/dist/core/skills.js.map +1 -1
  105. package/dist/core/system-prompt.d.ts.map +1 -1
  106. package/dist/core/system-prompt.js +1 -11
  107. package/dist/core/system-prompt.js.map +1 -1
  108. package/dist/index.d.ts +2 -1
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +2 -2
  111. package/dist/index.js.map +1 -1
  112. package/dist/main.d.ts.map +1 -1
  113. package/dist/main.js +10 -13
  114. package/dist/main.js.map +1 -1
  115. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  116. package/dist/modes/interactive/components/assistant-message.js +22 -10
  117. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  118. package/dist/modes/interactive/components/footer.js +1 -1
  119. package/dist/modes/interactive/components/footer.js.map +1 -1
  120. package/dist/modes/interactive/components/login-dialog.d.ts +4 -8
  121. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/login-dialog.js +14 -12
  123. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  124. package/dist/modes/interactive/components/model-selector.d.ts +13 -4
  125. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/model-selector.js +84 -41
  127. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  128. package/dist/modes/interactive/components/oauth-selector.d.ts +4 -4
  129. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/oauth-selector.js +14 -25
  131. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  132. package/dist/modes/interactive/interactive-mode.d.ts +5 -1
  133. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  134. package/dist/modes/interactive/interactive-mode.js +155 -129
  135. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  136. package/dist/package-manager-cli.d.ts.map +1 -1
  137. package/dist/package-manager-cli.js +70 -8
  138. package/dist/package-manager-cli.js.map +1 -1
  139. package/docs/custom-provider.md +8 -11
  140. package/docs/extensions.md +78 -555
  141. package/docs/models.md +4 -0
  142. package/docs/packages.md +1 -0
  143. package/docs/providers.md +23 -11
  144. package/docs/sdk.md +79 -105
  145. package/docs/usage.md +1 -0
  146. package/examples/AGENTS.md +34 -0
  147. package/examples/extensions/README.md +1 -0
  148. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  149. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  150. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  151. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  152. package/examples/extensions/gondolin/package-lock.json +2 -2
  153. package/examples/extensions/gondolin/package.json +1 -1
  154. package/examples/extensions/kimi-deferred-tools.ts +61 -0
  155. package/examples/extensions/sandbox/package-lock.json +2 -2
  156. package/examples/extensions/sandbox/package.json +1 -1
  157. package/examples/extensions/with-deps/package-lock.json +2 -2
  158. package/examples/extensions/with-deps/package.json +1 -1
  159. package/examples/sdk/02-custom-model.ts +5 -8
  160. package/examples/sdk/09-api-keys-and-oauth.ts +13 -31
  161. package/examples/sdk/12-full-control.ts +8 -13
  162. package/examples/sdk/README.md +14 -18
  163. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +32 -0
  164. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  165. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/local-module-loader.ts +2 -2
  166. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/rewrite-imports.ts +4 -4
  167. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +32 -32
  168. package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
  169. package/node_modules/@earendil-works/pi-ai/README.md +80 -25
  170. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +23 -42
  172. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  173. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  174. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +10 -6
  175. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
  176. package/node_modules/@earendil-works/pi-ai/dist/api/lazy.d.ts.map +1 -1
  177. package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js +9 -10
  178. package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js.map +1 -1
  179. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts +1 -0
  180. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  181. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +4 -3
  182. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  183. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts +2 -1
  184. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  185. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +54 -5
  186. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  187. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  188. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +23 -0
  189. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  190. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +1 -0
  191. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  192. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +24 -6
  193. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  194. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.d.ts +97 -0
  195. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.d.ts.map +1 -0
  196. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +307 -0
  197. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js.map +1 -0
  198. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.lazy.d.ts +3 -0
  199. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.lazy.d.ts.map +1 -0
  200. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.lazy.js +3 -0
  201. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.lazy.js.map +1 -0
  202. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
  203. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
  204. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +3 -0
  205. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
  206. package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts +1 -0
  207. package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts.map +1 -1
  208. package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js +4 -3
  209. package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js.map +1 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts +9 -0
  211. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts.map +1 -0
  212. package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/anthropic.js +51 -116
  213. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js.map +1 -0
  214. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.d.ts.map +1 -0
  215. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.js.map +1 -0
  216. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts +6 -0
  217. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -0
  218. package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/github-copilot.js +18 -77
  219. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -0
  220. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts +23 -0
  221. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts.map +1 -0
  222. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +49 -0
  223. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js.map +1 -0
  224. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.d.ts.map +1 -0
  225. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.js.map +1 -0
  226. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts +9 -0
  227. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts.map +1 -0
  228. package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/openai-codex.js +61 -155
  229. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js.map +1 -0
  230. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/pkce.d.ts.map +1 -0
  231. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/pkce.js.map +1 -0
  232. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts +16 -0
  233. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts.map +1 -0
  234. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js +316 -0
  235. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js.map +1 -0
  236. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.d.ts +6 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.d.ts.map +1 -0
  238. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.js +189 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.js.map +1 -0
  240. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +2 -4
  241. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +9 -7
  243. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +49 -10
  245. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  246. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  247. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts +3 -0
  248. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts.map +1 -0
  249. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +17 -0
  250. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js.map +1 -0
  251. package/node_modules/@earendil-works/pi-ai/dist/cli.js +58 -76
  252. package/node_modules/@earendil-works/pi-ai/dist/cli.js.map +1 -1
  253. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts +42 -0
  254. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts.map +1 -0
  255. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.js +2 -0
  256. package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.js.map +1 -0
  257. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +2 -0
  258. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
  259. package/node_modules/@earendil-works/pi-ai/dist/compat.js +49 -22
  260. package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
  261. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  262. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -0
  263. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/images-models.d.ts +4 -2
  265. package/node_modules/@earendil-works/pi-ai/dist/images-models.d.ts.map +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/images-models.js +5 -4
  267. package/node_modules/@earendil-works/pi-ai/dist/images-models.js.map +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +3 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  270. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  271. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  272. package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts +25 -0
  273. package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts.map +1 -0
  274. package/node_modules/@earendil-works/pi-ai/dist/models-store.js +16 -0
  275. package/node_modules/@earendil-works/pi-ai/dist/models-store.js.map +1 -0
  276. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +69 -30
  277. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +328 -120
  279. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/models.js +217 -31
  281. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/oauth.d.ts +2 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/oauth.d.ts.map +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/oauth.js +1 -1
  285. package/node_modules/@earendil-works/pi-ai/dist/oauth.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts +11 -6
  287. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  288. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +3 -0
  289. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  290. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  291. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +51 -10
  292. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  293. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  294. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +1 -1
  295. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
  297. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js +4 -3
  298. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js.map +1 -1
  299. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.d.ts.map +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.js +13 -20
  301. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.d.ts +8 -0
  303. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.d.ts.map +1 -0
  304. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.js +21 -0
  305. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.js.map +1 -0
  306. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.d.ts.map +1 -1
  307. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.js +2 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.js.map +1 -1
  309. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js +11 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +1 -6
  313. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +1 -2
  315. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
  317. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +56 -5
  318. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
  319. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +66 -0
  320. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
  321. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js +42 -0
  322. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
  323. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts +36 -0
  324. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  325. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js +19 -0
  326. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js.map +1 -1
  327. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts +36 -0
  328. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js +19 -0
  330. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.d.ts.map +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js.map +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +57 -0
  335. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
  336. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +19 -0
  337. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
  338. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +42 -0
  339. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +175 -139
  341. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.d.ts +26 -0
  343. package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.d.ts.map +1 -0
  344. package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js +59 -0
  345. package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js.map +1 -0
  346. package/node_modules/@earendil-works/pi-ai/dist/providers/radius.d.ts +9 -0
  347. package/node_modules/@earendil-works/pi-ai/dist/providers/radius.d.ts.map +1 -0
  348. package/node_modules/@earendil-works/pi-ai/dist/providers/radius.js +54 -0
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/radius.js.map +1 -0
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +84 -0
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +74 -2
  353. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  354. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts +1 -1
  355. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts.map +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js +15 -3
  357. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js.map +1 -1
  358. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts +6 -114
  359. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts.map +1 -1
  360. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js +3 -92
  361. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js.map +1 -1
  362. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.d.ts.map +1 -1
  363. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js +9 -0
  364. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js.map +1 -1
  365. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts +1 -1
  366. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
  367. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +6 -2
  368. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
  369. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts +8 -0
  370. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts.map +1 -0
  371. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js +92 -0
  372. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js.map +1 -0
  373. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts +6 -0
  374. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts.map +1 -0
  375. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js +54 -0
  376. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js.map +1 -0
  377. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/index.d.ts +4 -0
  378. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/index.d.ts.map +1 -0
  379. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/index.js +4 -0
  380. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/index.js.map +1 -0
  381. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.d.ts +7 -0
  382. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.d.ts.map +1 -0
  383. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.js +16 -0
  384. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.js.map +1 -0
  385. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts +19 -0
  386. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts.map +1 -0
  387. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js +217 -0
  388. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js.map +1 -0
  389. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts +4 -0
  390. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts.map +1 -0
  391. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js +46 -0
  392. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js.map +1 -0
  393. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.d.ts +13 -0
  394. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.d.ts.map +1 -0
  395. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js +144 -0
  396. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js.map +1 -0
  397. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts +5 -0
  398. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -0
  399. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +208 -0
  400. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -0
  401. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.d.ts +4 -0
  402. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.d.ts.map +1 -0
  403. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.js +17 -0
  404. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.js.map +1 -0
  405. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.d.ts +5 -0
  406. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.d.ts.map +1 -0
  407. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.js +34 -0
  408. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.js.map +1 -0
  409. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts +3 -1
  410. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts.map +1 -1
  411. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.js.map +1 -1
  412. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +12 -5
  413. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  414. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  415. package/node_modules/@earendil-works/pi-ai/package.json +6 -1
  416. package/node_modules/@earendil-works/pi-pty/native/prebuilds/darwin-arm64/senpi_pty.darwin-arm64.node +0 -0
  417. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  418. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-tui/dist/utils.js +22 -4
  420. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  421. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  422. package/package.json +6 -6
  423. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.d.ts +0 -27
  424. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.d.ts.map +0 -1
  425. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.js.map +0 -1
  426. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +0 -1
  427. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +0 -1
  428. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts +0 -32
  429. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +0 -1
  430. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +0 -1
  431. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +0 -58
  432. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +0 -1
  433. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +0 -122
  434. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +0 -1
  435. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.d.ts +0 -5
  436. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.d.ts.map +0 -1
  437. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.js +0 -22
  438. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.js.map +0 -1
  439. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/oauth-page.d.ts.map +0 -1
  440. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/oauth-page.js.map +0 -1
  441. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +0 -45
  442. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +0 -1
  443. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +0 -1
  444. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/pkce.d.ts.map +0 -1
  445. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/pkce.js.map +0 -1
  446. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.d.ts +0 -64
  447. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.d.ts.map +0 -1
  448. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.js +0 -2
  449. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.js.map +0 -1
  450. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/device-code.d.ts +0 -0
  451. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/device-code.js +0 -0
  452. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/oauth-page.d.ts +0 -0
  453. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/oauth-page.js +0 -0
  454. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/pkce.d.ts +0 -0
  455. /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/pkce.js +0 -0
@@ -1,10 +1,10 @@
1
- > senpi can create extensions. Ask it to build one for your use case.
1
+ > pi can create extensions. Ask it to build one for your use case.
2
2
 
3
3
  # Extensions
4
4
 
5
- Extensions are TypeScript modules that extend senpi's behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, and more.
5
+ Extensions are TypeScript modules that extend pi's behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, and more.
6
6
 
7
- > **Placement for /reload:** Put extensions in `~/.senpi/agent/extensions/` (global) or `.senpi/extensions/` (project-local) for auto-discovery. Use `senpi -e ./path.ts` only for quick tests. Extensions in auto-discovered locations can be hot-reloaded with `/reload`.
7
+ > **Placement for /reload:** Put extensions in `~/.pi/agent/extensions/` (global) or `.pi/extensions/` (project-local) for auto-discovery. Use `pi -e ./path.ts` only for quick tests. Extensions in auto-discovered locations can be hot-reloaded with `/reload`.
8
8
 
9
9
  **Key capabilities:**
10
10
  - **Custom tools** - Register tools the LLM can call via `pi.registerTool()`
@@ -38,11 +38,6 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
38
38
  - [Events](#events)
39
39
  - [Lifecycle Overview](#lifecycle-overview)
40
40
  - [Resource Events](#resource-events)
41
- - [Builtin Hooks](#builtin-hooks)
42
- - [Hook setup workflow](#hook-setup-workflow)
43
- - [Hook input and output](#hook-input-and-output)
44
- - [Common hook recipes](#common-hook-recipes)
45
- - [Hook troubleshooting](#hook-troubleshooting)
46
41
  - [Session Events](#session-events)
47
42
  - [Agent Events](#agent-events)
48
43
  - [Model Events](#model-events)
@@ -60,10 +55,10 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
60
55
 
61
56
  ## Quick Start
62
57
 
63
- Create `~/.senpi/agent/extensions/my-extension.ts`:
58
+ Create `~/.pi/agent/extensions/my-extension.ts`:
64
59
 
65
60
  ```typescript
66
- import type { ExtensionAPI } from "@code-yeongyu/senpi";
61
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
67
62
  import { Type } from "typebox";
68
63
 
69
64
  export default function (pi: ExtensionAPI) {
@@ -108,21 +103,21 @@ export default function (pi: ExtensionAPI) {
108
103
  Test with `--extension` (or `-e`) flag:
109
104
 
110
105
  ```bash
111
- senpi -e ./my-extension.ts
106
+ pi -e ./my-extension.ts
112
107
  ```
113
108
 
114
109
  ## Extension Locations
115
110
 
116
111
  > **Security:** Extensions run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
117
112
 
118
- Extensions are auto-discovered from trusted locations. Project-local `.senpi/extensions` entries load only after the project is trusted.
113
+ Extensions are auto-discovered from trusted locations. Project-local `.pi/extensions` entries load only after the project is trusted.
119
114
 
120
115
  | Location | Scope |
121
116
  |----------|-------|
122
- | `~/.senpi/agent/extensions/*.ts` | Global (all projects) |
123
- | `~/.senpi/agent/extensions/*/index.ts` | Global (subdirectory) |
124
- | `.senpi/extensions/*.ts` | Project-local |
125
- | `.senpi/extensions/*/index.ts` | Project-local (subdirectory) |
117
+ | `~/.pi/agent/extensions/*.ts` | Global (all projects) |
118
+ | `~/.pi/agent/extensions/*/index.ts` | Global (subdirectory) |
119
+ | `.pi/extensions/*.ts` | Project-local |
120
+ | `.pi/extensions/*/index.ts` | Project-local (subdirectory) |
126
121
 
127
122
  Additional paths via `settings.json`:
128
123
 
@@ -139,20 +134,20 @@ Additional paths via `settings.json`:
139
134
  }
140
135
  ```
141
136
 
142
- To share extensions via npm or git as senpi packages, see [packages.md](packages.md).
137
+ To share extensions via npm or git as pi packages, see [packages.md](packages.md).
143
138
 
144
139
  ## Available Imports
145
140
 
146
141
  | Package | Purpose |
147
142
  |---------|---------|
148
- | `@code-yeongyu/senpi` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) |
143
+ | `@earendil-works/pi-coding-agent` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) |
149
144
  | `typebox` | Schema definitions for tool parameters |
150
145
  | `@earendil-works/pi-ai` | AI utilities (`StringEnum` for Google-compatible enums) |
151
146
  | `@earendil-works/pi-tui` | TUI components for custom rendering |
152
147
 
153
148
  npm dependencies work too. Add a `package.json` next to your extension (or in a parent directory), run `npm install`, and imports from `node_modules/` are resolved automatically.
154
149
 
155
- For distributed senpi packages installed with `senpi install` (npm or git), runtime deps must be in `dependencies`. Package installation uses production installs (`npm install --omit=dev`) by default, so `devDependencies` are not available at runtime; when `npmCommand` is configured, git packages use plain `install` for compatibility with wrappers.
150
+ For distributed pi packages installed with `pi install` (npm or git), runtime deps must be in `dependencies`. Package installation uses production installs (`npm install --omit=dev`) by default, so `devDependencies` are not available at runtime; when `npmCommand` is configured, git packages use plain `install` for compatibility with wrappers.
156
151
 
157
152
  Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
158
153
 
@@ -161,7 +156,7 @@ Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
161
156
  An extension exports a default factory function that receives `ExtensionAPI`. The factory can be synchronous or asynchronous:
162
157
 
163
158
  ```typescript
164
- import type { ExtensionAPI } from "@code-yeongyu/senpi";
159
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
165
160
 
166
161
  export default function (pi: ExtensionAPI) {
167
162
  // Subscribe to events
@@ -183,14 +178,14 @@ export default function (pi: ExtensionAPI) {
183
178
 
184
179
  Extensions are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript works without compilation.
185
180
 
186
- If the factory returns a `Promise`, senpi awaits it before continuing startup. That means async initialization completes before `session_start`, before `resources_discover`, and before provider registrations queued via `pi.registerProvider()` are flushed.
181
+ If the factory returns a `Promise`, pi awaits it before continuing startup. That means async initialization completes before `session_start`, before `resources_discover`, and before provider registrations queued via `pi.registerProvider()` are flushed.
187
182
 
188
183
  ### Async factory functions
189
184
 
190
185
  Use an async factory for one-time startup work such as fetching remote configuration or dynamically discovering available models.
191
186
 
192
187
  ```typescript
193
- import type { ExtensionAPI } from "@code-yeongyu/senpi";
188
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
194
189
 
195
190
  export default async function (pi: ExtensionAPI) {
196
191
  const response = await fetch("http://localhost:1234/v1/models");
@@ -220,7 +215,7 @@ export default async function (pi: ExtensionAPI) {
220
215
  }
221
216
  ```
222
217
 
223
- This pattern makes the fetched models available during normal startup and to `senpi --list-models`.
218
+ This pattern makes the fetched models available during normal startup and to `pi --list-models`.
224
219
 
225
220
  ### Long-lived resources and shutdown
226
221
 
@@ -233,14 +228,14 @@ Defer background resource startup until `session_start` or the command/tool/even
233
228
  **Single file** - simplest, for small extensions:
234
229
 
235
230
  ```
236
- ~/.senpi/agent/extensions/
231
+ ~/.pi/agent/extensions/
237
232
  └── my-extension.ts
238
233
  ```
239
234
 
240
235
  **Directory with index.ts** - for multi-file extensions:
241
236
 
242
237
  ```
243
- ~/.senpi/agent/extensions/
238
+ ~/.pi/agent/extensions/
244
239
  └── my-extension/
245
240
  ├── index.ts # Entry point (exports default function)
246
241
  ├── tools.ts # Helper module
@@ -250,7 +245,7 @@ Defer background resource startup until `session_start` or the command/tool/even
250
245
  **Package with dependencies** - for extensions that need npm packages:
251
246
 
252
247
  ```
253
- ~/.senpi/agent/extensions/
248
+ ~/.pi/agent/extensions/
254
249
  └── my-extension/
255
250
  ├── package.json # Declares dependencies and entry points
256
251
  ├── package-lock.json
@@ -280,7 +275,7 @@ Run `npm install` in the extension directory, then imports from `node_modules/`
280
275
  ### Lifecycle Overview
281
276
 
282
277
  ```
283
- senpi starts
278
+ pi starts
284
279
 
285
280
  ├─► project_trust (user/global and CLI extensions only, before project resources load)
286
281
  ├─► session_start { reason: "startup" }
@@ -356,7 +351,7 @@ exit (Ctrl+C, Ctrl+D, SIGHUP, SIGTERM)
356
351
 
357
352
  #### project_trust
358
353
 
359
- Fired before senpi decides whether to trust a project with dynamic configs (`.senpi` or `.agents/skills`). It runs during startup and when session replacement (for example `/resume`) enters a cwd whose trust has not been resolved in the current process. Only user/global extensions and CLI `-e` extensions participate; project-local extensions are not loaded until after trust is resolved.
354
+ Fired before pi decides whether to trust a project with dynamic configs (`.pi` or `.agents/skills`). It runs during startup and when session replacement (for example `/resume`) enters a cwd whose trust has not been resolved in the current process. Only user/global extensions and CLI `-e` extensions participate; project-local extensions are not loaded until after trust is resolved.
360
355
 
361
356
  ```typescript
362
357
  pi.on("project_trust", async (event, ctx) => {
@@ -369,7 +364,7 @@ pi.on("project_trust", async (event, ctx) => {
369
364
  });
370
365
  ```
371
366
 
372
- A `project_trust` handler must return `{ trusted: "yes" | "no" | "undecided" }`. A user/global or CLI extension that returns `"yes"` or `"no"` owns the decision; the first yes/no decision wins and suppresses the built-in trust prompt. Use `remember: true` to persist a yes/no decision; otherwise it applies only to the current process. Return `"undecided"` to let later handlers or the built-in trust flow decide. Check `ctx.hasUI` before prompting. If no handler returns yes/no, normal trust resolution continues: saved `trust.json` decisions apply first, then `defaultProjectTrust` controls whether senpi asks, trusts, or declines by default.
367
+ A `project_trust` handler must return `{ trusted: "yes" | "no" | "undecided" }`. A user/global or CLI extension that returns `"yes"` or `"no"` owns the decision; the first yes/no decision wins and suppresses the built-in trust prompt. Use `remember: true` to persist a yes/no decision; otherwise it applies only to the current process. Return `"undecided"` to let later handlers or the built-in trust flow decide. Check `ctx.hasUI` before prompting. If no handler returns yes/no, normal trust resolution continues: saved `trust.json` decisions apply first, then `defaultProjectTrust` controls whether pi asks, trusts, or declines by default.
373
368
 
374
369
  ### Resource Events
375
370
 
@@ -390,451 +385,6 @@ pi.on("resources_discover", async (event, _ctx) => {
390
385
  });
391
386
  ```
392
387
 
393
- ### Builtin Hooks
394
-
395
- The builtin `hooks` extension runs trusted command hooks from JSON config files. It is intended for local guardrails and migration from Claude-style command hooks, while keeping the extension API as the primary senpi customization surface.
396
-
397
- Default senpi hook files are discovered from:
398
-
399
- | Source | Timing | Notes |
400
- |--------|--------|-------|
401
- | `~/.senpi/agent/hooks.json` | pre-session | Global hook config. |
402
- | Global package `pi.hooks` or `hooks/*.json` | pre-session | Package hook config loaded after the global hook file. |
403
- | `.senpi/hooks.json` | pre-session | Project hook config, loaded after project trust. |
404
- | Project package `pi.hooks` or `hooks/*.json` | pre-session | Package hook config loaded after the project hook file. |
405
- | Temporary package sources and SDK/host-provided `new DefaultResourceLoader({ additionalHookPaths })` | pre-session | Package/plugin hook JSON files resolved before `session_start`. |
406
- | `resources_discover` `hookPaths` | runtime | Late sources. They can affect later hook events in the current runtime and `SessionStart` on `/reload` or the next session. |
407
-
408
- #### Hook setup workflow
409
-
410
- Use builtin hooks when you already have Claude/Codex-style JSON hook configs or when you want a small shell-script guardrail. Use a TypeScript extension instead when the behavior needs rich senpi APIs, UI prompts, custom tools, long-lived state, or non-command handlers.
411
-
412
- For a project-local hook:
413
-
414
- 1. Create `.senpi/hooks.json`.
415
- 2. Put command scripts under `.senpi/hooks/` or another project path.
416
- 3. Start `senpi` in that project.
417
- 4. Run `/hooks list` and copy the real hook id.
418
- 5. Run `/hooks trust <id>` once for each command hook you want to execute.
419
- 6. Trigger the event, then use `/hooks diagnostics` if it did not run.
420
-
421
- For a global hook, use `~/.senpi/agent/hooks.json` and a stable global script path. For team-shared hooks, prefer a senpi package or plugin manifest so the scripts and hook JSON move together.
422
-
423
- Trust is tied to the command hook's canonical hash. Changing the command text, `commandWindows`, timeout, matcher, or status message makes the hook untrusted again until you review and trust the new hash. Disabling a hook with `/hooks disable <id>` keeps the trust entry but skips execution; `/hooks enable <id>` re-enables it.
424
-
425
- Recommended first check after adding a hook:
426
-
427
- ```text
428
- /hooks list
429
- /hooks diagnostics
430
- ```
431
-
432
- `/hooks list` should show the source, matcher, trust state, disabled state, and redacted command preview. `/hooks diagnostics` should be empty or contain only diagnostics you intentionally accept.
433
-
434
- #### Minimal project hook
435
-
436
- Create `.senpi/hooks.json`:
437
-
438
- ```json
439
- {
440
- "hooks": {
441
- "PreToolUse": [
442
- {
443
- "matcher": "bash",
444
- "hooks": [
445
- {
446
- "type": "command",
447
- "command": "node .senpi/hooks/log-pretool.mjs",
448
- "timeout": 10,
449
- "statusMessage": "Checking bash command"
450
- }
451
- ]
452
- }
453
- ]
454
- }
455
- }
456
- ```
457
-
458
- Create `.senpi/hooks/log-pretool.mjs`:
459
-
460
- ```javascript
461
- let stdin = "";
462
- process.stdin.setEncoding("utf8");
463
- process.stdin.on("data", (chunk) => {
464
- stdin += chunk;
465
- });
466
- process.stdin.on("end", () => {
467
- const input = JSON.parse(stdin);
468
- const toolInput = input.toolInput ?? input.tool_input ?? {};
469
- const command = String(toolInput.command ?? "");
470
- if (command.includes("rm -rf")) {
471
- process.stdout.write(JSON.stringify({
472
- hookSpecificOutput: {
473
- hookEventName: "PreToolUse",
474
- permissionDecision: "deny",
475
- permissionDecisionReason: "Refusing destructive shell command"
476
- }
477
- }));
478
- return;
479
- }
480
- process.stdout.write(JSON.stringify({
481
- hookSpecificOutput: {
482
- hookEventName: "PreToolUse",
483
- permissionDecision: "allow"
484
- }
485
- }));
486
- });
487
- ```
488
-
489
- Start senpi in the project and inspect hooks:
490
-
491
- ```bash
492
- senpi
493
- /hooks list
494
- /hooks trust hk_example_PreToolUse_0_0
495
- ```
496
-
497
- The real hook id is shown by `/hooks list`. A command hook must be trusted before it runs. Project hook trust is writable only when the project is trusted.
498
-
499
- Exact command grammar:
500
-
501
- ```text
502
- Usage: /hooks [list|diagnostics|trust <id>|disable <id>|enable <id>|reload]
503
- ```
504
-
505
- `/hooks list` shows executable hooks, ids, trust state, disabled state, matcher, status message, and a redacted command preview. `/hooks diagnostics` shows malformed, unsupported, untrusted, and skipped hook details. `/hooks reload` runs the normal extension/resource reload flow.
506
-
507
- #### Command handler JSON
508
-
509
- Only command handlers are executable in builtin hooks v1:
510
-
511
- ```json
512
- {
513
- "type": "command",
514
- "command": "node ./hooks/check.mjs",
515
- "commandWindows": "node .\\hooks\\check.mjs",
516
- "timeout": 30,
517
- "statusMessage": "Running hook"
518
- }
519
- ```
520
-
521
- `command` is required and runs through the host shell with the hook input JSON on stdin. `commandWindows` or `command_windows` can override the command on Windows. `timeout` is seconds and defaults to 600. `statusMessage` is display text: while the hook command runs during `PreToolUse`/`PostToolUse`, the TUI shows it in the live `Running PreToolUse/PostToolUse hook: ...` status row (hooks without one show their sanitized command text instead).
522
-
523
- Hook commands inherit a minimal environment (`PATH`, home/user/shell/temp variables, and Windows shell basics). Hooks loaded through the plugin manifest helper also receive `PLUGIN_ROOT`, `PLUGIN_DATA`, `CLAUDE_PLUGIN_ROOT`, and `CLAUDE_PLUGIN_DATA`. Every command receives `SENPI_HOOK_SOURCE` and `SENPI_HOOK_EVENT`. Do not put API keys or tokens in hook config, command text, status messages, stdout, stderr, or diagnostics. Read secrets inside the command from your own secret store and avoid echoing them.
524
-
525
- #### Event map
526
-
527
- | Event | senpi source | Supported behavior |
528
- |-------|--------------|--------------------|
529
- | `SessionStart` | `session_start` | Runs on startup/reload/new/resume/fork. `additionalContext` is recorded as hidden hook context. Decisions are diagnostics only. |
530
- | `UserPromptSubmit` | `input` plus `before_agent_start` | Can block the prompt. `additionalContext` is injected as hidden context for the turn. `systemMessage` appends to the turn system prompt. |
531
- | `PreToolUse` | `tool_call` | Can deny/block, ask (represented as block), allow/approve, mutate `updatedInput` only with `permissionDecision: "allow"`, and add context for the matching tool result. |
532
- | `PostToolUse` | `tool_result` | Can block by replacing the tool result with an error, replace tool output with `updatedToolOutput`, and append `additionalContext`. |
533
- | `PreCompact` | `session_before_compact` | Can block/cancel compaction with `decision: "block"` or exit code 2. `additionalContext` and `customInstructions` are diagnostic-only. |
534
- | `PostCompact` | `session_compact` | Runs after accepted compactions. Output fields are currently diagnostic-only. |
535
- | `Stop` | `agent_end` | Can block by sending a follow-up prompt from `additionalContext` or `reason`. Reentry is capped at eight blocks per turn. |
536
-
537
- Matchers are strings. For tool events, matchers match tool names. For lifecycle events, `*`, event names, reasons such as `startup`, `reload`, `manual`, or `overflow`, comma/pipe-separated literals, and JavaScript regular expressions are supported.
538
-
539
- Command stdout may be empty or JSON. Universal JSON fields include `decision`, `reason`, `additionalContext`, `continue`, `stopReason`, `suppressOutput`, `systemMessage`, and `hookSpecificOutput`. `hookSpecificOutput.hookEventName` must match the current event when present. Exit code `2` is treated as a block decision with stderr as the reason.
540
-
541
- #### Hook input and output
542
-
543
- Every command receives one JSON object on stdin. The object always includes `event` and `cwd`, and includes session/transcript fields when senpi has them:
544
-
545
- | Field | Meaning |
546
- |-------|---------|
547
- | `event` | Hook event name, such as `PreToolUse` or `UserPromptSubmit`. |
548
- | `cwd` | Current project working directory. |
549
- | `session_id` | Session id when available. |
550
- | `transcript_path` | Session transcript path when available. |
551
-
552
- Tool events include both senpi-style camelCase and Claude-compatible snake_case fields:
553
-
554
- ```json
555
- {
556
- "event": "PreToolUse",
557
- "toolName": "bash",
558
- "toolInput": { "command": "npm test" },
559
- "tool_name": "bash",
560
- "tool_input": { "command": "npm test" },
561
- "cwd": "/repo"
562
- }
563
- ```
564
-
565
- Prompt hooks receive the raw prompt:
566
-
567
- ```json
568
- {
569
- "event": "UserPromptSubmit",
570
- "prompt": "summarize this repo",
571
- "cwd": "/repo"
572
- }
573
- ```
574
-
575
- Output must be valid JSON if you want senpi to apply a decision. Empty stdout means no decision. Prefer event-specific output inside `hookSpecificOutput`:
576
-
577
- ```json
578
- {
579
- "hookSpecificOutput": {
580
- "hookEventName": "PreToolUse",
581
- "permissionDecision": "deny",
582
- "permissionDecisionReason": "Do not run destructive commands"
583
- }
584
- }
585
- ```
586
-
587
- `PreToolUse` supports `permissionDecision: "allow" | "deny" | "ask"`. `updatedInput` is applied only when `permissionDecision` is `"allow"`. `additionalContext` is saved as hidden context for the active tool result.
588
-
589
- ```json
590
- {
591
- "hookSpecificOutput": {
592
- "hookEventName": "PreToolUse",
593
- "permissionDecision": "allow",
594
- "updatedInput": { "command": "npm test -- --runInBand" },
595
- "additionalContext": "The hook serialized this test command."
596
- }
597
- }
598
- ```
599
-
600
- `UserPromptSubmit` can block or add context, but it cannot replace the prompt through Claude/Codex-compatible fields:
601
-
602
- ```json
603
- {
604
- "decision": "block",
605
- "reason": "Please include an issue number before starting release work."
606
- }
607
- ```
608
-
609
- `PostToolUse` can replace visible tool output with `updatedToolOutput` and can add `additionalContext`:
610
-
611
- ```json
612
- {
613
- "hookSpecificOutput": {
614
- "hookEventName": "PostToolUse",
615
- "updatedToolOutput": "Output redacted by local hook.",
616
- "additionalContext": "The raw tool output was replaced because it matched the secret scanner."
617
- }
618
- }
619
- ```
620
-
621
- `Stop` can ask senpi to continue with a follow-up prompt by returning `decision: "block"` plus `additionalContext` or `reason`. senpi caps repeated Stop follow-ups at eight per turn to prevent loops.
622
-
623
- #### Common hook recipes
624
-
625
- Block dangerous shell commands:
626
-
627
- ```javascript
628
- let stdin = "";
629
- process.stdin.setEncoding("utf8");
630
- process.stdin.on("data", (chunk) => {
631
- stdin += chunk;
632
- });
633
- process.stdin.on("end", () => {
634
- const input = JSON.parse(stdin);
635
- const toolInput = input.toolInput ?? input.tool_input ?? {};
636
- const command = String(toolInput.command ?? "");
637
-
638
- if (/\brm\s+-rf\b/.test(command)) {
639
- process.stdout.write(JSON.stringify({
640
- hookSpecificOutput: {
641
- hookEventName: "PreToolUse",
642
- permissionDecision: "deny",
643
- permissionDecisionReason: "Blocked rm -rf"
644
- }
645
- }));
646
- }
647
- });
648
- ```
649
-
650
- Add per-prompt project context:
651
-
652
- ```json
653
- {
654
- "hooks": {
655
- "UserPromptSubmit": [
656
- {
657
- "hooks": [
658
- {
659
- "type": "command",
660
- "command": "node .senpi/hooks/prompt-context.mjs",
661
- "statusMessage": "Loading prompt context"
662
- }
663
- ]
664
- }
665
- ]
666
- }
667
- }
668
- ```
669
-
670
- ```javascript
671
- process.stdin.resume();
672
- process.stdin.on("end", () => {
673
- process.stdout.write(JSON.stringify({
674
- hookSpecificOutput: {
675
- hookEventName: "UserPromptSubmit",
676
- additionalContext: "Prefer the repository's AGENTS.md rules over generic defaults."
677
- }
678
- }));
679
- });
680
- ```
681
-
682
- Stop when a final answer needs a required follow-up:
683
-
684
- ```javascript
685
- process.stdin.resume();
686
- process.stdin.on("end", () => {
687
- process.stdout.write(JSON.stringify({
688
- decision: "block",
689
- hookSpecificOutput: {
690
- hookEventName: "Stop",
691
- additionalContext: "Before finishing, run the focused regression test and summarize the result."
692
- }
693
- }));
694
- });
695
- ```
696
-
697
- Distribute hooks from a package:
698
-
699
- ```json
700
- {
701
- "name": "team-senpi-hooks",
702
- "pi": {
703
- "hooks": ["./hooks/pretool.json"]
704
- }
705
- }
706
- ```
707
-
708
- ```json
709
- {
710
- "hooks": {
711
- "PreToolUse": [
712
- {
713
- "matcher": "bash|edit|write",
714
- "hooks": [
715
- {
716
- "type": "command",
717
- "command": "node ./hooks/check.mjs",
718
- "statusMessage": "Running team hook"
719
- }
720
- ]
721
- }
722
- ]
723
- }
724
- }
725
- ```
726
-
727
- Package hook paths are resolved relative to the package root. If you need plugin-root environment variables, use a `.codex-plugin/plugin.json` manifest and `${PLUGIN_ROOT}` in the command.
728
-
729
- #### Plugin hooks
730
-
731
- Plugin hook manifests are package integration inputs. Installed senpi packages can expose hook JSON files through `package.json` under `pi.hooks` or by placing JSON files under `hooks/`; those sources are discovered before `session_start` in global, project, or temporary package scope.
732
-
733
- Plugin hook manifests live at `.codex-plugin/plugin.json` under the plugin root. A manifest can point to hook JSON files:
734
-
735
- ```json
736
- {
737
- "name": "example-hooks-plugin",
738
- "hooks": "./hooks/pretool.json"
739
- }
740
- ```
741
-
742
- It can also inline hook config directly:
743
-
744
- ```json
745
- {
746
- "name": "inline-hooks-plugin",
747
- "hooks": {
748
- "hooks": {
749
- "SessionStart": [
750
- {
751
- "matcher": "startup|reload",
752
- "hooks": [
753
- {
754
- "type": "command",
755
- "command": "node ${PLUGIN_ROOT}/hooks/session-start.mjs"
756
- }
757
- ]
758
- }
759
- ]
760
- }
761
- }
762
- }
763
- ```
764
-
765
- `hooks` may also be an array mixing paths, nested arrays, and inline hook objects. Hook paths must stay inside the plugin root. The manifest helper also understands a plugin default hook file at `hooks/hooks.json` unless the host disables default plugin hooks. Plugin commands that reference `${PLUGIN_ROOT}`, `$PLUGIN_ROOT`, or `%PLUGIN_ROOT%` must resolve to existing files inside the plugin root.
766
-
767
- SDK hosts can still provide explicit pre-session hook sources:
768
-
769
- ```typescript
770
- const loader = new DefaultResourceLoader({
771
- cwd,
772
- agentDir,
773
- additionalHookPaths: ["/absolute/path/to/package-hooks.json"],
774
- });
775
- ```
776
-
777
- Pre-session sources are visible to `SessionStart` on initial startup.
778
-
779
- #### Runtime hook sources
780
-
781
- Extensions can return late hook paths from `resources_discover`:
782
-
783
- ```typescript
784
- import { join } from "node:path";
785
- import type { ExtensionAPI } from "@code-yeongyu/senpi";
786
-
787
- export default function (pi: ExtensionAPI) {
788
- pi.on("resources_discover", (event, ctx) => {
789
- if (event.reason !== "reload") return {};
790
- return {
791
- hookPaths: [join(ctx.cwd, ".senpi", "generated-hooks.json")],
792
- };
793
- });
794
- }
795
- ```
796
-
797
- These paths are runtime sources. They can affect later hook events in the current runtime, but their `SessionStart` hooks do not run for the already-started initial session. On `/hooks reload` or `/reload`, runtime `SessionStart` hooks are visible to the reloaded session. If a runtime source contains `SessionStart`, senpi records a diagnostic: `Runtime SessionStart hooks are loaded for reload or the next session only.`
798
-
799
- #### Not yet supported
800
-
801
- The builtin hooks implementation intentionally does not claim full Claude hook coverage. Unsupported shapes produce warnings or diagnostics and are not executed.
802
-
803
- | Area | Not yet supported |
804
- |------|-------------------|
805
- | Events | `PermissionRequest`, `PermissionDenied`, `SubagentStart`, `SubagentStop`, `Notification`, `Setup`, `UserPromptExpansion`, `PostToolUseFailure`, `PostToolBatch`, `TaskCreated`, `TaskCompleted`, `StopFailure`, `TeammateIdle`, `InstructionsLoaded`, `ConfigChange`, `CwdChanged`, `FileChanged`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay`, `SessionEnd`, `Elicitation`, `ElicitationResult`. |
806
- | Handler types | `prompt`, `agent`, `http`, and `mcp_tool`. |
807
- | Command forms | Exec-form commands, object-valued `command`, separate `args`, `shell`, and command handlers with `async: true`. |
808
- | Command fields | `if`, `asyncRewake`, `terminalSequence`, and `continueOnBlock`. |
809
- | Prompt mutation | UserPromptSubmit prompt replacement fields such as `prompt`, `updatedPrompt`, and `replacementPrompt`. |
810
- | Async behavior | Claude-style async hooks and `asyncRewake`. |
811
- | PreCompact mutation | `customInstructions` does not change compaction in builtin hooks v1. |
812
-
813
- #### omo-codex migration notes
814
-
815
- For omo-codex or Claude-style hook configs, migrate the lowest-risk checks first:
816
-
817
- - Keep existing `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `SessionStart`, `PreCompact`, `PostCompact`, and `Stop` command hooks if they use shell command strings.
818
- - Move `http`, `mcp_tool`, `prompt`, and `agent` hooks to senpi extensions or tools.
819
- - Replace `if` conditions with logic inside the command script or with matcher strings for tool/lifecycle selection.
820
- - Treat `Notification`, subagent/task/teammate/worktree events, and prompt replacement as deferred; document them in plugin README files instead of assuming execution.
821
- - When the host uses the plugin manifest helper, use `PLUGIN_ROOT` and `PLUGIN_DATA` for plugin-relative scripts and state. Keep secrets out of manifests and hook JSON.
822
-
823
- #### Hook troubleshooting
824
-
825
- If a hook does not run:
826
-
827
- 1. Run `/hooks list` and confirm the hook is present, enabled, and trusted.
828
- 2. Run `/hooks diagnostics` and check for malformed JSON, unsupported fields, untrusted hashes, skipped runtime `SessionStart`, or plugin containment errors.
829
- 3. Confirm the matcher matches the event. Tool events match tool names such as `bash`, `edit`, `write`, `Bash`, `Edit`, and `Write`; lifecycle events match reasons such as `startup`, `reload`, `manual`, and `overflow`.
830
- 4. Confirm the command path works from the project cwd. For plugin commands using `${PLUGIN_ROOT}`, the resolved file must exist inside the plugin root.
831
- 5. Keep stdout as valid JSON or empty. Human-readable logs should go to stderr, and secret-bearing logs should be avoided entirely.
832
- 6. After editing hook JSON or scripts, run `/hooks reload`, then `/hooks list` again. If the trusted hash changed, trust the hook again.
833
-
834
- If a hook runs but has no effect, check the event support table. Some fields are diagnostic-only by design, such as `PreCompact` `additionalContext` and `customInstructions`, `PostCompact` output fields, and unsupported prompt replacement fields for `UserPromptSubmit`.
835
-
836
- If a hook times out, increase `timeout` in seconds or make the script observe stdin and exit quickly. The default timeout is 600 seconds. Invalid timeout values such as `0`, negative numbers, `NaN`, or infinity are rejected and the command is not started.
837
-
838
388
  ### Session Events
839
389
 
840
390
  See [Session Format](session-format.md) for session storage internals and the SessionManager API.
@@ -878,7 +428,7 @@ pi.on("session_before_switch", async (event, ctx) => {
878
428
  });
879
429
  ```
880
430
 
881
- After a successful switch or new-session action, senpi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "new" | "resume"` and `previousSessionFile`.
431
+ After a successful switch or new-session action, pi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "new" | "resume"` and `previousSessionFile`.
882
432
  Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
883
433
 
884
434
  #### session_before_fork
@@ -895,7 +445,7 @@ pi.on("session_before_fork", async (event, ctx) => {
895
445
  });
896
446
  ```
897
447
 
898
- After a successful fork or clone, senpi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "fork"` and `previousSessionFile`.
448
+ After a successful fork or clone, pi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "fork"` and `previousSessionFile`.
899
449
  Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
900
450
 
901
451
  #### session_before_compact / session_compact
@@ -972,7 +522,7 @@ pi.on("before_agent_start", async (event, ctx) => {
972
522
  // event.systemPrompt - current chained system prompt for this handler
973
523
  // (includes changes from earlier before_agent_start handlers)
974
524
  // event.systemPromptOptions - structured options used to build the system prompt
975
- // .customPrompt - any custom system prompt (from --system-prompt or custom templates)
525
+ // .customPrompt - any custom system prompt (from --system-prompt, SYSTEM.md, or custom templates)
976
526
  // .selectedTools - tools currently active in the prompt
977
527
  // .toolSnippets - one-line descriptions for each tool
978
528
  // .promptGuidelines - custom guideline bullets
@@ -994,7 +544,7 @@ pi.on("before_agent_start", async (event, ctx) => {
994
544
  });
995
545
  ```
996
546
 
997
- The `systemPromptOptions` field gives extensions access to the same structured data senpi uses to build the system prompt. This lets you inspect what senpi has loaded — custom prompts, guidelines, tool snippets, context files, skills — without re-discovering resources or re-parsing flags. Use it when your extension needs to make deep, informed changes to the system prompt while respecting user-provided configuration.
547
+ The `systemPromptOptions` field gives extensions access to the same structured data Pi uses to build the system prompt. This lets you inspect what Pi has loaded — custom prompts, guidelines, tool snippets, context files, skills — without re-discovering resources or re-parsing flags. Use it when your extension needs to make deep, informed changes to the system prompt while respecting user-provided configuration.
998
548
 
999
549
  Inside `before_agent_start`, `event.systemPrompt` and `ctx.getSystemPrompt()` both reflect the chained system prompt as of the current handler. Later `before_agent_start` handlers can still modify it again.
1000
550
 
@@ -1122,7 +672,7 @@ Runs once per provider request; retries reuse the same headers rather than re-fi
1122
672
 
1123
673
  Fired after the provider-specific payload is built, right before the request is sent. Handlers run in extension load order. Returning `undefined` keeps the payload unchanged. Returning any other value replaces the payload for later handlers and for the actual request.
1124
674
 
1125
- This hook can rewrite provider-level system instructions or remove them entirely. Those payload-level changes are not reflected by `ctx.getSystemPrompt()`, which reports senpi's system prompt string rather than the final serialized provider payload.
675
+ This hook can rewrite provider-level system instructions or remove them entirely. Those payload-level changes are not reflected by `ctx.getSystemPrompt()`, which reports Pi's system prompt string rather than the final serialized provider payload.
1126
676
 
1127
677
  ```typescript
1128
678
  pi.on("before_provider_request", (event, ctx) => {
@@ -1195,7 +745,7 @@ Use this to update extension UI when `pi.setThinkingLevel()`, model changes, or
1195
745
 
1196
746
  Fired after `tool_execution_start`, before the tool executes. **Can block.** Use `isToolCallEventType` to narrow and get typed inputs.
1197
747
 
1198
- Before `tool_call` runs, senpi waits for previously emitted Agent events to finish draining through `AgentSession`. This means `ctx.sessionManager` is up to date through the current assistant tool-calling message.
748
+ Before `tool_call` runs, pi waits for previously emitted Agent events to finish draining through `AgentSession`. This means `ctx.sessionManager` is up to date through the current assistant tool-calling message.
1199
749
 
1200
750
  In the default parallel tool execution mode, sibling tool calls from the same assistant message are preflighted sequentially, then executed concurrently. `tool_call` is not guaranteed to see sibling tool results from that same assistant message in `ctx.sessionManager`.
1201
751
 
@@ -1208,7 +758,7 @@ Behavior guarantees:
1208
758
  - Return values from `tool_call` only control blocking via `{ block: true, reason?: string }`
1209
759
 
1210
760
  ```typescript
1211
- import { isToolCallEventType } from "@code-yeongyu/senpi";
761
+ import { isToolCallEventType } from "@earendil-works/pi-coding-agent";
1212
762
 
1213
763
  pi.on("tool_call", async (event, ctx) => {
1214
764
  // event.toolName - "bash", "read", "write", "edit", etc.
@@ -1244,7 +794,7 @@ export type MyToolInput = Static<typeof myToolSchema>;
1244
794
  Use `isToolCallEventType` with explicit type parameters:
1245
795
 
1246
796
  ```typescript
1247
- import { isToolCallEventType } from "@code-yeongyu/senpi";
797
+ import { isToolCallEventType } from "@earendil-works/pi-coding-agent";
1248
798
  import type { MyToolInput } from "my-extension";
1249
799
 
1250
800
  pi.on("tool_call", (event) => {
@@ -1268,7 +818,7 @@ In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in
1268
818
  Use `ctx.signal` for nested async work inside the handler. This lets Esc cancel model calls, `fetch()`, and other abort-aware operations started by the extension.
1269
819
 
1270
820
  ```typescript
1271
- import { isBashToolResult } from "@code-yeongyu/senpi";
821
+ import { isBashToolResult } from "@earendil-works/pi-coding-agent";
1272
822
 
1273
823
  pi.on("tool_result", async (event, ctx) => {
1274
824
  // event.toolName, event.toolCallId, event.input
@@ -1296,7 +846,7 @@ pi.on("tool_result", async (event, ctx) => {
1296
846
  Fired when user executes `!` or `!!` commands. **Can intercept.**
1297
847
 
1298
848
  ```typescript
1299
- import { createLocalBashOperations } from "@code-yeongyu/senpi";
849
+ import { createLocalBashOperations } from "@earendil-works/pi-coding-agent";
1300
850
 
1301
851
  pi.on("user_bash", (event, ctx) => {
1302
852
  // event.command - the bash command
@@ -1306,7 +856,7 @@ pi.on("user_bash", (event, ctx) => {
1306
856
  // Option 1: Provide custom operations (e.g., SSH)
1307
857
  return { operations: remoteBashOps };
1308
858
 
1309
- // Option 2: Wrap senpi's built-in local bash backend
859
+ // Option 2: Wrap pi's built-in local bash backend
1310
860
  const local = createLocalBashOperations();
1311
861
  return {
1312
862
  operations: {
@@ -1439,7 +989,7 @@ Use this for abort-aware nested work started by extension handlers, for example:
1439
989
  - file or process helpers that accept `AbortSignal`
1440
990
 
1441
991
  `ctx.signal` is typically defined during active turn events such as `tool_call`, `tool_result`, `message_update`, and `turn_end`.
1442
- It is usually `undefined` in idle or non-turn contexts such as session events, extension commands, and shortcuts fired while senpi is idle.
992
+ It is usually `undefined` in idle or non-turn contexts such as session events, extension commands, and shortcuts fired while pi is idle.
1443
993
 
1444
994
  ```typescript
1445
995
  pi.on("tool_result", async (event, ctx) => {
@@ -1460,7 +1010,7 @@ Control flow helpers. `ctx.isIdle()` is false while Pi is processing an agent ru
1460
1010
 
1461
1011
  ### ctx.shutdown()
1462
1012
 
1463
- Request a graceful shutdown of senpi.
1013
+ Request a graceful shutdown of pi.
1464
1014
 
1465
1015
  - **Interactive mode:** Deferred until the agent becomes idle (after processing all queued steering and follow-up messages).
1466
1016
  - **RPC mode:** Deferred until the next idle state (after completing the current command response, when waiting for the next command).
@@ -1476,19 +1026,6 @@ pi.on("tool_call", (event, ctx) => {
1476
1026
  });
1477
1027
  ```
1478
1028
 
1479
- ### ctx.updateToolHookStatus()
1480
-
1481
- Only available on the context passed to `tool_call` and `tool_result` handlers. Replaces the label of that handler's live `Running PreToolUse/PostToolUse hook: ...` status row in the TUI, so long-running hooks can report what they are doing. Messages are truncated to 79 characters; calls after the handler finished are ignored.
1482
-
1483
- ```typescript
1484
- pi.on("tool_result", async (event, ctx) => {
1485
- ctx.updateToolHookStatus?.("Checking comments");
1486
- await runCommentChecker(event);
1487
- ctx.updateToolHookStatus?.("Collecting diagnostics");
1488
- await collectDiagnostics(event);
1489
- });
1490
- ```
1491
-
1492
1029
  ### ctx.getContextUsage()
1493
1030
 
1494
1031
  Returns current context usage for the active model. Uses last assistant usage when available, then estimates tokens for trailing messages.
@@ -1518,7 +1055,7 @@ ctx.compact({
1518
1055
 
1519
1056
  ### ctx.getSystemPrompt()
1520
1057
 
1521
- Returns senpi's current system prompt string.
1058
+ Returns Pi's current system prompt string.
1522
1059
 
1523
1060
  - During `before_agent_start`, this reflects chained system-prompt changes made so far for the current turn.
1524
1061
  - It does not include later `context` message mutations.
@@ -1538,7 +1075,7 @@ Command handlers receive `ExtensionCommandContext`, which extends `ExtensionCont
1538
1075
 
1539
1076
  ### ctx.getSystemPromptOptions()
1540
1077
 
1541
- Returns the base inputs senpi currently uses to build the system prompt.
1078
+ Returns the base inputs Pi currently uses to build the system prompt.
1542
1079
 
1543
1080
  ```typescript
1544
1081
  const options = ctx.getSystemPromptOptions();
@@ -1661,7 +1198,7 @@ Options:
1661
1198
  To discover available sessions, use the static `SessionManager.list()` or `SessionManager.listAll()` methods:
1662
1199
 
1663
1200
  ```typescript
1664
- import { SessionManager } from "@code-yeongyu/senpi";
1201
+ import { SessionManager } from "@earendil-works/pi-coding-agent";
1665
1202
 
1666
1203
  pi.registerCommand("switch", {
1667
1204
  description: "Switch to another session",
@@ -1755,7 +1292,7 @@ Tools run with `ExtensionContext`, so they cannot call `ctx.reload()` directly.
1755
1292
  Example tool the LLM can call to trigger reload:
1756
1293
 
1757
1294
  ```typescript
1758
- import type { ExtensionAPI } from "@code-yeongyu/senpi";
1295
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
1759
1296
  import { Type } from "typebox";
1760
1297
 
1761
1298
  export default function (pi: ExtensionAPI) {
@@ -1873,7 +1410,7 @@ pi.sendUserMessage("What is 2+2?");
1873
1410
  // With content array (text + images)
1874
1411
  pi.sendUserMessage([
1875
1412
  { type: "text", text: "Describe this image:" },
1876
- { type: "image", data: "base64-encoded-data", mimeType: "image/png" },
1413
+ { type: "image", source: { type: "base64", mediaType: "image/png", data: "..." } },
1877
1414
  ]);
1878
1415
 
1879
1416
  // During streaming - must specify delivery mode
@@ -1948,7 +1485,7 @@ Labels persist in the session and survive restarts. Use them to mark important p
1948
1485
 
1949
1486
  Register a command.
1950
1487
 
1951
- If multiple extensions register the same command name, senpi keeps them all and assigns numeric invocation suffixes in load order, for example `/review:1` and `/review:2`.
1488
+ If multiple extensions register the same command name, pi keeps them all and assigns numeric invocation suffixes in load order, for example `/review:1` and `/review:2`.
1952
1489
 
1953
1490
  ```typescript
1954
1491
  pi.registerCommand("stats", {
@@ -2102,41 +1639,6 @@ Typical `sourceInfo.source` values:
2102
1639
  - `sdk` for tools passed via `createAgentSession({ customTools })`
2103
1640
  - extension source metadata for tools registered by extensions
2104
1641
 
2105
- ### pi.executeTool(name, params, options?)
2106
-
2107
- Execute an active tool from extension code using the same wrapped pipeline as a model-dispatched tool call.
2108
-
2109
- ```typescript
2110
- const result = await pi.executeTool("read", { path: "README.md" }, {
2111
- onUpdate: (partial) => {
2112
- // Forward partial AgentToolResult updates into your parent tool UI.
2113
- },
2114
- });
2115
- ```
2116
-
2117
- `params` are prepared and validated against the target tool schema before `tool_call` handlers run. If validation fails, `executeTool` rejects with `ExecuteToolError` code `invalid_params`, the tool is not executed, and no `tool_call` hook fires.
2118
-
2119
- Only active tools can run. Registered but inactive tools reject with code `inactive_tool`; unknown names reject with code `unknown_tool`. Both errors include `toolName` and `activeTools`.
2120
-
2121
- When pre-tool hooks block, `executeTool` rejects with code `blocked` and the hook reason. When hooks mutate `event.input`, the executed tool sees the mutated arguments. `tool_result` hooks can replace the returned content, details, or error state before the promise resolves.
2122
-
2123
- The optional `signal` and `onUpdate` are forwarded directly to the tool execution callback. Bridge-invoked calls emit `tool_call` and `tool_result` extension events, but do not emit `tool_execution_start`, `tool_execution_update`, or `tool_execution_end` UI events; they are subcalls of the parent extension/tool UI.
2124
-
2125
- The SDK exports `ExecuteToolOptions<TDetails>`, `ExecuteToolResult<TDetails>`, `ExecuteToolUpdateCallback<TDetails>`, `ExecuteToolError`, and `ExecuteToolErrorCode`. `ExecuteToolResult<TDetails>` is the normal `AgentToolResult<TDetails>` returned by the wrapped tool after `tool_result` hooks have run.
2126
-
2127
- ```typescript
2128
- try {
2129
- const result = await pi.executeTool("bash", { command: "pwd" });
2130
- ctx.ui.notify(result.content);
2131
- } catch (error) {
2132
- if (error instanceof ExecuteToolError && error.code === "blocked") {
2133
- ctx.ui.notify(error.message, "warning");
2134
- } else {
2135
- throw error;
2136
- }
2137
- }
2138
- ```
2139
-
2140
1642
  ### pi.setModel(model)
2141
1643
 
2142
1644
  Set the current model. Returns `false` if no API key is available for the model. See [models.md](models.md) for configuring custom models.
@@ -2175,7 +1677,7 @@ Register or override a model provider dynamically. Useful for proxies, custom en
2175
1677
 
2176
1678
  Calls made during the extension factory function are queued and applied once the runner initialises. Calls made after that — for example from a command handler following a user setup flow — take effect immediately without requiring a `/reload`.
2177
1679
 
2178
- If you need to discover models from a remote endpoint, prefer an async extension factory over deferring the fetch to `session_start`. senpi waits for the factory before startup continues, so the registered models are available immediately, including to `senpi --list-models`.
1680
+ Dynamic providers can implement `refreshModels`. Pi calls it during model refresh, publishes the returned list synchronously through the provider, and passes the canonical credential/store/network/signal context. The extension decides whether to persist the catalog through `context.store`; live servers such as llama.cpp can ignore it.
2179
1681
 
2180
1682
  ```typescript
2181
1683
  // Register a new provider with custom models
@@ -2197,6 +1699,26 @@ pi.registerProvider("my-proxy", {
2197
1699
  ]
2198
1700
  });
2199
1701
 
1702
+ // Register a live llama.cpp catalog without persisting discovered models
1703
+ pi.registerProvider("llama.cpp", {
1704
+ baseUrl: "http://localhost:8080/v1",
1705
+ apiKey: "local",
1706
+ api: "openai-completions",
1707
+ async refreshModels({ signal }) {
1708
+ const response = await fetch("http://localhost:8080/v1/models", { signal });
1709
+ const { data } = await response.json();
1710
+ return data.map(({ id }) => ({
1711
+ id,
1712
+ name: id,
1713
+ reasoning: false,
1714
+ input: ["text"],
1715
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1716
+ contextWindow: 128000,
1717
+ maxTokens: 16384
1718
+ }));
1719
+ }
1720
+ });
1721
+
2200
1722
  // Override baseUrl for an existing provider (keeps all models)
2201
1723
  pi.registerProvider("anthropic", {
2202
1724
  baseUrl: "https://proxy.example.com"
@@ -2234,6 +1756,7 @@ pi.registerProvider("corporate-ai", {
2234
1756
  - `headers` - Custom headers to include in requests.
2235
1757
  - `authHeader` - If true, adds `Authorization: Bearer` header automatically.
2236
1758
  - `models` - Array of model definitions. If provided, replaces all existing models for this provider. Model definitions can set `baseUrl` to override the provider endpoint for that model.
1759
+ - `refreshModels` - Async dynamic discovery callback. Its returned models replace extension-provided models. Use the scoped `context.store` only when results should persist.
2237
1760
  - `oauth` - OAuth provider config for `/login` support. When provided, the provider appears in the login menu.
2238
1761
  - `streamSimple` - Custom streaming implementation for non-standard APIs.
2239
1762
 
@@ -2309,7 +1832,7 @@ Pass the real target file path to `withFileMutationQueue()`, not the raw user ar
2309
1832
  Queue the entire mutation window on that target path. That includes read-modify-write logic, not just the final write.
2310
1833
 
2311
1834
  ```typescript
2312
- import { withFileMutationQueue } from "@code-yeongyu/senpi";
1835
+ import { withFileMutationQueue } from "@earendil-works/pi-coding-agent";
2313
1836
  import { mkdir, readFile, writeFile } from "node:fs/promises";
2314
1837
  import { dirname, resolve } from "node:path";
2315
1838
 
@@ -2405,7 +1928,7 @@ async execute(toolCallId, params) {
2405
1928
 
2406
1929
  **Important:** Use `StringEnum` from `@earendil-works/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API.
2407
1930
 
2408
- **Argument preparation:** `prepareArguments(args)` is optional. If defined, it runs before schema validation and before `execute()`. Use it to mimic an older accepted input shape when senpi resumes an older session whose stored tool call arguments no longer match the current schema. Return the object you want validated against `parameters`. Keep the public schema strict. Do not add deprecated compatibility fields to `parameters` just to keep old resumed sessions working.
1931
+ **Argument preparation:** `prepareArguments(args)` is optional. If defined, it runs before schema validation and before `execute()`. Use it to mimic an older accepted input shape when pi resumes an older session whose stored tool call arguments no longer match the current schema. Return the object you want validated against `parameters`. Keep the public schema strict. Do not add deprecated compatibility fields to `parameters` just to keep old resumed sessions working.
2409
1932
 
2410
1933
  Example: an older session may contain an `edit` tool call with top-level `oldText` and `newText`, while the current schema only accepts `edits: [{ oldText, newText }]`.
2411
1934
 
@@ -2458,13 +1981,13 @@ Extensions can override built-in tools (`read`, `bash`, `edit`, `write`, `grep`,
2458
1981
 
2459
1982
  ```bash
2460
1983
  # Extension's read tool replaces built-in read
2461
- senpi -e ./tool-override.ts
1984
+ pi -e ./tool-override.ts
2462
1985
  ```
2463
1986
 
2464
1987
  Alternatively, use `--no-builtin-tools` to start without any built-in tools while keeping extension tools enabled:
2465
1988
  ```bash
2466
1989
  # No built-in tools, only extension tools
2467
- senpi --no-builtin-tools -e ./my-extension.ts
1990
+ pi --no-builtin-tools -e ./my-extension.ts
2468
1991
  ```
2469
1992
 
2470
1993
  See [examples/extensions/tool-override.ts](../examples/extensions/tool-override.ts) for a complete example that overrides `read` with logging and access control.
@@ -2489,7 +2012,7 @@ Built-in tool implementations:
2489
2012
  Built-in tools support pluggable operations for delegating to remote systems (SSH, containers, etc.):
2490
2013
 
2491
2014
  ```typescript
2492
- import { createReadTool, createBashTool, type ReadOperations } from "@code-yeongyu/senpi";
2015
+ import { createReadTool, createBashTool, type ReadOperations } from "@earendil-works/pi-coding-agent";
2493
2016
 
2494
2017
  // Create tool with custom operations
2495
2018
  const remoteRead = createReadTool(cwd, {
@@ -2515,12 +2038,12 @@ pi.registerTool({
2515
2038
 
2516
2039
  **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
2517
2040
 
2518
- For `user_bash`, extensions can reuse senpi's local shell backend via `createLocalBashOperations()` instead of reimplementing local process spawning, shell resolution, and process-tree termination.
2041
+ For `user_bash`, extensions can reuse pi's local shell backend via `createLocalBashOperations()` instead of reimplementing local process spawning, shell resolution, and process-tree termination.
2519
2042
 
2520
2043
  The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution:
2521
2044
 
2522
2045
  ```typescript
2523
- import { createBashTool } from "@code-yeongyu/senpi";
2046
+ import { createBashTool } from "@earendil-works/pi-coding-agent";
2524
2047
 
2525
2048
  const bashTool = createBashTool(cwd, {
2526
2049
  spawnHook: ({ command, cwd, env }) => ({
@@ -2550,7 +2073,7 @@ import {
2550
2073
  formatSize, // Human-readable size (e.g., "50KB", "1.5MB")
2551
2074
  DEFAULT_MAX_BYTES, // 50KB
2552
2075
  DEFAULT_MAX_LINES, // 2000
2553
- } from "@code-yeongyu/senpi";
2076
+ } from "@earendil-works/pi-coding-agent";
2554
2077
 
2555
2078
  async execute(toolCallId, params, signal, onUpdate, ctx) {
2556
2079
  const output = await runCommand();
@@ -2633,7 +2156,6 @@ pi.registerTool({
2633
2156
  - `lastComponent` - the previously returned component for that slot, if any
2634
2157
  - `invalidate()` - request a rerender of this tool row
2635
2158
  - `toolCallId`, `cwd`, `executionStarted`, `argsComplete`, `isPartial`, `expanded`, `showImages`, `isError`
2636
- - `imageProtocol` - optional for compatibility with older hosts; when present it is `"kitty"`, `"iterm2"`, or `null` when the terminal cannot render inline images. With an active protocol, the host owns native image rendering and protocol fallbacks for image result blocks, so custom renderers can suppress duplicate image indicators.
2637
2159
 
2638
2160
  Use `context.state` for cross-slot shared state. Keep slot-local caches on the returned component instance when you want to reuse and mutate the same component across renders.
2639
2161
 
@@ -2687,7 +2209,7 @@ If a slot intentionally has no visible content, return an empty `Component` such
2687
2209
  Use `keyHint()` to display keybinding hints that respect the active keybinding configuration:
2688
2210
 
2689
2211
  ```typescript
2690
- import { keyHint } from "@code-yeongyu/senpi";
2212
+ import { keyHint } from "@earendil-works/pi-coding-agent";
2691
2213
 
2692
2214
  renderResult(result, { expanded }, theme, context) {
2693
2215
  let text = theme.fg("success", "✓ Done");
@@ -2992,7 +2514,7 @@ ctx.ui.setFooter((tui, theme) => ({
2992
2514
  ctx.ui.setFooter(undefined); // Restore built-in footer
2993
2515
 
2994
2516
  // Terminal title
2995
- ctx.ui.setTitle("senpi - my-project");
2517
+ ctx.ui.setTitle("pi - my-project");
2996
2518
 
2997
2519
  // Editor text
2998
2520
  ctx.ui.setEditorText("Prefill text");
@@ -3165,7 +2687,7 @@ See [tui.md](tui.md) for the full `OverlayOptions` and `OverlayHandle` API and [
3165
2687
  Replace the main input editor with a custom implementation (vim mode, emacs mode, etc.):
3166
2688
 
3167
2689
  ```typescript
3168
- import { CustomEditor, type ExtensionAPI } from "@code-yeongyu/senpi";
2690
+ import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
3169
2691
  import { matchesKey } from "@earendil-works/pi-tui";
3170
2692
 
3171
2693
  class VimEditor extends CustomEditor {
@@ -3275,7 +2797,7 @@ theme.strikethrough(text)
3275
2797
  For syntax highlighting in custom tool renderers:
3276
2798
 
3277
2799
  ```typescript
3278
- import { highlightCode, getLanguageFromPath } from "@code-yeongyu/senpi";
2800
+ import { highlightCode, getLanguageFromPath } from "@earendil-works/pi-coding-agent";
3279
2801
 
3280
2802
  // Highlight code with explicit language
3281
2803
  const highlighted = highlightCode("const x = 1;", "typescript", theme);
@@ -3368,6 +2890,7 @@ All examples in [examples/extensions/](../examples/extensions/).
3368
2890
  | `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
3369
2891
  | `sandbox/` | Sandboxed tool execution | Tool operations |
3370
2892
  | `gondolin/` | Route built-in tools and `!` commands into a Gondolin micro-VM | Tool operations, built-in tool overrides, `on("user_bash")` |
2893
+ | `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
3371
2894
  | **Games** |||
3372
2895
  | `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
3373
2896
  | `space-invaders.ts` | Space Invaders game | `registerCommand`, `ui.custom` |