@code-yeongyu/senpi 2026.8.10 → 2026.8.11-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/brand-dir-migration.d.ts +28 -0
  3. package/dist/brand-dir-migration.d.ts.map +1 -0
  4. package/dist/brand-dir-migration.js +77 -0
  5. package/dist/brand-dir-migration.js.map +1 -0
  6. package/dist/cli/grok-neo-gate.d.ts +0 -8
  7. package/dist/cli/grok-neo-gate.d.ts.map +1 -1
  8. package/dist/cli/grok-neo-gate.js +4 -2
  9. package/dist/cli/grok-neo-gate.js.map +1 -1
  10. package/dist/cli-main.d.ts +1 -1
  11. package/dist/cli-main.d.ts.map +1 -1
  12. package/dist/cli-main.js +4 -0
  13. package/dist/cli-main.js.map +1 -1
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +3 -2
  17. package/dist/cli.js.map +1 -1
  18. package/dist/config.d.ts +27 -1
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +41 -9
  21. package/dist/config.js.map +1 -1
  22. package/dist/core/agent-session.d.ts +8 -2
  23. package/dist/core/agent-session.d.ts.map +1 -1
  24. package/dist/core/agent-session.js +65 -8
  25. package/dist/core/agent-session.js.map +1 -1
  26. package/dist/core/brand.d.ts +79 -0
  27. package/dist/core/brand.d.ts.map +1 -0
  28. package/dist/core/brand.js +141 -0
  29. package/dist/core/brand.js.map +1 -0
  30. package/dist/core/dynamic-prompt/identity.d.ts.map +1 -1
  31. package/dist/core/dynamic-prompt/identity.js +2 -1
  32. package/dist/core/dynamic-prompt/identity.js.map +1 -1
  33. package/dist/core/experimental.d.ts.map +1 -1
  34. package/dist/core/experimental.js +2 -1
  35. package/dist/core/experimental.js.map +1 -1
  36. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts +2 -0
  37. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts.map +1 -0
  38. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js +24 -0
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js.map +1 -0
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts +4 -0
  41. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts.map +1 -1
  42. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js +5 -2
  43. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js.map +1 -1
  44. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts +6 -1
  45. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts.map +1 -1
  46. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js +16 -0
  47. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js.map +1 -1
  48. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.d.ts.map +1 -1
  49. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js +10 -1
  50. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js.map +1 -1
  51. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/compaction/log.js +2 -1
  53. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  54. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.d.ts.map +1 -1
  55. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js +4 -4
  56. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js.map +1 -1
  57. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/goal/index.js +5 -0
  59. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  60. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +2 -2
  61. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  62. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +3 -3
  63. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  64. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/goal/monitor-continuation.js +6 -0
  66. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  67. package/dist/core/extensions/builtin/goal/store.d.ts +3 -2
  68. package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/goal/store.js +128 -101
  70. package/dist/core/extensions/builtin/goal/store.js.map +1 -1
  71. package/dist/core/extensions/builtin/goal/transitions.js +2 -1
  72. package/dist/core/extensions/builtin/goal/transitions.js.map +1 -1
  73. package/dist/core/extensions/builtin/help/index.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/help/index.js +3 -2
  75. package/dist/core/extensions/builtin/help/index.js.map +1 -1
  76. package/dist/core/extensions/builtin/imagegen/auth.d.ts +45 -0
  77. package/dist/core/extensions/builtin/imagegen/auth.d.ts.map +1 -0
  78. package/dist/core/extensions/builtin/imagegen/auth.js +137 -0
  79. package/dist/core/extensions/builtin/imagegen/auth.js.map +1 -0
  80. package/dist/core/extensions/builtin/imagegen/index.d.ts +5 -0
  81. package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -0
  82. package/dist/core/extensions/builtin/imagegen/index.js +46 -0
  83. package/dist/core/extensions/builtin/imagegen/index.js.map +1 -0
  84. package/dist/core/extensions/builtin/imagegen/paths.d.ts +26 -0
  85. package/dist/core/extensions/builtin/imagegen/paths.d.ts.map +1 -0
  86. package/dist/core/extensions/builtin/imagegen/paths.js +52 -0
  87. package/dist/core/extensions/builtin/imagegen/paths.js.map +1 -0
  88. package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +67 -0
  89. package/dist/core/extensions/builtin/imagegen/state.d.ts +26 -0
  90. package/dist/core/extensions/builtin/imagegen/state.d.ts.map +1 -0
  91. package/dist/core/extensions/builtin/imagegen/state.js +35 -0
  92. package/dist/core/extensions/builtin/imagegen/state.js.map +1 -0
  93. package/dist/core/extensions/builtin/imagegen/tool.d.ts +31 -0
  94. package/dist/core/extensions/builtin/imagegen/tool.d.ts.map +1 -0
  95. package/dist/core/extensions/builtin/imagegen/tool.js +174 -0
  96. package/dist/core/extensions/builtin/imagegen/tool.js.map +1 -0
  97. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  98. package/dist/core/extensions/builtin/index.js +9 -1
  99. package/dist/core/extensions/builtin/index.js.map +1 -1
  100. package/dist/core/extensions/builtin/mcp/control-inventory.d.ts +14 -0
  101. package/dist/core/extensions/builtin/mcp/control-inventory.d.ts.map +1 -0
  102. package/dist/core/extensions/builtin/mcp/control-inventory.js +22 -0
  103. package/dist/core/extensions/builtin/mcp/control-inventory.js.map +1 -0
  104. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +2 -44
  105. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
  106. package/dist/core/extensions/builtin/mcp/expose/native-search.js +3 -97
  107. package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
  108. package/dist/core/extensions/builtin/mcp/expose/proxy.d.ts.map +1 -1
  109. package/dist/core/extensions/builtin/mcp/expose/proxy.js +15 -4
  110. package/dist/core/extensions/builtin/mcp/expose/proxy.js.map +1 -1
  111. package/dist/core/extensions/builtin/mcp/expose/session.d.ts +2 -1
  112. package/dist/core/extensions/builtin/mcp/expose/session.d.ts.map +1 -1
  113. package/dist/core/extensions/builtin/mcp/expose/session.js +2 -2
  114. package/dist/core/extensions/builtin/mcp/expose/session.js.map +1 -1
  115. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +13 -11
  116. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
  117. package/dist/core/extensions/builtin/mcp/expose/tier-b.js +58 -59
  118. package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
  119. package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
  120. package/dist/core/extensions/builtin/mcp/index.js +28 -36
  121. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  122. package/dist/core/extensions/builtin/mcp/service-register.d.ts +2 -1
  123. package/dist/core/extensions/builtin/mcp/service-register.d.ts.map +1 -1
  124. package/dist/core/extensions/builtin/mcp/service-register.js +2 -2
  125. package/dist/core/extensions/builtin/mcp/service-register.js.map +1 -1
  126. package/dist/core/extensions/builtin/mcp/service-types.d.ts +4 -0
  127. package/dist/core/extensions/builtin/mcp/service-types.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/mcp/service-types.js.map +1 -1
  129. package/dist/core/extensions/builtin/mcp/service.d.ts +6 -11
  130. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/mcp/service.js +79 -41
  132. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  133. package/dist/core/extensions/builtin/mcp/wrap.d.ts +2 -0
  134. package/dist/core/extensions/builtin/mcp/wrap.d.ts.map +1 -1
  135. package/dist/core/extensions/builtin/mcp/wrap.js +3 -0
  136. package/dist/core/extensions/builtin/mcp/wrap.js.map +1 -1
  137. package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts +27 -0
  138. package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts.map +1 -0
  139. package/dist/core/extensions/builtin/openai-image-gen/externalize.js +133 -0
  140. package/dist/core/extensions/builtin/openai-image-gen/externalize.js.map +1 -0
  141. package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts +21 -0
  142. package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts.map +1 -0
  143. package/dist/core/extensions/builtin/openai-image-gen/gate.js +63 -0
  144. package/dist/core/extensions/builtin/openai-image-gen/gate.js.map +1 -0
  145. package/dist/core/extensions/builtin/openai-image-gen/index.d.ts +14 -0
  146. package/dist/core/extensions/builtin/openai-image-gen/index.d.ts.map +1 -0
  147. package/dist/core/extensions/builtin/openai-image-gen/index.js +77 -0
  148. package/dist/core/extensions/builtin/openai-image-gen/index.js.map +1 -0
  149. package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts +15 -0
  150. package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts.map +1 -0
  151. package/dist/core/extensions/builtin/openai-image-gen/inject.js +42 -0
  152. package/dist/core/extensions/builtin/openai-image-gen/inject.js.map +1 -0
  153. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  154. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +2 -1
  155. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  156. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
  157. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +2 -1
  158. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
  159. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
  160. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +2 -1
  161. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
  162. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  163. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -1
  164. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  165. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -1
  166. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +6 -5
  167. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -1
  168. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  169. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +2 -1
  170. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  171. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  172. package/dist/core/extensions/builtin/terminal/monitor-notify.js +8 -1
  173. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  174. package/dist/core/extensions/builtin/terminal/notify.d.ts +3 -1
  175. package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
  176. package/dist/core/extensions/builtin/terminal/notify.js +4 -1
  177. package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
  178. package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts +22 -0
  179. package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts.map +1 -0
  180. package/dist/core/extensions/builtin/{mcp/expose → tool-search/engine}/bm25.js +16 -31
  181. package/dist/core/extensions/builtin/tool-search/engine/bm25.js.map +1 -0
  182. package/dist/core/extensions/builtin/tool-search/engine/document.d.ts +14 -0
  183. package/dist/core/extensions/builtin/tool-search/engine/document.d.ts.map +1 -0
  184. package/dist/core/extensions/builtin/tool-search/engine/document.js +2 -0
  185. package/dist/core/extensions/builtin/tool-search/engine/document.js.map +1 -0
  186. package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts +55 -0
  187. package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts.map +1 -0
  188. package/dist/core/extensions/builtin/tool-search/engine/marker.js +189 -0
  189. package/dist/core/extensions/builtin/tool-search/engine/marker.js.map +1 -0
  190. package/dist/core/extensions/builtin/tool-search/index.d.ts +7 -0
  191. package/dist/core/extensions/builtin/tool-search/index.d.ts.map +1 -0
  192. package/dist/core/extensions/builtin/tool-search/index.js +71 -0
  193. package/dist/core/extensions/builtin/tool-search/index.js.map +1 -0
  194. package/dist/core/extensions/builtin/tool-search/native-search.d.ts +52 -0
  195. package/dist/core/extensions/builtin/tool-search/native-search.d.ts.map +1 -0
  196. package/dist/core/extensions/builtin/tool-search/native-search.js +116 -0
  197. package/dist/core/extensions/builtin/tool-search/native-search.js.map +1 -0
  198. package/dist/core/extensions/builtin/tool-search/service.d.ts +38 -0
  199. package/dist/core/extensions/builtin/tool-search/service.d.ts.map +1 -0
  200. package/dist/core/extensions/builtin/tool-search/service.js +200 -0
  201. package/dist/core/extensions/builtin/tool-search/service.js.map +1 -0
  202. package/dist/core/extensions/builtin/tool-search/tool.d.ts +21 -0
  203. package/dist/core/extensions/builtin/tool-search/tool.d.ts.map +1 -0
  204. package/dist/core/extensions/builtin/tool-search/tool.js +95 -0
  205. package/dist/core/extensions/builtin/tool-search/tool.js.map +1 -0
  206. package/dist/core/extensions/loader.d.ts.map +1 -1
  207. package/dist/core/extensions/loader.js +3 -0
  208. package/dist/core/extensions/loader.js.map +1 -1
  209. package/dist/core/extensions/types.d.ts +44 -4
  210. package/dist/core/extensions/types.d.ts.map +1 -1
  211. package/dist/core/extensions/types.js +11 -0
  212. package/dist/core/extensions/types.js.map +1 -1
  213. package/dist/core/footer-data-provider.d.ts +1 -4
  214. package/dist/core/footer-data-provider.d.ts.map +1 -1
  215. package/dist/core/footer-data-provider.js +0 -7
  216. package/dist/core/footer-data-provider.js.map +1 -1
  217. package/dist/core/generated-shim-banner.d.ts +15 -0
  218. package/dist/core/generated-shim-banner.d.ts.map +1 -0
  219. package/dist/core/generated-shim-banner.js +26 -0
  220. package/dist/core/generated-shim-banner.js.map +1 -0
  221. package/dist/core/model-runtime.d.ts.map +1 -1
  222. package/dist/core/model-runtime.js +7 -3
  223. package/dist/core/model-runtime.js.map +1 -1
  224. package/dist/core/package-manager.d.ts.map +1 -1
  225. package/dist/core/package-manager.js +2 -1
  226. package/dist/core/package-manager.js.map +1 -1
  227. package/dist/core/provider-composer.d.ts +10 -1
  228. package/dist/core/provider-composer.d.ts.map +1 -1
  229. package/dist/core/provider-composer.js +9 -0
  230. package/dist/core/provider-composer.js.map +1 -1
  231. package/dist/core/resource-loader.d.ts.map +1 -1
  232. package/dist/core/resource-loader.js +3 -5
  233. package/dist/core/resource-loader.js.map +1 -1
  234. package/dist/core/session-log.d.ts.map +1 -1
  235. package/dist/core/session-log.js +4 -2
  236. package/dist/core/session-log.js.map +1 -1
  237. package/dist/core/settings-manager.d.ts.map +1 -1
  238. package/dist/core/settings-manager.js +3 -2
  239. package/dist/core/settings-manager.js.map +1 -1
  240. package/dist/core/telemetry.d.ts.map +1 -1
  241. package/dist/core/telemetry.js +2 -1
  242. package/dist/core/telemetry.js.map +1 -1
  243. package/dist/core/timings.d.ts +0 -4
  244. package/dist/core/timings.d.ts.map +1 -1
  245. package/dist/core/timings.js +2 -1
  246. package/dist/core/timings.js.map +1 -1
  247. package/dist/inspector-policy.d.ts.map +1 -1
  248. package/dist/inspector-policy.js +2 -1
  249. package/dist/inspector-policy.js.map +1 -1
  250. package/dist/main.d.ts.map +1 -1
  251. package/dist/main.js +5 -4
  252. package/dist/main.js.map +1 -1
  253. package/dist/migrations.d.ts.map +1 -1
  254. package/dist/migrations.js +4 -0
  255. package/dist/migrations.js.map +1 -1
  256. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  257. package/dist/modes/interactive/components/footer.js +1 -8
  258. package/dist/modes/interactive/components/footer.js.map +1 -1
  259. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  260. package/dist/modes/interactive/interactive-mode.js +6 -7
  261. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  262. package/dist/modes/interactive/tips/catalog/cli-tips.d.ts.map +1 -1
  263. package/dist/modes/interactive/tips/catalog/cli-tips.js +2 -1
  264. package/dist/modes/interactive/tips/catalog/cli-tips.js.map +1 -1
  265. package/dist/modes/interactive/tips/catalog/ethos-tips.d.ts.map +1 -1
  266. package/dist/modes/interactive/tips/catalog/ethos-tips.js +4 -3
  267. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  268. package/dist/modes/interactive/tips/catalog/model-tips.d.ts.map +1 -1
  269. package/dist/modes/interactive/tips/catalog/model-tips.js +2 -1
  270. package/dist/modes/interactive/tips/catalog/model-tips.js.map +1 -1
  271. package/dist/modes/interactive/tips/catalog/session-tips.d.ts.map +1 -1
  272. package/dist/modes/interactive/tips/catalog/session-tips.js +2 -1
  273. package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
  274. package/dist/modes/interactive/tips/catalog/settings-tips.d.ts.map +1 -1
  275. package/dist/modes/interactive/tips/catalog/settings-tips.js +3 -2
  276. package/dist/modes/interactive/tips/catalog/settings-tips.js.map +1 -1
  277. package/dist/modes/interactive/tips/catalog/workspace-tips.d.ts.map +1 -1
  278. package/dist/modes/interactive/tips/catalog/workspace-tips.js +4 -3
  279. package/dist/modes/interactive/tips/catalog/workspace-tips.js.map +1 -1
  280. package/dist/modes/provider-native-rendering.d.ts.map +1 -1
  281. package/dist/modes/provider-native-rendering.js +33 -0
  282. package/dist/modes/provider-native-rendering.js.map +1 -1
  283. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  284. package/dist/modes/rpc/connection-handler.js +130 -4
  285. package/dist/modes/rpc/connection-handler.js.map +1 -1
  286. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  287. package/dist/modes/rpc/rpc-mode.js +2 -1
  288. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  289. package/dist/modes/rpc/rpc-types.d.ts +31 -0
  290. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  291. package/dist/modes/rpc/rpc-types.js.map +1 -1
  292. package/dist/nearest-parent-config.d.ts +6 -1
  293. package/dist/nearest-parent-config.d.ts.map +1 -1
  294. package/dist/nearest-parent-config.js +18 -2
  295. package/dist/nearest-parent-config.js.map +1 -1
  296. package/dist/package-manager-cli.d.ts.map +1 -1
  297. package/dist/package-manager-cli.js +13 -1
  298. package/dist/package-manager-cli.js.map +1 -1
  299. package/dist/rpc-entry.js +2 -0
  300. package/dist/rpc-entry.js.map +1 -1
  301. package/dist/self-update-bootstrap.d.ts.map +1 -1
  302. package/dist/self-update-bootstrap.js +6 -0
  303. package/dist/self-update-bootstrap.js.map +1 -1
  304. package/dist/senpi +3 -2
  305. package/dist/utils/pi-user-agent.d.ts +1 -1
  306. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  307. package/dist/utils/pi-user-agent.js +4 -3
  308. package/dist/utils/pi-user-agent.js.map +1 -1
  309. package/dist/utils/tools-manager.d.ts.map +1 -1
  310. package/dist/utils/tools-manager.js +2 -1
  311. package/dist/utils/tools-manager.js.map +1 -1
  312. package/dist/utils/version-check.d.ts +3 -0
  313. package/dist/utils/version-check.d.ts.map +1 -1
  314. package/dist/utils/version-check.js +37 -6
  315. package/dist/utils/version-check.js.map +1 -1
  316. package/dist/valid-cwd.d.ts +2 -0
  317. package/dist/valid-cwd.d.ts.map +1 -0
  318. package/dist/valid-cwd.js +14 -0
  319. package/dist/valid-cwd.js.map +1 -0
  320. package/docs/environment-variables.md +7 -0
  321. package/docs/extensions.md +50 -13
  322. package/docs/mcp.md +2 -0
  323. package/docs/rpc.md +54 -0
  324. package/docs/skills.md +8 -0
  325. package/examples/extensions/searchable-tools.ts +49 -0
  326. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +36 -0
  327. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  328. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +5 -1
  330. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +4 -1
  332. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  333. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
  334. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  335. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +9 -0
  336. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  337. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  338. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  339. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +4 -2
  341. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  343. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +7 -3
  344. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  345. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts +8 -0
  346. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts.map +1 -0
  347. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js +222 -0
  348. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js.map +1 -0
  349. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts +3 -0
  350. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts.map +1 -0
  351. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js +10 -0
  352. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js.map +1 -0
  353. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  354. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +113 -4
  355. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  357. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +1 -0
  358. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  359. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts +5 -0
  360. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
  361. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +2 -1
  362. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  363. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts.map +1 -1
  364. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js +2 -1
  365. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js.map +1 -1
  366. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +10 -0
  367. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  368. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  369. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +32 -0
  370. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  371. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +32 -0
  372. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  373. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  374. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  375. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  376. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  377. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  378. package/node_modules/@earendil-works/pi-ai/dist/models.js +36 -13
  379. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  380. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts +2 -0
  381. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts.map +1 -1
  382. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.js.map +1 -1
  383. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  384. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -1
  385. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  386. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  387. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  388. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  389. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  390. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  391. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  392. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  393. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts +1 -0
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts.map +1 -1
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js +18 -0
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js.map +1 -1
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts +3 -0
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts.map +1 -0
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js +16 -0
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js.map +1 -0
  401. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +1 -1
  402. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  404. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +7 -0
  406. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts +14 -0
  408. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts.map +1 -0
  409. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js +24 -0
  410. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js.map +1 -0
  411. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  412. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.d.ts.map +1 -1
  413. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js +11 -3
  414. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js.map +1 -1
  415. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  416. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  417. package/package.json +8 -8
  418. package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts +0 -30
  419. package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts.map +0 -1
  420. package/dist/core/extensions/builtin/mcp/expose/bm25.js.map +0 -1
  421. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts +0 -15
  422. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts.map +0 -1
  423. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js +0 -33
  424. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js.map +0 -1
  425. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +0 -43
  426. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +0 -1
  427. package/dist/core/extensions/builtin/mcp/expose/tool-search.js +0 -125
  428. package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +0 -1
  429. package/dist/core/omo-native-detect.d.ts +0 -3
  430. package/dist/core/omo-native-detect.d.ts.map +0 -1
  431. package/dist/core/omo-native-detect.js +0 -64
  432. package/dist/core/omo-native-detect.js.map +0 -1
  433. package/dist/core/omo-native-detect.test.d.ts +0 -2
  434. package/dist/core/omo-native-detect.test.d.ts.map +0 -1
  435. package/dist/core/omo-native-detect.test.js +0 -47
  436. package/dist/core/omo-native-detect.test.js.map +0 -1
  437. package/dist/modes/interactive/components/footer-omo-native-badge.test.d.ts +0 -2
  438. package/dist/modes/interactive/components/footer-omo-native-badge.test.d.ts.map +0 -1
  439. package/dist/modes/interactive/components/footer-omo-native-badge.test.js +0 -52
  440. package/dist/modes/interactive/components/footer-omo-native-badge.test.js.map +0 -1
@@ -1,12 +1,13 @@
1
+ import { APP_NAME } from "../../../../config.js";
1
2
  import { buildHelpMarkdown } from "../../../../modes/interactive/help-content.js";
2
3
  import { HELP_OVERLAY_OPTIONS, HelpPanel } from "./panel.js";
3
- const NON_TUI_HELP = "Interactive /help is available in TUI mode; run senpi --help for CLI usage.";
4
+ const NON_TUI_HELP = `Interactive /help is available in TUI mode; run ${APP_NAME} --help for CLI usage.`;
4
5
  export default function helpExtension(pi) {
5
6
  pi.registerCommand("keybindings", {
6
7
  description: "Open your keybindings.json in $EDITOR and reload it live",
7
8
  handler: async (_args, ctx) => {
8
9
  if (ctx.mode !== "tui") {
9
- ctx.ui.notify("Interactive /keybindings opens your config in $EDITOR and reloads it; run senpi in TUI mode to use it.", "info");
10
+ ctx.ui.notify(`Interactive /keybindings opens your config in $EDITOR and reloads it; run ${APP_NAME} in TUI mode to use it.`, "info");
10
11
  return;
11
12
  }
12
13
  // In TUI mode interactive-mode's text dispatch handles /keybindings first.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,YAAY,GAAG,6EAA6E,CAAC;AAEnG,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAgB;IACrD,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE;QACjC,WAAW,EAAE,0DAA0D;QACvE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,wGAAwG,EACxG,MAAM,CACN,CAAC;gBACF,OAAO;YACR,CAAC;YACD,2EAA2E;QAC5E,CAAC;KACD,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,2CAA2C;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBACpC,OAAO;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC5E,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAC7F,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CACvD,CAAC;QACH,CAAC;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { buildHelpMarkdown } from \"../../../../modes/interactive/help-content.ts\";\nimport type { ExtensionAPI } from \"../../types.ts\";\nimport { HELP_OVERLAY_OPTIONS, HelpPanel } from \"./panel.ts\";\n\nconst NON_TUI_HELP = \"Interactive /help is available in TUI mode; run senpi --help for CLI usage.\";\n\nexport default function helpExtension(pi: ExtensionAPI): void {\n\tpi.registerCommand(\"keybindings\", {\n\t\tdescription: \"Open your keybindings.json in $EDITOR and reload it live\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"Interactive /keybindings opens your config in $EDITOR and reloads it; run senpi in TUI mode to use it.\",\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In TUI mode interactive-mode's text dispatch handles /keybindings first.\n\t\t},\n\t});\n\n\tpi.registerCommand(\"help\", {\n\t\tdescription: \"Show usage, keybindings, and all commands\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(NON_TUI_HELP, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst markdown = buildHelpMarkdown({ extensionCommands: pi.getCommands() });\n\t\t\tawait ctx.ui.custom<void>(\n\t\t\t\t(tui, theme, keybindings, done) => new HelpPanel({ markdown, tui, theme, keybindings, done }),\n\t\t\t\t{ overlay: true, overlayOptions: HELP_OVERLAY_OPTIONS },\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,YAAY,GAAG,mDAAmD,QAAQ,wBAAwB,CAAC;AAEzG,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAgB;IACrD,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE;QACjC,WAAW,EAAE,0DAA0D;QACvE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,6EAA6E,QAAQ,yBAAyB,EAC9G,MAAM,CACN,CAAC;gBACF,OAAO;YACR,CAAC;YACD,2EAA2E;QAC5E,CAAC;KACD,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,2CAA2C;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBACpC,OAAO;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC5E,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAC7F,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CACvD,CAAC;QACH,CAAC;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport { buildHelpMarkdown } from \"../../../../modes/interactive/help-content.ts\";\nimport type { ExtensionAPI } from \"../../types.ts\";\nimport { HELP_OVERLAY_OPTIONS, HelpPanel } from \"./panel.ts\";\n\nconst NON_TUI_HELP = `Interactive /help is available in TUI mode; run ${APP_NAME} --help for CLI usage.`;\n\nexport default function helpExtension(pi: ExtensionAPI): void {\n\tpi.registerCommand(\"keybindings\", {\n\t\tdescription: \"Open your keybindings.json in $EDITOR and reload it live\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Interactive /keybindings opens your config in $EDITOR and reloads it; run ${APP_NAME} in TUI mode to use it.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In TUI mode interactive-mode's text dispatch handles /keybindings first.\n\t\t},\n\t});\n\n\tpi.registerCommand(\"help\", {\n\t\tdescription: \"Show usage, keybindings, and all commands\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(NON_TUI_HELP, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst markdown = buildHelpMarkdown({ extensionCommands: pi.getCommands() });\n\t\t\tawait ctx.ui.custom<void>(\n\t\t\t\t(tui, theme, keybindings, done) => new HelpPanel({ markdown, tui, theme, keybindings, done }),\n\t\t\t\t{ overlay: true, overlayOptions: HELP_OVERLAY_OPTIONS },\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
@@ -0,0 +1,45 @@
1
+ export interface ImageGenAuthModel {
2
+ provider: string;
3
+ id: string;
4
+ baseUrl: string;
5
+ api?: string;
6
+ }
7
+ export type ImageGenRegistryAuthResult = {
8
+ ok: true;
9
+ apiKey?: string;
10
+ headers?: Record<string, string>;
11
+ } | {
12
+ ok: false;
13
+ error: string;
14
+ };
15
+ export interface ImageGenProviderAuthResult {
16
+ auth: {
17
+ apiKey?: string;
18
+ headers?: Record<string, string | null>;
19
+ };
20
+ }
21
+ export interface ImageGenAuthRegistry<TModel extends ImageGenAuthModel = ImageGenAuthModel> {
22
+ authStorage: {
23
+ get(provider: string): unknown;
24
+ };
25
+ getAll(): TModel[];
26
+ getApiKeyAndHeaders(model: TModel): Promise<ImageGenRegistryAuthResult>;
27
+ getProviderAuth(provider: string): Promise<ImageGenProviderAuthResult | undefined>;
28
+ }
29
+ export interface ResolveImageGenAuthDeps<TModel extends ImageGenAuthModel = ImageGenAuthModel> {
30
+ modelRegistry: ImageGenAuthRegistry<TModel>;
31
+ env?: Readonly<Record<string, string | undefined>>;
32
+ }
33
+ export type ImageGenAuthResolution = {
34
+ kind: "native-openai" | "gateway";
35
+ apiKey: string | undefined;
36
+ baseUrl: string;
37
+ headers?: Record<string, string>;
38
+ provenance: "store" | "env" | "provider-config";
39
+ providerId?: string;
40
+ } | {
41
+ kind: "none";
42
+ reason: string;
43
+ };
44
+ export declare function resolveImageGenAuth<TModel extends ImageGenAuthModel>(deps: ResolveImageGenAuthDeps<TModel>): Promise<ImageGenAuthResolution>;
45
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/auth.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,0BAA0B,GACnC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC/D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhC,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;KACxC,CAAC;CACF;AAED,MAAM,WAAW,oBAAoB,CAAC,MAAM,SAAS,iBAAiB,GAAG,iBAAiB;IACzF,WAAW,EAAE;QACZ,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;KAC/B,CAAC;IACF,MAAM,IAAI,MAAM,EAAE,CAAC;IACnB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACxE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,uBAAuB,CAAC,MAAM,SAAS,iBAAiB,GAAG,iBAAiB;IAC5F,aAAa,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC5C,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,sBAAsB,GAC/B;IACA,IAAI,EAAE,eAAe,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,OAAO,GAAG,KAAK,GAAG,iBAAiB,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACnB,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAiHpC,wBAAsB,mBAAmB,CAAC,MAAM,SAAS,iBAAiB,EACzE,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,GACnC,OAAO,CAAC,sBAAsB,CAAC,CAoCjC"}
@@ -0,0 +1,137 @@
1
+ const OPENAI_BASE_URL = "https://api.openai.com/v1";
2
+ const SETUP_REASON = 'Image generation is not configured. Store an OpenAI API key for provider "openai", configure an OpenAI-compatible gateway in models.json and optionally pin it with PI_IMAGE_GEN_PROVIDER, or set OPENAI_API_KEY.';
3
+ function nonEmpty(value) {
4
+ const trimmed = value?.trim();
5
+ return trimmed ? trimmed : undefined;
6
+ }
7
+ function resolvedHeaders(headers) {
8
+ if (!headers)
9
+ return undefined;
10
+ const resolved = {};
11
+ for (const [name, value] of Object.entries(headers)) {
12
+ if (typeof value === "string" && value.trim().length > 0)
13
+ resolved[name] = value;
14
+ }
15
+ return Object.keys(resolved).length > 0 ? resolved : undefined;
16
+ }
17
+ function credentialParts(auth) {
18
+ const apiKey = nonEmpty(auth?.apiKey);
19
+ if (!apiKey)
20
+ return undefined;
21
+ const headers = resolvedHeaders(auth?.headers);
22
+ return { apiKey, ...(headers ? { headers } : {}) };
23
+ }
24
+ function isStoredApiKey(value) {
25
+ return typeof value === "object" && value !== null && "type" in value && value.type === "api_key";
26
+ }
27
+ function isGatewayApi(api) {
28
+ return api === "openai-completions" || api === "openai-responses";
29
+ }
30
+ function compareText(left, right) {
31
+ if (left < right)
32
+ return -1;
33
+ if (left > right)
34
+ return 1;
35
+ return 0;
36
+ }
37
+ function compareProviderIds(left, right) {
38
+ const leftMatches = /openai/i.test(left);
39
+ const rightMatches = /openai/i.test(right);
40
+ if (leftMatches !== rightMatches)
41
+ return leftMatches ? -1 : 1;
42
+ return compareText(left, right);
43
+ }
44
+ function groupGatewayModels(models) {
45
+ const groups = new Map();
46
+ const ordered = [...models].sort((left, right) => compareText(left.provider, right.provider) || compareText(left.id, right.id));
47
+ for (const model of ordered) {
48
+ if (model.provider === "openai" || !isGatewayApi(model.api) || !nonEmpty(model.baseUrl))
49
+ continue;
50
+ if (!groups.has(model.provider))
51
+ groups.set(model.provider, model);
52
+ }
53
+ return groups;
54
+ }
55
+ async function resolveStoredOpenAi(registry) {
56
+ if (!isStoredApiKey(registry.authStorage.get("openai")))
57
+ return undefined;
58
+ let resolved;
59
+ try {
60
+ resolved = await registry.getProviderAuth("openai");
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ const credentials = credentialParts(resolved?.auth);
66
+ if (!credentials)
67
+ return undefined;
68
+ return {
69
+ kind: "native-openai",
70
+ ...credentials,
71
+ baseUrl: OPENAI_BASE_URL,
72
+ provenance: "store",
73
+ providerId: "openai",
74
+ };
75
+ }
76
+ async function resolveGateway(providerId, model, registry) {
77
+ const baseUrl = nonEmpty(model.baseUrl);
78
+ if (!baseUrl)
79
+ return undefined;
80
+ let resolved;
81
+ try {
82
+ resolved = await registry.getApiKeyAndHeaders(model);
83
+ }
84
+ catch {
85
+ return undefined;
86
+ }
87
+ if (!resolved.ok)
88
+ return undefined;
89
+ const credentials = credentialParts(resolved);
90
+ if (!credentials)
91
+ return undefined;
92
+ return {
93
+ kind: "gateway",
94
+ ...credentials,
95
+ baseUrl,
96
+ provenance: "provider-config",
97
+ providerId,
98
+ };
99
+ }
100
+ export async function resolveImageGenAuth(deps) {
101
+ const native = await resolveStoredOpenAi(deps.modelRegistry);
102
+ if (native)
103
+ return native;
104
+ const groups = groupGatewayModels(deps.modelRegistry.getAll());
105
+ const env = deps.env ?? process.env;
106
+ const pinnedProvider = nonEmpty(env.PI_IMAGE_GEN_PROVIDER);
107
+ if (pinnedProvider) {
108
+ const pinnedModel = groups.get(pinnedProvider);
109
+ if (pinnedModel) {
110
+ const pinned = await resolveGateway(pinnedProvider, pinnedModel, deps.modelRegistry);
111
+ if (pinned)
112
+ return pinned;
113
+ }
114
+ }
115
+ const providerIds = [...groups.keys()]
116
+ .filter((providerId) => providerId !== pinnedProvider)
117
+ .sort(compareProviderIds);
118
+ for (const providerId of providerIds) {
119
+ const model = groups.get(providerId);
120
+ if (!model)
121
+ continue;
122
+ const gateway = await resolveGateway(providerId, model, deps.modelRegistry);
123
+ if (gateway)
124
+ return gateway;
125
+ }
126
+ const envApiKey = nonEmpty(env.OPENAI_API_KEY);
127
+ if (envApiKey) {
128
+ return {
129
+ kind: "native-openai",
130
+ apiKey: envApiKey,
131
+ baseUrl: OPENAI_BASE_URL,
132
+ provenance: "env",
133
+ };
134
+ }
135
+ return { kind: "none", reason: SETUP_REASON };
136
+ }
137
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/auth.ts"],"names":[],"mappings":"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","sourcesContent":["export interface ImageGenAuthModel {\n\tprovider: string;\n\tid: string;\n\tbaseUrl: string;\n\tapi?: string;\n}\n\nexport type ImageGenRegistryAuthResult =\n\t| { ok: true; apiKey?: string; headers?: Record<string, string> }\n\t| { ok: false; error: string };\n\nexport interface ImageGenProviderAuthResult {\n\tauth: {\n\t\tapiKey?: string;\n\t\theaders?: Record<string, string | null>;\n\t};\n}\n\nexport interface ImageGenAuthRegistry<TModel extends ImageGenAuthModel = ImageGenAuthModel> {\n\tauthStorage: {\n\t\tget(provider: string): unknown;\n\t};\n\tgetAll(): TModel[];\n\tgetApiKeyAndHeaders(model: TModel): Promise<ImageGenRegistryAuthResult>;\n\tgetProviderAuth(provider: string): Promise<ImageGenProviderAuthResult | undefined>;\n}\n\nexport interface ResolveImageGenAuthDeps<TModel extends ImageGenAuthModel = ImageGenAuthModel> {\n\tmodelRegistry: ImageGenAuthRegistry<TModel>;\n\tenv?: Readonly<Record<string, string | undefined>>;\n}\n\nexport type ImageGenAuthResolution =\n\t| {\n\t\t\tkind: \"native-openai\" | \"gateway\";\n\t\t\tapiKey: string | undefined;\n\t\t\tbaseUrl: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\tprovenance: \"store\" | \"env\" | \"provider-config\";\n\t\t\tproviderId?: string;\n\t }\n\t| { kind: \"none\"; reason: string };\n\ninterface CredentialParts {\n\tapiKey: string | undefined;\n\theaders?: Record<string, string>;\n}\n\nconst OPENAI_BASE_URL = \"https://api.openai.com/v1\";\nconst SETUP_REASON =\n\t'Image generation is not configured. Store an OpenAI API key for provider \"openai\", configure an OpenAI-compatible gateway in models.json and optionally pin it with PI_IMAGE_GEN_PROVIDER, or set OPENAI_API_KEY.';\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n\tconst trimmed = value?.trim();\n\treturn trimmed ? trimmed : undefined;\n}\n\nfunction resolvedHeaders(headers: Record<string, string | null> | undefined): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst resolved: Record<string, string> = {};\n\tfor (const [name, value] of Object.entries(headers)) {\n\t\tif (typeof value === \"string\" && value.trim().length > 0) resolved[name] = value;\n\t}\n\treturn Object.keys(resolved).length > 0 ? resolved : undefined;\n}\n\nfunction credentialParts(\n\tauth: { apiKey?: string; headers?: Record<string, string | null> } | undefined,\n): CredentialParts | undefined {\n\tconst apiKey = nonEmpty(auth?.apiKey);\n\tif (!apiKey) return undefined;\n\tconst headers = resolvedHeaders(auth?.headers);\n\treturn { apiKey, ...(headers ? { headers } : {}) };\n}\n\nfunction isStoredApiKey(value: unknown): boolean {\n\treturn typeof value === \"object\" && value !== null && \"type\" in value && value.type === \"api_key\";\n}\n\nfunction isGatewayApi(api: string | undefined): boolean {\n\treturn api === \"openai-completions\" || api === \"openai-responses\";\n}\n\nfunction compareText(left: string, right: string): number {\n\tif (left < right) return -1;\n\tif (left > right) return 1;\n\treturn 0;\n}\n\nfunction compareProviderIds(left: string, right: string): number {\n\tconst leftMatches = /openai/i.test(left);\n\tconst rightMatches = /openai/i.test(right);\n\tif (leftMatches !== rightMatches) return leftMatches ? -1 : 1;\n\treturn compareText(left, right);\n}\n\nfunction groupGatewayModels<TModel extends ImageGenAuthModel>(models: readonly TModel[]): Map<string, TModel> {\n\tconst groups = new Map<string, TModel>();\n\tconst ordered = [...models].sort(\n\t\t(left, right) => compareText(left.provider, right.provider) || compareText(left.id, right.id),\n\t);\n\tfor (const model of ordered) {\n\t\tif (model.provider === \"openai\" || !isGatewayApi(model.api) || !nonEmpty(model.baseUrl)) continue;\n\t\tif (!groups.has(model.provider)) groups.set(model.provider, model);\n\t}\n\treturn groups;\n}\n\nasync function resolveStoredOpenAi<TModel extends ImageGenAuthModel>(\n\tregistry: ImageGenAuthRegistry<TModel>,\n): Promise<ImageGenAuthResolution | undefined> {\n\tif (!isStoredApiKey(registry.authStorage.get(\"openai\"))) return undefined;\n\tlet resolved: ImageGenProviderAuthResult | undefined;\n\ttry {\n\t\tresolved = await registry.getProviderAuth(\"openai\");\n\t} catch {\n\t\treturn undefined;\n\t}\n\tconst credentials = credentialParts(resolved?.auth);\n\tif (!credentials) return undefined;\n\treturn {\n\t\tkind: \"native-openai\",\n\t\t...credentials,\n\t\tbaseUrl: OPENAI_BASE_URL,\n\t\tprovenance: \"store\",\n\t\tproviderId: \"openai\",\n\t};\n}\n\nasync function resolveGateway<TModel extends ImageGenAuthModel>(\n\tproviderId: string,\n\tmodel: TModel,\n\tregistry: ImageGenAuthRegistry<TModel>,\n): Promise<ImageGenAuthResolution | undefined> {\n\tconst baseUrl = nonEmpty(model.baseUrl);\n\tif (!baseUrl) return undefined;\n\tlet resolved: ImageGenRegistryAuthResult;\n\ttry {\n\t\tresolved = await registry.getApiKeyAndHeaders(model);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!resolved.ok) return undefined;\n\tconst credentials = credentialParts(resolved);\n\tif (!credentials) return undefined;\n\treturn {\n\t\tkind: \"gateway\",\n\t\t...credentials,\n\t\tbaseUrl,\n\t\tprovenance: \"provider-config\",\n\t\tproviderId,\n\t};\n}\n\nexport async function resolveImageGenAuth<TModel extends ImageGenAuthModel>(\n\tdeps: ResolveImageGenAuthDeps<TModel>,\n): Promise<ImageGenAuthResolution> {\n\tconst native = await resolveStoredOpenAi(deps.modelRegistry);\n\tif (native) return native;\n\n\tconst groups = groupGatewayModels(deps.modelRegistry.getAll());\n\tconst env = deps.env ?? process.env;\n\tconst pinnedProvider = nonEmpty(env.PI_IMAGE_GEN_PROVIDER);\n\tif (pinnedProvider) {\n\t\tconst pinnedModel = groups.get(pinnedProvider);\n\t\tif (pinnedModel) {\n\t\t\tconst pinned = await resolveGateway(pinnedProvider, pinnedModel, deps.modelRegistry);\n\t\t\tif (pinned) return pinned;\n\t\t}\n\t}\n\n\tconst providerIds = [...groups.keys()]\n\t\t.filter((providerId) => providerId !== pinnedProvider)\n\t\t.sort(compareProviderIds);\n\tfor (const providerId of providerIds) {\n\t\tconst model = groups.get(providerId);\n\t\tif (!model) continue;\n\t\tconst gateway = await resolveGateway(providerId, model, deps.modelRegistry);\n\t\tif (gateway) return gateway;\n\t}\n\n\tconst envApiKey = nonEmpty(env.OPENAI_API_KEY);\n\tif (envApiKey) {\n\t\treturn {\n\t\t\tkind: \"native-openai\",\n\t\t\tapiKey: envApiKey,\n\t\t\tbaseUrl: OPENAI_BASE_URL,\n\t\t\tprovenance: \"env\",\n\t\t};\n\t}\n\n\treturn { kind: \"none\", reason: SETUP_REASON };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { ExtensionAPI } from "../../types.ts";
2
+ export declare const IMAGE_GEN_SECTION = "\n## Image Generation\n\nWhen image generation tooling is present, read the gpt-image-gen skill before generating.\nUse the image generation tool currently available in this session.\n";
3
+ export declare function registerImageGenExtension(pi: ExtensionAPI, baseDir?: string): void;
4
+ export default function imageGenExtension(pi: ExtensionAPI): void;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAQrE,eAAO,MAAM,iBAAiB,6LAK7B,CAAC;AAiBF,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,SAAoB,GAAG,IAAI,CAa7F;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAEhE"}
@@ -0,0 +1,46 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { resolveImageGenAuth } from "./auth.js";
5
+ import { imageGenRegistryOverride } from "./state.js";
6
+ import { generateImageTool } from "./tool.js";
7
+ const IMAGEGEN_BASE_DIR = dirname(fileURLToPath(import.meta.url));
8
+ let loggedMissingSkill = false;
9
+ export const IMAGE_GEN_SECTION = `
10
+ ## Image Generation
11
+
12
+ When image generation tooling is present, read the gpt-image-gen skill before generating.
13
+ Use the image generation tool currently available in this session.
14
+ `;
15
+ async function isImageGenActive(ctx) {
16
+ const auth = await resolveImageGenAuth({ modelRegistry: imageGenRegistryOverride() ?? ctx.modelRegistry });
17
+ return auth.kind !== "none";
18
+ }
19
+ function bundledSkillPath(baseDir) {
20
+ const skillPath = join(baseDir, "skill", "SKILL.md");
21
+ if (existsSync(skillPath))
22
+ return skillPath;
23
+ if (!loggedMissingSkill) {
24
+ loggedMissingSkill = true;
25
+ console.debug(`[imagegen] bundled skill not found at ${skillPath}; skipping contribution`);
26
+ }
27
+ return undefined;
28
+ }
29
+ export function registerImageGenExtension(pi, baseDir = IMAGEGEN_BASE_DIR) {
30
+ pi.registerTool(generateImageTool);
31
+ pi.on("resources_discover", async (_event, ctx) => {
32
+ if (!(await isImageGenActive(ctx)))
33
+ return undefined;
34
+ const skillPath = bundledSkillPath(baseDir);
35
+ return skillPath === undefined ? undefined : { skillPaths: [skillPath] };
36
+ });
37
+ pi.on("before_agent_start", async (event, ctx) => {
38
+ if (!(await isImageGenActive(ctx)))
39
+ return undefined;
40
+ return { systemPrompt: `${event.systemPrompt}\n${IMAGE_GEN_SECTION}` };
41
+ });
42
+ }
43
+ export default function imageGenExtension(pi) {
44
+ registerImageGenExtension(pi);
45
+ }
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAE/B,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;CAKhC,CAAC;AAEF,KAAK,UAAU,gBAAgB,CAAC,GAAqB;IACpD,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,EAAE,aAAa,EAAE,wBAAwB,EAAE,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;IAC3G,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACzB,kBAAkB,GAAG,IAAI,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,yCAAyC,SAAS,yBAAyB,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,EAAgB,EAAE,OAAO,GAAG,iBAAiB;IACtF,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAEnC,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACrD,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAChD,IAAI,CAAC,CAAC,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACrD,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,iBAAiB,EAAE,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAgB;IACzD,yBAAyB,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { resolveImageGenAuth } from \"./auth.ts\";\nimport { imageGenRegistryOverride } from \"./state.ts\";\nimport { generateImageTool } from \"./tool.ts\";\n\nconst IMAGEGEN_BASE_DIR = dirname(fileURLToPath(import.meta.url));\nlet loggedMissingSkill = false;\n\nexport const IMAGE_GEN_SECTION = `\n## Image Generation\n\nWhen image generation tooling is present, read the gpt-image-gen skill before generating.\nUse the image generation tool currently available in this session.\n`;\n\nasync function isImageGenActive(ctx: ExtensionContext): Promise<boolean> {\n\tconst auth = await resolveImageGenAuth({ modelRegistry: imageGenRegistryOverride() ?? ctx.modelRegistry });\n\treturn auth.kind !== \"none\";\n}\n\nfunction bundledSkillPath(baseDir: string): string | undefined {\n\tconst skillPath = join(baseDir, \"skill\", \"SKILL.md\");\n\tif (existsSync(skillPath)) return skillPath;\n\tif (!loggedMissingSkill) {\n\t\tloggedMissingSkill = true;\n\t\tconsole.debug(`[imagegen] bundled skill not found at ${skillPath}; skipping contribution`);\n\t}\n\treturn undefined;\n}\n\nexport function registerImageGenExtension(pi: ExtensionAPI, baseDir = IMAGEGEN_BASE_DIR): void {\n\tpi.registerTool(generateImageTool);\n\n\tpi.on(\"resources_discover\", async (_event, ctx) => {\n\t\tif (!(await isImageGenActive(ctx))) return undefined;\n\t\tconst skillPath = bundledSkillPath(baseDir);\n\t\treturn skillPath === undefined ? undefined : { skillPaths: [skillPath] };\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!(await isImageGenActive(ctx))) return undefined;\n\t\treturn { systemPrompt: `${event.systemPrompt}\\n${IMAGE_GEN_SECTION}` };\n\t});\n}\n\nexport default function imageGenExtension(pi: ExtensionAPI): void {\n\tregisterImageGenExtension(pi);\n}\n"]}
@@ -0,0 +1,26 @@
1
+ export declare const GENERATED_IMAGE_DIRECTORY = "generated-images";
2
+ export type TargetPaths = {
3
+ ok: true;
4
+ paths: string[];
5
+ } | {
6
+ ok: false;
7
+ error: string;
8
+ };
9
+ /**
10
+ * Reduces a provider-supplied identifier to a safe file stem: path separators and
11
+ * any other unexpected character collapse to `_`, the result is length-capped, and
12
+ * an identifier that sanitizes to nothing falls back to `image`.
13
+ */
14
+ export declare function sanitizeImageStem(identifier: string): string;
15
+ /**
16
+ * Resolves the absolute destination paths for a generation call.
17
+ *
18
+ * A relative output_path resolves against the working directory. An omitted path
19
+ * falls back to generated-images/<sanitized tool call id>.png. An extensionless
20
+ * path gains .png; any other extension is rejected. With more than one image a
21
+ * zero-padded index is inserted before the extension.
22
+ */
23
+ export declare function resolveTargets(cwd: string, toolCallId: string, count: number, outputPath: string | undefined): TargetPaths;
24
+ /** Prefers a path relative to the working directory, falling back to absolute. */
25
+ export declare function displayPath(cwd: string, absolute: string): string;
26
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/paths.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAI5D,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAG5D;AAMD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GAAG,SAAS,GAC5B,WAAW,CAmBb;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjE"}
@@ -0,0 +1,52 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ export const GENERATED_IMAGE_DIRECTORY = "generated-images";
3
+ const DEFAULT_DIRECTORY = GENERATED_IMAGE_DIRECTORY;
4
+ const MAX_TOOL_CALL_ID_CHARS = 64;
5
+ /**
6
+ * Reduces a provider-supplied identifier to a safe file stem: path separators and
7
+ * any other unexpected character collapse to `_`, the result is length-capped, and
8
+ * an identifier that sanitizes to nothing falls back to `image`.
9
+ */
10
+ export function sanitizeImageStem(identifier) {
11
+ const sanitized = identifier.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, MAX_TOOL_CALL_ID_CHARS);
12
+ return sanitized.length > 0 ? sanitized : "image";
13
+ }
14
+ function sanitizeToolCallId(toolCallId) {
15
+ return sanitizeImageStem(toolCallId);
16
+ }
17
+ /**
18
+ * Resolves the absolute destination paths for a generation call.
19
+ *
20
+ * A relative output_path resolves against the working directory. An omitted path
21
+ * falls back to generated-images/<sanitized tool call id>.png. An extensionless
22
+ * path gains .png; any other extension is rejected. With more than one image a
23
+ * zero-padded index is inserted before the extension.
24
+ */
25
+ export function resolveTargets(cwd, toolCallId, count, outputPath) {
26
+ const requested = outputPath?.trim();
27
+ let base;
28
+ if (requested === undefined || requested.length === 0) {
29
+ base = resolve(cwd, DEFAULT_DIRECTORY, `${sanitizeToolCallId(toolCallId)}.png`);
30
+ }
31
+ else {
32
+ const absolute = isAbsolute(requested) ? requested : resolve(cwd, requested);
33
+ const extensionMatch = /\.[^./\\]+$/.exec(absolute);
34
+ if (extensionMatch && extensionMatch[0].toLowerCase() !== ".png") {
35
+ return { ok: false, error: `Error: output_path must end in .png (got "${requested}").` };
36
+ }
37
+ base = extensionMatch ? absolute : `${absolute}.png`;
38
+ }
39
+ if (count === 1)
40
+ return { ok: true, paths: [base] };
41
+ const stem = base.slice(0, -".png".length);
42
+ return {
43
+ ok: true,
44
+ paths: Array.from({ length: count }, (_, index) => `${stem}-${String(index + 1).padStart(2, "0")}.png`),
45
+ };
46
+ }
47
+ /** Prefers a path relative to the working directory, falling back to absolute. */
48
+ export function displayPath(cwd, absolute) {
49
+ const relativePath = relative(cwd, absolute);
50
+ return relativePath && !relativePath.startsWith("..") && !isAbsolute(relativePath) ? relativePath : absolute;
51
+ }
52
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAC5D,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AACpD,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAIlC;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IACnD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAC9F,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AACnD,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB;IAC7C,OAAO,iBAAiB,CAAC,UAAU,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC7B,GAAW,EACX,UAAkB,EAClB,KAAa,EACb,UAA8B;IAE9B,MAAM,SAAS,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,IAAY,CAAC;IACjB,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvD,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,kBAAkB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACjF,CAAC;SAAM,CAAC;QACP,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7E,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,cAAc,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YAClE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6CAA6C,SAAS,KAAK,EAAE,CAAC;QAC1F,CAAC;QACD,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,MAAM,CAAC;IACtD,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO;QACN,EAAE,EAAE,IAAI;QACR,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;KACvG,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAAgB;IACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC7C,OAAO,YAAY,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC9G,CAAC","sourcesContent":["import { isAbsolute, relative, resolve } from \"node:path\";\n\nexport const GENERATED_IMAGE_DIRECTORY = \"generated-images\";\nconst DEFAULT_DIRECTORY = GENERATED_IMAGE_DIRECTORY;\nconst MAX_TOOL_CALL_ID_CHARS = 64;\n\nexport type TargetPaths = { ok: true; paths: string[] } | { ok: false; error: string };\n\n/**\n * Reduces a provider-supplied identifier to a safe file stem: path separators and\n * any other unexpected character collapse to `_`, the result is length-capped, and\n * an identifier that sanitizes to nothing falls back to `image`.\n */\nexport function sanitizeImageStem(identifier: string): string {\n\tconst sanitized = identifier.replace(/[^A-Za-z0-9_-]/g, \"_\").slice(0, MAX_TOOL_CALL_ID_CHARS);\n\treturn sanitized.length > 0 ? sanitized : \"image\";\n}\n\nfunction sanitizeToolCallId(toolCallId: string): string {\n\treturn sanitizeImageStem(toolCallId);\n}\n\n/**\n * Resolves the absolute destination paths for a generation call.\n *\n * A relative output_path resolves against the working directory. An omitted path\n * falls back to generated-images/<sanitized tool call id>.png. An extensionless\n * path gains .png; any other extension is rejected. With more than one image a\n * zero-padded index is inserted before the extension.\n */\nexport function resolveTargets(\n\tcwd: string,\n\ttoolCallId: string,\n\tcount: number,\n\toutputPath: string | undefined,\n): TargetPaths {\n\tconst requested = outputPath?.trim();\n\tlet base: string;\n\tif (requested === undefined || requested.length === 0) {\n\t\tbase = resolve(cwd, DEFAULT_DIRECTORY, `${sanitizeToolCallId(toolCallId)}.png`);\n\t} else {\n\t\tconst absolute = isAbsolute(requested) ? requested : resolve(cwd, requested);\n\t\tconst extensionMatch = /\\.[^./\\\\]+$/.exec(absolute);\n\t\tif (extensionMatch && extensionMatch[0].toLowerCase() !== \".png\") {\n\t\t\treturn { ok: false, error: `Error: output_path must end in .png (got \"${requested}\").` };\n\t\t}\n\t\tbase = extensionMatch ? absolute : `${absolute}.png`;\n\t}\n\tif (count === 1) return { ok: true, paths: [base] };\n\tconst stem = base.slice(0, -\".png\".length);\n\treturn {\n\t\tok: true,\n\t\tpaths: Array.from({ length: count }, (_, index) => `${stem}-${String(index + 1).padStart(2, \"0\")}.png`),\n\t};\n}\n\n/** Prefers a path relative to the working directory, falling back to absolute. */\nexport function displayPath(cwd: string, absolute: string): string {\n\tconst relativePath = relative(cwd, absolute);\n\treturn relativePath && !relativePath.startsWith(\"..\") && !isAbsolute(relativePath) ? relativePath : absolute;\n}\n"]}
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: gpt-image-gen
3
+ description: MUST read before generating images. Detailed prompt-crafting guide for gpt-image models, covering tool routing (native image_generation server tool vs the generate_image tool), prompt structure from subject to background, verbatim text rendering, anti-patterns, and the revised_prompt feedback loop for iteration.
4
+ ---
5
+
6
+ # GPT Image Generation
7
+
8
+ How to write image prompts that come back right the first time, and how to fix them fast when they don't. Read this before your first generation call.
9
+
10
+ ## Which tool
11
+
12
+ When image generation tooling is present in your tool set, pick the surface that actually exists right now:
13
+
14
+ - If a native `image_generation` server tool is available, use it. The provider runs generation server-side and returns the image in the response stream.
15
+ - Otherwise, call the `generate_image` tool. It sends your prompt to the configured OpenAI-compatible endpoint and saves the result to a file.
16
+
17
+ Check your current tool set before choosing. Skill visibility refreshes on reload, but tool state can change mid-session (model switch, credential change), so trust the tools you can see over what this page said at startup. If both surfaces ever appear, prefer the native server tool.
18
+
19
+ ## Prompt crafting
20
+
21
+ This section is the core of the skill. gpt-image models reward detail, and the single most common failure mode is a one-line prompt.
22
+
23
+ Build each prompt from six parts, in this order:
24
+
25
+ 1. Subject. Who or what, with concrete physical detail. "A middle-aged baker with flour on her forearms and a gray-streaked braid" beats "a baker".
26
+ 2. Medium and style. One style, stated plainly: "35mm film photograph", "watercolor illustration", "flat vector poster". Pick one lane.
27
+ 3. Composition and camera. Framing, angle, focal length or its visual equivalent. "Eye-level medium close-up, shallow depth of field, subject left of center".
28
+ 4. Lighting and color. Direction, quality, palette. "Soft window light from the left, warm amber tones against deep shadow".
29
+ 5. Mood. The emotional register: quiet, tense, celebratory, clinical.
30
+ 6. Background. What sits behind the subject, and how much of it is in focus.
31
+
32
+ A good prompt reads as a short paragraph, not a list and not a lone sentence. If your prompt fits on one line, it is under-specified, and the model will fill the gaps with whatever it likes.
33
+
34
+ ### Rendering text in the image
35
+
36
+ When the image must contain readable text (a sign, a label, a headline), put the exact string in double quotes and state the font style and placement:
37
+
38
+ A weathered wooden sign above the door reads "OPEN TIL LATE" in hand-painted white serif letters, centered, slightly faded.
39
+
40
+ Keep on-image text short. Long passages smear. If the layout matters, say where each string sits.
41
+
42
+ ### Anti-patterns
43
+
44
+ - Contradictory instructions. "Photorealistic watercolor" or "minimalist scene packed with detail" forces the model to average two opposing goals, and you get neither.
45
+ - Element overcrowding. Every named object competes for pixels and attention. Past roughly five or six distinct elements, small ones get dropped or mangled. Cut before you add.
46
+ - Style-list collisions. "In the style of anime, oil painting, and pixel art" is three prompts in a trench coat. Choose one style per image and generate variants separately.
47
+
48
+ ### The revised_prompt loop
49
+
50
+ Both surfaces can return a `revised_prompt`: the prompt the model actually used after its own rewrite. Always read it.
51
+
52
+ 1. Diff it against your intent. Note what the model added, dropped, or reinterpreted.
53
+ 2. Fold the delta into your next prompt explicitly. If the rewrite dropped "overcast sky", put "overcast sky, no direct sunlight" back with more weight. If it added something you dislike, name the exclusion ("no lens flare").
54
+ 3. Regenerate. Treat each round as a conversation with the rewriter, not a fresh roll of the dice.
55
+
56
+ ## Editing and masks
57
+
58
+ v1 has no editing surface. The `generate_image` tool is text-only: it accepts a prompt and returns new images. There is no image input, no mask, no inpainting, no variation mode. The native `image_generation` server tool may perform provider-side edits on its own (action=auto), but no edit controls are exposed here.
59
+
60
+ Don't build workflows around editing. If the user asks to change an existing image, say that v1 generates from text only, then offer the closest text-only path: describe the desired end state as a full new prompt. Editing, masks, and image input are planned for a future version.
61
+
62
+ ## Iteration workflow
63
+
64
+ - Generate one image first. Inspect the result against every clause of your prompt before spending more.
65
+ - Correct deviations by editing the prompt, not by hoping. Name what was wrong and what stays fixed.
66
+ - Batch with `n` only after the prompt is proven. `n` variants of a bad prompt is `n` bad images.
67
+ - Keep the full prompt text in the conversation. It is your reproducibility record: anyone can re-run the exact call later, and you can diff prompt versions when results drift.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Client-tool availability state for the imagegen builtin.
3
+ *
4
+ * The generate_image tool is registered once and gated at call time so a
5
+ * mid-session login or model switch takes effect without a reload. Credentials
6
+ * are re-resolved inside every execute; this module only carries the native
7
+ * bypass seam, which the sibling openai-image-gen builtin wires live once the
8
+ * native server tool ships. Until then it stays false and the client tool owns
9
+ * every image request.
10
+ */
11
+ import type { ImageGenAuthRegistry } from "./auth.ts";
12
+ export declare const NATIVE_BYPASS_MESSAGE = "Image generation is handled by the provider's native server-side tool for the current model. Call the native image_generation tool instead of generate_image.";
13
+ /** Enables or disables deferral to a provider-native image generation tool. */
14
+ export declare function setNativeBypass(enabled: boolean): void;
15
+ /** Whether generate_image should defer to a provider-native image generation tool. */
16
+ export declare function isNativeBypass(): boolean;
17
+ /**
18
+ * Overrides the registry the tool resolves credentials from. Tests and the
19
+ * arbitration suite use this to force a credential direction, because the
20
+ * builtin provider catalog always contains credential-resolvable gateways and
21
+ * the ambient session registry is therefore never credential-free.
22
+ */
23
+ export declare function setImageGenRegistry(registry: ImageGenAuthRegistry | undefined): void;
24
+ /** The registry override, when one is installed. */
25
+ export declare function imageGenRegistryOverride(): ImageGenAuthRegistry | undefined;
26
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,eAAO,MAAM,qBAAqB,kKAC8H,CAAC;AAKjK,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD;AAED,sFAAsF;AACtF,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAEpF;AAED,oDAAoD;AACpD,wBAAgB,wBAAwB,IAAI,oBAAoB,GAAG,SAAS,CAE3E"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Client-tool availability state for the imagegen builtin.
3
+ *
4
+ * The generate_image tool is registered once and gated at call time so a
5
+ * mid-session login or model switch takes effect without a reload. Credentials
6
+ * are re-resolved inside every execute; this module only carries the native
7
+ * bypass seam, which the sibling openai-image-gen builtin wires live once the
8
+ * native server tool ships. Until then it stays false and the client tool owns
9
+ * every image request.
10
+ */
11
+ export const NATIVE_BYPASS_MESSAGE = "Image generation is handled by the provider's native server-side tool for the current model. Call the native image_generation tool instead of generate_image.";
12
+ let nativeBypass = false;
13
+ let registryOverride;
14
+ /** Enables or disables deferral to a provider-native image generation tool. */
15
+ export function setNativeBypass(enabled) {
16
+ nativeBypass = enabled;
17
+ }
18
+ /** Whether generate_image should defer to a provider-native image generation tool. */
19
+ export function isNativeBypass() {
20
+ return nativeBypass;
21
+ }
22
+ /**
23
+ * Overrides the registry the tool resolves credentials from. Tests and the
24
+ * arbitration suite use this to force a credential direction, because the
25
+ * builtin provider catalog always contains credential-resolvable gateways and
26
+ * the ambient session registry is therefore never credential-free.
27
+ */
28
+ export function setImageGenRegistry(registry) {
29
+ registryOverride = registry;
30
+ }
31
+ /** The registry override, when one is installed. */
32
+ export function imageGenRegistryOverride() {
33
+ return registryOverride;
34
+ }
35
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GACjC,+JAA+J,CAAC;AAEjK,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,IAAI,gBAAkD,CAAC;AAEvD,+EAA+E;AAC/E,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC/C,YAAY,GAAG,OAAO,CAAC;AACxB,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,cAAc;IAC7B,OAAO,YAAY,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAA0C;IAC7E,gBAAgB,GAAG,QAAQ,CAAC;AAC7B,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,wBAAwB;IACvC,OAAO,gBAAgB,CAAC;AACzB,CAAC","sourcesContent":["/**\n * Client-tool availability state for the imagegen builtin.\n *\n * The generate_image tool is registered once and gated at call time so a\n * mid-session login or model switch takes effect without a reload. Credentials\n * are re-resolved inside every execute; this module only carries the native\n * bypass seam, which the sibling openai-image-gen builtin wires live once the\n * native server tool ships. Until then it stays false and the client tool owns\n * every image request.\n */\n\nimport type { ImageGenAuthRegistry } from \"./auth.ts\";\n\nexport const NATIVE_BYPASS_MESSAGE =\n\t\"Image generation is handled by the provider's native server-side tool for the current model. Call the native image_generation tool instead of generate_image.\";\n\nlet nativeBypass = false;\nlet registryOverride: ImageGenAuthRegistry | undefined;\n\n/** Enables or disables deferral to a provider-native image generation tool. */\nexport function setNativeBypass(enabled: boolean): void {\n\tnativeBypass = enabled;\n}\n\n/** Whether generate_image should defer to a provider-native image generation tool. */\nexport function isNativeBypass(): boolean {\n\treturn nativeBypass;\n}\n\n/**\n * Overrides the registry the tool resolves credentials from. Tests and the\n * arbitration suite use this to force a credential direction, because the\n * builtin provider catalog always contains credential-resolvable gateways and\n * the ambient session registry is therefore never credential-free.\n */\nexport function setImageGenRegistry(registry: ImageGenAuthRegistry | undefined): void {\n\tregistryOverride = registry;\n}\n\n/** The registry override, when one is installed. */\nexport function imageGenRegistryOverride(): ImageGenAuthRegistry | undefined {\n\treturn registryOverride;\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import { Type } from "typebox";
2
+ import { type ImageGenAuthRegistry } from "./auth.ts";
3
+ export interface GenerateImageDetails {
4
+ paths: string[];
5
+ model: string;
6
+ source: string;
7
+ size: string;
8
+ quality: string;
9
+ requested: number;
10
+ generated: number;
11
+ revisedPrompts: string[];
12
+ error?: string;
13
+ reason?: "missing_config" | "provider_native_bypass" | "invalid_params" | "write_failed" | "provider_error";
14
+ }
15
+ /**
16
+ * Only the registry surface the credential resolver needs. The session passes its
17
+ * full ModelRegistry, which satisfies this structurally.
18
+ */
19
+ export interface GenerateImageToolContext {
20
+ cwd: string;
21
+ modelRegistry: ImageGenAuthRegistry;
22
+ }
23
+ export declare const GENERATE_IMAGE_TOOL_NAME = "generate_image";
24
+ export declare const generateImageTool: import("../../types.ts").ToolDefinition<Type.TObject<{
25
+ prompt: Type.TString;
26
+ size: Type.TOptional<Type.TUnion<[Type.TLiteral<"auto">, Type.TLiteral<"1024x1024">, Type.TLiteral<"1024x1536">, Type.TLiteral<"1536x1024">]>>;
27
+ quality: Type.TOptional<Type.TUnion<[Type.TLiteral<"auto">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>>;
28
+ n: Type.TOptional<Type.TInteger>;
29
+ output_path: Type.TOptional<Type.TString>;
30
+ }>, GenerateImageDetails, any> & import("../../types.ts").ToolDefinition<any, any, any>;
31
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/imagegen/tool.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAE,KAAK,oBAAoB,EAAoD,MAAM,WAAW,CAAC;AAuCxG,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,gBAAgB,GAAG,wBAAwB,GAAG,gBAAgB,GAAG,cAAc,GAAG,gBAAgB,CAAC;CAC5G;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,oBAAoB,CAAC;CACpC;AA6ED,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,eAAO,MAAM,iBAAiB;;;;;;uFA4F5B,CAAC"}