@xopcai/xopc 0.0.141 → 0.0.143

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 (605) hide show
  1. package/README.md +1 -1
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/activity-center-store-jITiX2vJ.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BRTCpm3t.js → agent-avatar-dicebear-DiME9u_P.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-DzBXhZXO.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-DaMMZBAT.js → app-management-settings-panel-Cuo7SbUP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BXHThPyM.js → appearance-settings-DUfdNQqk.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CKuKK5AU.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-izB-4N4L.js → archive-plugin-B-Qk6cGr.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CJihXa5y.js → attachment-load-Di6EEbQX.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DGxvRxtO.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-D-FF_WKV.js +4 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-D3VUeG8s.js → binary-plugins-ZaOZDH2I.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-KnA0sLI3.js → block-editor-BTFhjWfg.js} +36 -36
  16. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-D8rRNhc6.js → capability-presets-api-BU-pVZiZ.js} +1 -1
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DgyeEwzh.js +2 -0
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-BWgqwC5h.js → channel-recipient-api-DuulnhIj.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-BbVsdD_I.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +1 -0
  22. package/dist/gateway/static/root/assets/check-BODqo66o.js +1 -0
  23. package/dist/gateway/static/root/assets/chunk-QUQL4437-DXsxWP7r.js +4 -0
  24. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-page-B8QqVy3I.js +2 -0
  26. package/dist/gateway/static/root/assets/{desktop-pet-CzdqX001.js → desktop-pet---yzVxVR.js} +1 -1
  27. package/dist/gateway/static/root/assets/desktop-pet-settings-Dc3gqBJE.js +1 -0
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-PzlO5tSM.js → directory-picker-path-field-DCmOGLtK.js} +1 -1
  29. package/dist/gateway/static/root/assets/dreaming-settings-BgT5KZVe.js +3 -0
  30. package/dist/gateway/static/root/assets/{extension-debug-page-DcW8Ie3r.js → extension-debug-page-ByaKTTq4.js} +1 -1
  31. package/dist/gateway/static/root/assets/extension-page-BmRzHAZr.js +1 -0
  32. package/dist/gateway/static/root/assets/extension-settings-page-JUtwIhbF.js +1 -0
  33. package/dist/gateway/static/root/assets/{fetch-06q5eCMA.js → fetch-8QNN25Sh.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-4VXUJtLz.js → gateway-config-api-CxicF50_.js} +1 -1
  35. package/dist/gateway/static/root/assets/gateway-settings-Bz2I_EO5.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-2f7_vsv7.js → gateway-startup-retry-5YBnS9Fj.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-VcoyuZGN.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-Cilkap2G.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-BpuQTufF.js → goals-config-api-CwcHRdC0.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-C6eoni4z.js +2 -0
  41. package/dist/gateway/static/root/assets/goals-settings-o4i-qAOS.js +1 -0
  42. package/dist/gateway/static/root/assets/heartbeat-settings-DQQkETX8.js +1 -0
  43. package/dist/gateway/static/root/assets/index-BKRqeRHm.js +257 -0
  44. package/dist/gateway/static/root/assets/index-CphxClbs.css +1 -0
  45. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-LT6qB-ua.js +1 -0
  46. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +7 -0
  47. package/dist/gateway/static/root/assets/{markdown-split-zS4KLNAf.js → markdown-split-Dw-yE2-y.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-_BgNJ9_7.js → media-plugins-D9NNNUgE.js} +1 -1
  49. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +5 -0
  50. package/dist/gateway/static/root/assets/models-hub-panel-DVn2Q1Ik.js +2 -0
  51. package/dist/gateway/static/root/assets/notes-page-CRgbJGgk.js +1 -0
  52. package/dist/gateway/static/root/assets/notes-workbench-BxZRHLWx.js +2 -0
  53. package/dist/gateway/static/root/assets/{page-tabs-B7sGQkgU.js → page-tabs-D4hkWVt_.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-D1ri4s_O.js → preview-open-alternatives-CIckv0uy.js} +1 -1
  55. package/dist/gateway/static/root/assets/project-detail-page-Doz53xLn.js +1 -0
  56. package/dist/gateway/static/root/assets/projects-page-DoMtcRLg.js +1 -0
  57. package/dist/gateway/static/root/assets/remote-access-hub-BeHVEgrm.js +1 -0
  58. package/dist/gateway/static/root/assets/{save-bar-controls-BClrOinh.js → save-bar-controls-B0b42kB2.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schedule-field-CL7YTwLV.js → schedule-field-BtjEkczK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-ww4PiIje.js → schema-form-Bf0bk3i6.js} +1 -1
  61. package/dist/gateway/static/root/assets/sessions-page-Bk4bQsBe.js +1 -0
  62. package/dist/gateway/static/root/assets/settings-advanced-gate-DdFyaRMm.js +1 -0
  63. package/dist/gateway/static/root/assets/{settings-collapsible-section-D9gEEVm2.js → settings-collapsible-section-BTKTdTNX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-form-section-DGeEoBkb.js → settings-form-section-DL4P0sAj.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BXUeMR37.js → settings-loading-skeleton-BV6KFNj4.js} +1 -1
  66. package/dist/gateway/static/root/assets/settings-page-B_4DsX5W.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-page-layout-CEepfbCa.js → settings-page-layout-CyGlrInB.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-DJ1_MLgX.js +1 -0
  69. package/dist/gateway/static/root/assets/share-preview-page-BQBV7YrV.js +2 -0
  70. package/dist/gateway/static/root/assets/shares-settings-0VuFLBeU.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-DO87Ckeo.js +1 -0
  72. package/dist/gateway/static/root/assets/skills-page-D3VdtxAn.js +2 -0
  73. package/dist/gateway/static/root/assets/{system-settings-panel-W6MBJXrr.js → system-settings-panel-D85fBBuI.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-BkODXN7T.js → typed-models-lib-CwEuYrHX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-CTbwLZXc.js → use-channel-catalog-COXIfXcl.js} +1 -1
  76. package/dist/gateway/static/root/assets/user-context-page-m9JVQ73F.js +1 -0
  77. package/dist/gateway/static/root/assets/user-profile-fields-editor-DtQiuY7E.js +1 -0
  78. package/dist/gateway/static/root/assets/user-profile-settings-panel-CWM0fEpb.js +1 -0
  79. package/dist/gateway/static/root/assets/{utils-ZxrKHxyb.js → utils--BO6xT3u.js} +1 -1
  80. package/dist/gateway/static/root/assets/voice-api-key-field-LoT3wgZ9.js +1 -0
  81. package/dist/gateway/static/root/assets/with-selector-aYPsXwdl.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page-DSTMz_mO.js +1 -0
  83. package/dist/gateway/static/root/assets/workflow-run-setup-panel-B35lJzvm.js +3 -0
  84. package/dist/gateway/static/root/assets/workflows-page-BfSm9oR8.js +11 -0
  85. package/dist/gateway/static/root/assets/workflows-page-DLioOiRN.css +1 -0
  86. package/dist/gateway/static/root/connector-icons/README.md +11 -0
  87. package/dist/gateway/static/root/connector-icons/airtable.svg +13 -0
  88. package/dist/gateway/static/root/connector-icons/asana.svg +15 -0
  89. package/dist/gateway/static/root/connector-icons/brave-search.svg +1 -0
  90. package/dist/gateway/static/root/connector-icons/clickup.svg +19 -0
  91. package/dist/gateway/static/root/connector-icons/composio.svg +266 -0
  92. package/dist/gateway/static/root/connector-icons/discord.svg +15 -0
  93. package/dist/gateway/static/root/connector-icons/dropbox.svg +152 -0
  94. package/dist/gateway/static/root/connector-icons/excel.svg +56 -0
  95. package/dist/gateway/static/root/connector-icons/fetch.svg +6 -0
  96. package/dist/gateway/static/root/connector-icons/figma.svg +178 -0
  97. package/dist/gateway/static/root/connector-icons/filesystem.svg +6 -0
  98. package/dist/gateway/static/root/connector-icons/github.svg +10 -0
  99. package/dist/gateway/static/root/connector-icons/gmail.svg +3 -0
  100. package/dist/gateway/static/root/connector-icons/google-calendar.svg +3 -0
  101. package/dist/gateway/static/root/connector-icons/google-docs.svg +25 -0
  102. package/dist/gateway/static/root/connector-icons/google-drive.svg +25 -0
  103. package/dist/gateway/static/root/connector-icons/google-sheets.svg +1 -0
  104. package/dist/gateway/static/root/connector-icons/hubspot.svg +142 -0
  105. package/dist/gateway/static/root/connector-icons/jira.svg +15 -0
  106. package/dist/gateway/static/root/connector-icons/linear.svg +5 -0
  107. package/dist/gateway/static/root/connector-icons/memory.svg +5 -0
  108. package/dist/gateway/static/root/connector-icons/microsoft-teams.svg +33 -0
  109. package/dist/gateway/static/root/connector-icons/notion.svg +5 -0
  110. package/dist/gateway/static/root/connector-icons/one-drive.svg +13 -0
  111. package/dist/gateway/static/root/connector-icons/outlook.svg +76 -0
  112. package/dist/gateway/static/root/connector-icons/playwright.svg +9 -0
  113. package/dist/gateway/static/root/connector-icons/salesforce.svg +17 -0
  114. package/dist/gateway/static/root/connector-icons/sequential-thinking.svg +8 -0
  115. package/dist/gateway/static/root/connector-icons/shopify.svg +5 -0
  116. package/dist/gateway/static/root/connector-icons/slack.svg +9 -0
  117. package/dist/gateway/static/root/connector-icons/spotify.svg +43 -0
  118. package/dist/gateway/static/root/connector-icons/stripe.svg +11 -0
  119. package/dist/gateway/static/root/connector-icons/telegram.svg +130 -0
  120. package/dist/gateway/static/root/connector-icons/time.svg +6 -0
  121. package/dist/gateway/static/root/connector-icons/todoist.svg +277 -0
  122. package/dist/gateway/static/root/connector-icons/trello.svg +19 -0
  123. package/dist/gateway/static/root/connector-icons/twitter.svg +128 -0
  124. package/dist/gateway/static/root/connector-icons/whatsapp.svg +61 -0
  125. package/dist/gateway/static/root/connector-icons/youtube.svg +11 -0
  126. package/dist/gateway/static/root/index.html +9 -6
  127. package/dist/package.js +1 -1
  128. package/dist/src/agent/agent-manager.d.ts +2 -0
  129. package/dist/src/agent/agent-manager.js +8 -0
  130. package/dist/src/agent/agent-manager.js.map +1 -1
  131. package/dist/src/agent/background-review/prompts.d.ts +1 -1
  132. package/dist/src/agent/background-review/prompts.js +3 -2
  133. package/dist/src/agent/background-review/prompts.js.map +1 -1
  134. package/dist/src/agent/embedded/session-runner.js +5 -5
  135. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  136. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  137. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +4 -3
  138. package/dist/src/agent/embedded/xopc-auth-storage.js +6 -6
  139. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  140. package/dist/src/agent/embedded/xopc-stream-bridge.js +1 -0
  141. package/dist/src/agent/embedded/xopc-stream-bridge.js.map +1 -1
  142. package/dist/src/agent/embedded/xopc-tools-bridge.d.ts +9 -0
  143. package/dist/src/agent/embedded/xopc-tools-bridge.js +71 -3
  144. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  145. package/dist/src/agent/goals/checklist-judge.js +3 -3
  146. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  147. package/dist/src/agent/goals/judge.js +2 -2
  148. package/dist/src/agent/goals/judge.js.map +1 -1
  149. package/dist/src/agent/goals/post-turn.js +5 -4
  150. package/dist/src/agent/goals/post-turn.js.map +1 -1
  151. package/dist/src/agent/image/understanding/pi-ai-provider.js +2 -2
  152. package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
  153. package/dist/src/agent/mcp/mcp-transport.js +4 -1
  154. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  155. package/dist/src/agent/memory/compaction.js +2 -2
  156. package/dist/src/agent/memory/compaction.js.map +1 -1
  157. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  158. package/dist/src/agent/memory/context/planner.js +60 -14
  159. package/dist/src/agent/memory/context/planner.js.map +1 -1
  160. package/dist/src/agent/memory/context/types.d.ts +3 -1
  161. package/dist/src/agent/memory/lifecycle.d.ts +11 -0
  162. package/dist/src/agent/memory/lifecycle.js +50 -0
  163. package/dist/src/agent/memory/lifecycle.js.map +1 -0
  164. package/dist/src/agent/memory/source-origin.d.ts +3 -0
  165. package/dist/src/agent/memory/source-origin.js +19 -0
  166. package/dist/src/agent/memory/source-origin.js.map +1 -0
  167. package/dist/src/agent/memory/understanding/service.js +5 -0
  168. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  169. package/dist/src/agent/memory/user-context-coordinator.js +7 -2
  170. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  171. package/dist/src/agent/prompt/sections/behavior.d.ts +2 -0
  172. package/dist/src/agent/prompt/sections/behavior.js +30 -1
  173. package/dist/src/agent/prompt/sections/behavior.js.map +1 -1
  174. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  175. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  176. package/dist/src/agent/prompt/service-prompt-builder.js +8 -1
  177. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  178. package/dist/src/agent/prompt/system-prompt.d.ts +2 -0
  179. package/dist/src/agent/prompt/system-prompt.js +6 -3
  180. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  181. package/dist/src/agent/service/btw-query.d.ts +4 -0
  182. package/dist/src/agent/service/btw-query.js +94 -13
  183. package/dist/src/agent/service/btw-query.js.map +1 -1
  184. package/dist/src/agent/service/process-direct-streaming.js +22 -0
  185. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  186. package/dist/src/agent/service.d.ts +2 -0
  187. package/dist/src/agent/service.js +9 -3
  188. package/dist/src/agent/service.js.map +1 -1
  189. package/dist/src/agent/session/session-inspector.js +9 -1
  190. package/dist/src/agent/session/session-inspector.js.map +1 -1
  191. package/dist/src/agent/starter-agents.js +1 -1
  192. package/dist/src/agent/starter-agents.js.map +1 -1
  193. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  194. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  195. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -1
  196. package/dist/src/agent/tools/composio-tool.d.ts +18 -5
  197. package/dist/src/agent/tools/composio-tool.js +252 -35
  198. package/dist/src/agent/tools/composio-tool.js.map +1 -1
  199. package/dist/src/agent/tools/factory.js +7 -3
  200. package/dist/src/agent/tools/factory.js.map +1 -1
  201. package/dist/src/agent/tools/index.d.ts +1 -1
  202. package/dist/src/agent/tools/index.js +2 -2
  203. package/dist/src/agent/tools/session-search-tool.js +2 -2
  204. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  205. package/dist/src/agent/tools/web-extract.js +2 -2
  206. package/dist/src/agent/tools/web-extract.js.map +1 -1
  207. package/dist/src/agent/tools/workflow-tool.d.ts +0 -1
  208. package/dist/src/agent/tools/workflow-tool.js +3 -16
  209. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  210. package/dist/src/agent/workflow/builtins/index.d.ts +2 -28
  211. package/dist/src/agent/workflow/builtins/index.js +226 -41
  212. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  213. package/dist/src/agent/workflow/catalog.d.ts +32 -34
  214. package/dist/src/agent/workflow/catalog.js +158 -154
  215. package/dist/src/agent/workflow/catalog.js.map +1 -1
  216. package/dist/src/agent/workflow/index.d.ts +4 -6
  217. package/dist/src/agent/workflow/index.js +2 -5
  218. package/dist/src/agent/workflow/snapshot.d.ts +2 -2
  219. package/dist/src/agent/workflow/snapshot.js +2 -2
  220. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  221. package/dist/src/agent/workflow/structured-output-tool.d.ts +2 -2
  222. package/dist/src/agent/workflow/structured-output-tool.js +2 -2
  223. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -1
  224. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  225. package/dist/src/agent/workflow/types.d.ts +31 -26
  226. package/dist/src/agent-manifest/index.d.ts +1 -0
  227. package/dist/src/agent-manifest/index.js +3 -1
  228. package/dist/src/agent-manifest/index.js.map +1 -1
  229. package/dist/src/agent-manifest/preset-chain.d.ts +10 -0
  230. package/dist/src/agent-manifest/preset-chain.js +32 -0
  231. package/dist/src/agent-manifest/preset-chain.js.map +1 -0
  232. package/dist/src/agent-manifest/resolver.js +3 -10
  233. package/dist/src/agent-manifest/resolver.js.map +1 -1
  234. package/dist/src/agent-manifest/schema.d.ts +4 -4
  235. package/dist/src/ai-assist/text-assist.d.ts +2 -1
  236. package/dist/src/ai-assist/text-assist.js +10 -23
  237. package/dist/src/ai-assist/text-assist.js.map +1 -1
  238. package/dist/src/auth/credentials.js +5 -2
  239. package/dist/src/auth/credentials.js.map +1 -1
  240. package/dist/src/auth/oauth/github-copilot.d.ts +3 -4
  241. package/dist/src/auth/oauth/github-copilot.js +66 -2
  242. package/dist/src/auth/oauth/github-copilot.js.map +1 -0
  243. package/dist/src/auth/oauth/index.js +2 -2
  244. package/dist/src/automations/api/routes.js +13 -1
  245. package/dist/src/automations/api/routes.js.map +1 -1
  246. package/dist/src/automations/domain/validation.d.ts +14 -14
  247. package/dist/src/automations/draft/automation-draft-service.js +3 -3
  248. package/dist/src/automations/draft/automation-draft-service.js.map +1 -1
  249. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  250. package/dist/src/browser/providers/browser-ext-install.d.ts +11 -1
  251. package/dist/src/browser/providers/browser-ext-install.js +39 -14
  252. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  253. package/dist/src/capabilities/store-connector.d.ts +0 -1
  254. package/dist/src/capabilities/store-connector.js +3 -5
  255. package/dist/src/capabilities/store-connector.js.map +1 -1
  256. package/dist/src/chat-commands/builtins/review.js +84 -68
  257. package/dist/src/chat-commands/builtins/review.js.map +1 -1
  258. package/dist/src/chat-commands/builtins/workflow.js +9 -54
  259. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  260. package/dist/src/chat-commands/types.d.ts +4 -0
  261. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  262. package/dist/src/cli/commands/extension-create.js +2 -2
  263. package/dist/src/cli/commands/extension-create.js.map +1 -1
  264. package/dist/src/cli/commands/extension-marketplace.js +42 -36
  265. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  266. package/dist/src/cli/commands/extension-pack.d.ts +6 -0
  267. package/dist/src/cli/commands/extension-pack.js +3 -2
  268. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  269. package/dist/src/commands/agents.config.d.ts +1 -0
  270. package/dist/src/commands/agents.config.js +1 -0
  271. package/dist/src/commands/agents.config.js.map +1 -1
  272. package/dist/src/config/schema.d.ts +6 -6
  273. package/dist/src/config/schema.js +6 -22
  274. package/dist/src/config/schema.js.map +1 -1
  275. package/dist/src/config/web-patch.d.ts +1 -1
  276. package/dist/src/connectors/approval.d.ts +2 -0
  277. package/dist/src/connectors/approval.js +33 -0
  278. package/dist/src/connectors/approval.js.map +1 -0
  279. package/dist/src/connectors/auth-provider-registry.d.ts +9 -0
  280. package/dist/src/connectors/auth-provider-registry.js +17 -0
  281. package/dist/src/connectors/auth-provider-registry.js.map +1 -0
  282. package/dist/src/connectors/builtin-catalog.js +55 -116
  283. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  284. package/dist/src/connectors/catalog.js +7 -2
  285. package/dist/src/connectors/catalog.js.map +1 -1
  286. package/dist/src/connectors/composio-catalog.d.ts +19 -0
  287. package/dist/src/connectors/composio-catalog.js +237 -0
  288. package/dist/src/connectors/composio-catalog.js.map +1 -0
  289. package/dist/src/connectors/composio-logo.d.ts +1 -0
  290. package/dist/src/connectors/composio-logo.js +51 -0
  291. package/dist/src/connectors/composio-logo.js.map +1 -0
  292. package/dist/src/connectors/composio-sessions.d.ts +116 -0
  293. package/dist/src/connectors/composio-sessions.js +296 -0
  294. package/dist/src/connectors/composio-sessions.js.map +1 -0
  295. package/dist/src/connectors/composio-triggers.d.ts +17 -0
  296. package/dist/src/connectors/composio-triggers.js +48 -5
  297. package/dist/src/connectors/composio-triggers.js.map +1 -1
  298. package/dist/src/connectors/composio.d.ts +31 -2
  299. package/dist/src/connectors/composio.js +374 -151
  300. package/dist/src/connectors/composio.js.map +1 -1
  301. package/dist/src/connectors/connector-memory-sync.d.ts +15 -0
  302. package/dist/src/connectors/connector-memory-sync.js +90 -0
  303. package/dist/src/connectors/connector-memory-sync.js.map +1 -0
  304. package/dist/src/connectors/install.js +35 -92
  305. package/dist/src/connectors/install.js.map +1 -1
  306. package/dist/src/connectors/instances.js +6 -2
  307. package/dist/src/connectors/instances.js.map +1 -1
  308. package/dist/src/connectors/integration-strategy.d.ts +3 -0
  309. package/dist/src/connectors/integration-strategy.js +29 -0
  310. package/dist/src/connectors/integration-strategy.js.map +1 -0
  311. package/dist/src/connectors/policy.d.ts +13 -0
  312. package/dist/src/connectors/policy.js +48 -0
  313. package/dist/src/connectors/policy.js.map +1 -0
  314. package/dist/src/connectors/providers.js +1 -1
  315. package/dist/src/connectors/runtime-adapter-registry.d.ts +25 -0
  316. package/dist/src/connectors/runtime-adapter-registry.js +154 -0
  317. package/dist/src/connectors/runtime-adapter-registry.js.map +1 -0
  318. package/dist/src/connectors/types.d.ts +113 -4
  319. package/dist/src/connectors/workflow-preflight.d.ts +20 -0
  320. package/dist/src/connectors/workflow-preflight.js +70 -0
  321. package/dist/src/connectors/workflow-preflight.js.map +1 -0
  322. package/dist/src/extensions/install-transaction.d.ts +16 -0
  323. package/dist/src/extensions/install-transaction.js +76 -0
  324. package/dist/src/extensions/install-transaction.js.map +1 -0
  325. package/dist/src/extensions/install.d.ts +2 -0
  326. package/dist/src/extensions/install.js +23 -1
  327. package/dist/src/extensions/install.js.map +1 -1
  328. package/dist/src/gateway/agents-admin.d.ts +2 -0
  329. package/dist/src/gateway/agents-admin.js +7 -0
  330. package/dist/src/gateway/agents-admin.js.map +1 -1
  331. package/dist/src/gateway/capability-presets-admin.d.ts +11 -0
  332. package/dist/src/gateway/capability-presets-admin.js +11 -4
  333. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  334. package/dist/src/gateway/chat-stream/mapper.js +17 -0
  335. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  336. package/dist/src/gateway/chat-stream/protocol.d.ts +18 -1
  337. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -3
  338. package/dist/src/gateway/hono/routes/agents.js +3 -0
  339. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  340. package/dist/src/gateway/hono/routes/capability-presets.js +19 -1
  341. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  342. package/dist/src/gateway/hono/routes/connectors.js +188 -25
  343. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  344. package/dist/src/gateway/hono/routes/goals.js +22 -3
  345. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  346. package/dist/src/gateway/hono/routes/home.d.ts +60 -1
  347. package/dist/src/gateway/hono/routes/home.js +244 -18
  348. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  349. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  350. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  351. package/dist/src/gateway/hono/routes/memory.js +14 -1
  352. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  353. package/dist/src/gateway/hono/routes/models.js +1 -0
  354. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  355. package/dist/src/gateway/hono/routes/projects.js +103 -2
  356. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  357. package/dist/src/gateway/hono/routes/public-gateway.js +93 -0
  358. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  359. package/dist/src/gateway/hono/routes/voice.js +2 -2
  360. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  361. package/dist/src/gateway/hono/routes/workflows.js +137 -22
  362. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  363. package/dist/src/gateway/hono/routes/you.d.ts +23 -0
  364. package/dist/src/gateway/hono/routes/you.js +538 -0
  365. package/dist/src/gateway/hono/routes/you.js.map +1 -0
  366. package/dist/src/gateway/hono/sse.d.ts +2 -1
  367. package/dist/src/gateway/hono/sse.js +2 -1
  368. package/dist/src/gateway/hono/sse.js.map +1 -1
  369. package/dist/src/gateway/service/marketplace-service.d.ts +13 -1
  370. package/dist/src/gateway/service/marketplace-service.js +96 -40
  371. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  372. package/dist/src/gateway/service.d.ts +2 -0
  373. package/dist/src/gateway/service.js +7 -1
  374. package/dist/src/gateway/service.js.map +1 -1
  375. package/dist/src/goals/goal-contract-draft.js +2 -2
  376. package/dist/src/goals/goal-contract-draft.js.map +1 -1
  377. package/dist/src/goals/goal-evidence-review.js +2 -2
  378. package/dist/src/goals/goal-evidence-review.js.map +1 -1
  379. package/dist/src/goals/goal-service.d.ts +7 -5
  380. package/dist/src/goals/goal-service.js +25 -13
  381. package/dist/src/goals/goal-service.js.map +1 -1
  382. package/dist/src/goals/goal-store.js +46 -7
  383. package/dist/src/goals/goal-store.js.map +1 -1
  384. package/dist/src/goals/types.d.ts +24 -0
  385. package/dist/src/notes/service.js +2 -2
  386. package/dist/src/notes/service.js.map +1 -1
  387. package/dist/src/providers/constants.d.ts +2 -0
  388. package/dist/src/providers/constants.js +11 -0
  389. package/dist/src/providers/constants.js.map +1 -0
  390. package/dist/src/providers/extension-stream-bridge.js +1 -0
  391. package/dist/src/providers/extension-stream-bridge.js.map +1 -1
  392. package/dist/src/providers/index.d.ts +3 -3
  393. package/dist/src/providers/index.js +5 -4
  394. package/dist/src/providers/index.js.map +1 -1
  395. package/dist/src/providers/model-call.d.ts +17 -0
  396. package/dist/src/providers/model-call.js +60 -0
  397. package/dist/src/providers/model-call.js.map +1 -0
  398. package/dist/src/session/session-title.js +2 -2
  399. package/dist/src/session/session-title.js.map +1 -1
  400. package/dist/src/storage/sqlite/connector-repository.d.ts +49 -0
  401. package/dist/src/storage/sqlite/connector-repository.js +385 -0
  402. package/dist/src/storage/sqlite/connector-repository.js.map +1 -0
  403. package/dist/src/storage/sqlite/index.d.ts +3 -0
  404. package/dist/src/storage/sqlite/index.js +4 -1
  405. package/dist/src/storage/sqlite/migrations/030_connectors.sql +94 -0
  406. package/dist/src/storage/sqlite/migrations/031_connector_approvals.sql +24 -0
  407. package/dist/src/storage/sqlite/migrations/032_connector_webhook_deliveries.sql +15 -0
  408. package/dist/src/storage/sqlite/migrations/033_user_trust_policies.sql +6 -0
  409. package/dist/src/storage/sqlite/migrations/034_allow_global_auto_trust.sql +14 -0
  410. package/dist/src/storage/sqlite/migrations/035_user_profile_prompt_state.sql +7 -0
  411. package/dist/src/storage/sqlite/migrations/036_goal_outcome_metric.sql +12 -0
  412. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  413. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  414. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  415. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  416. package/dist/src/storage/sqlite/schema.js +1 -1
  417. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +3 -0
  418. package/dist/src/storage/sqlite/user-profile-setup-repository.js +34 -0
  419. package/dist/src/storage/sqlite/user-profile-setup-repository.js.map +1 -0
  420. package/dist/src/storage/sqlite/user-trust-repository.d.ts +3 -0
  421. package/dist/src/storage/sqlite/user-trust-repository.js +34 -0
  422. package/dist/src/storage/sqlite/user-trust-repository.js.map +1 -0
  423. package/dist/src/tui/components/assistant-message.js +15 -0
  424. package/dist/src/tui/components/assistant-message.js.map +1 -1
  425. package/dist/src/tui/tui-agent-events.js +85 -1
  426. package/dist/src/tui/tui-agent-events.js.map +1 -1
  427. package/dist/src/tui/tui-command-formatters.js +7 -7
  428. package/dist/src/tui/tui-command-formatters.js.map +1 -1
  429. package/dist/src/tui/tui-commands.js +1 -1
  430. package/dist/src/tui/tui-startup-resources.js +1 -1
  431. package/dist/src/user-context/import.d.ts +12 -0
  432. package/dist/src/user-context/import.js +48 -0
  433. package/dist/src/user-context/import.js.map +1 -0
  434. package/dist/src/user-context/profile.d.ts +37 -0
  435. package/dist/src/user-context/profile.js +165 -0
  436. package/dist/src/user-context/profile.js.map +1 -0
  437. package/dist/src/user-context/projection.d.ts +54 -0
  438. package/dist/src/user-context/projection.js +121 -0
  439. package/dist/src/user-context/projection.js.map +1 -0
  440. package/dist/src/user-context/source-recommendations.d.ts +13 -0
  441. package/dist/src/user-context/source-recommendations.js +86 -0
  442. package/dist/src/user-context/source-recommendations.js.map +1 -0
  443. package/dist/src/user-context/trust-policy.d.ts +11 -0
  444. package/dist/src/user-context/trust-policy.js +31 -0
  445. package/dist/src/user-context/trust-policy.js.map +1 -0
  446. package/dist/src/voice/tts/summarize.js +2 -2
  447. package/dist/src/voice/tts/summarize.js.map +1 -1
  448. package/dist/src/workflows/authoring/index.d.ts +1 -0
  449. package/dist/src/workflows/authoring/index.js +2 -0
  450. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +33 -0
  451. package/dist/src/workflows/authoring/workflow-draft-store.js +74 -0
  452. package/dist/src/workflows/authoring/workflow-draft-store.js.map +1 -0
  453. package/dist/src/workflows/domain/definition-utils.d.ts +6 -4
  454. package/dist/src/workflows/domain/definition-utils.js +28 -26
  455. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  456. package/dist/src/workflows/domain/definition.d.ts +79 -6
  457. package/dist/src/workflows/domain/event.d.ts +18 -2
  458. package/dist/src/workflows/domain/index.js +3 -3
  459. package/dist/src/workflows/domain/run.d.ts +16 -2
  460. package/dist/src/workflows/domain/run.js.map +1 -1
  461. package/dist/src/workflows/domain/validation.d.ts +9 -5
  462. package/dist/src/workflows/domain/validation.js +183 -40
  463. package/dist/src/workflows/domain/validation.js.map +1 -1
  464. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +2 -3
  465. package/dist/src/workflows/draft/workflow-draft-prompt.js +31 -73
  466. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -1
  467. package/dist/src/workflows/draft/workflow-draft-service.js +6 -10
  468. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  469. package/dist/src/workflows/draft/workflow-draft-validator.js +29 -37
  470. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -1
  471. package/dist/src/workflows/draft/workflow-draft.types.d.ts +4 -4
  472. package/dist/src/workflows/engine/projector.js +43 -1
  473. package/dist/src/workflows/engine/projector.js.map +1 -1
  474. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -3
  475. package/dist/src/workflows/engine/workflow-engine.js +24 -4
  476. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  477. package/dist/src/workflows/index.js +4 -7
  478. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +1 -9
  479. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -1
  480. package/dist/src/workflows/runtime/graph-workflow-runtime.d.ts +10 -0
  481. package/dist/src/workflows/runtime/graph-workflow-runtime.js +295 -0
  482. package/dist/src/workflows/runtime/graph-workflow-runtime.js.map +1 -0
  483. package/dist/src/workflows/runtime/index.d.ts +1 -2
  484. package/dist/src/workflows/runtime/index.js +2 -5
  485. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +5 -8
  486. package/dist/src/workflows/service/workflow-run-service.js +15 -1
  487. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  488. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -1
  489. package/package.json +8 -7
  490. package/dist/gateway/static/root/assets/agents-Bd863Akz.js +0 -2
  491. package/dist/gateway/static/root/assets/apps-page-B4omjLxa.js +0 -1
  492. package/dist/gateway/static/root/assets/automation-suggestion-card-fgtj5Gek.js +0 -1
  493. package/dist/gateway/static/root/assets/automations-page-Dz2mgjIR.js +0 -4
  494. package/dist/gateway/static/root/assets/browser-settings-page-DZZz5v_i.js +0 -8
  495. package/dist/gateway/static/root/assets/capability-presets-settings-panel-sCHojZr4.js +0 -1
  496. package/dist/gateway/static/root/assets/channels-settings-UyVSnf9s.js +0 -1
  497. package/dist/gateway/static/root/assets/channels-status-swr-CB5FzcLf.js +0 -1
  498. package/dist/gateway/static/root/assets/connectors-page-BzhHiUO4.js +0 -2
  499. package/dist/gateway/static/root/assets/desktop-pet-settings-DqqUPC7G.js +0 -1
  500. package/dist/gateway/static/root/assets/dreaming-settings-BmL54kQq.js +0 -3
  501. package/dist/gateway/static/root/assets/extension-page-DT5cpace.js +0 -1
  502. package/dist/gateway/static/root/assets/extension-settings-page-CbMk4GhQ.js +0 -1
  503. package/dist/gateway/static/root/assets/gateway-settings-CdghmKHJ.js +0 -1
  504. package/dist/gateway/static/root/assets/goal-create-dialog-CAlsM9MP.js +0 -1
  505. package/dist/gateway/static/root/assets/goal-detail-page-CLPa4F2y.js +0 -4
  506. package/dist/gateway/static/root/assets/goals-page-B2VpdzfH.js +0 -2
  507. package/dist/gateway/static/root/assets/goals-settings-CW1NwxvV.js +0 -1
  508. package/dist/gateway/static/root/assets/heartbeat-settings-C86k5tff.js +0 -1
  509. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +0 -1
  510. package/dist/gateway/static/root/assets/index-ehajXmqL.js +0 -262
  511. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-8xwKEhui.js +0 -1
  512. package/dist/gateway/static/root/assets/logs-page-C_BMONOO.js +0 -7
  513. package/dist/gateway/static/root/assets/messages-B-8CqAeX.js +0 -3
  514. package/dist/gateway/static/root/assets/models-hub-panel-Do_cwNjF.js +0 -2
  515. package/dist/gateway/static/root/assets/notes-page-5IdlPHaX.js +0 -1
  516. package/dist/gateway/static/root/assets/notes-workbench-0KsRZJIZ.js +0 -2
  517. package/dist/gateway/static/root/assets/project-detail-page-Dk2zB1gy.js +0 -1
  518. package/dist/gateway/static/root/assets/projects-page-CJQntm2G.js +0 -1
  519. package/dist/gateway/static/root/assets/remote-access-hub-CHeZZg7O.js +0 -1
  520. package/dist/gateway/static/root/assets/sessions-page-9Hb_r0AG.js +0 -1
  521. package/dist/gateway/static/root/assets/settings-advanced-gate-PmzVFvAv.js +0 -1
  522. package/dist/gateway/static/root/assets/settings-page-C5G2klUB.js +0 -1
  523. package/dist/gateway/static/root/assets/setup-status-panel-oQ8OLnw3.js +0 -1
  524. package/dist/gateway/static/root/assets/share-preview-page-CXtDHMSi.js +0 -2
  525. package/dist/gateway/static/root/assets/shares-settings-BlNoairj.js +0 -1
  526. package/dist/gateway/static/root/assets/skill-reload-api-BYV5x1KO.js +0 -1
  527. package/dist/gateway/static/root/assets/skills-page-ClBcKQZP.js +0 -2
  528. package/dist/gateway/static/root/assets/toast-z0toXu32.js +0 -1
  529. package/dist/gateway/static/root/assets/user-profile-settings-panel-CeC308-E.js +0 -1
  530. package/dist/gateway/static/root/assets/voice-api-key-field-BE57S-nS.js +0 -1
  531. package/dist/gateway/static/root/assets/work-item-detail-page-Di1ww5Aa.js +0 -1
  532. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CzK84i-B.js +0 -3
  533. package/dist/gateway/static/root/assets/workflow-start-dialog-CtLTtNUB.js +0 -1
  534. package/dist/gateway/static/root/assets/workflows-page-CZFZdua9.js +0 -18
  535. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +0 -13
  536. package/dist/src/agent/workflow/builtins/audit-repo.js +0 -183
  537. package/dist/src/agent/workflow/builtins/audit-repo.js.map +0 -1
  538. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +0 -12
  539. package/dist/src/agent/workflow/builtins/client-proposal.js +0 -164
  540. package/dist/src/agent/workflow/builtins/client-proposal.js.map +0 -1
  541. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +0 -12
  542. package/dist/src/agent/workflow/builtins/competitor-scan.js +0 -164
  543. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +0 -1
  544. package/dist/src/agent/workflow/builtins/content-draft.d.ts +0 -13
  545. package/dist/src/agent/workflow/builtins/content-draft.js +0 -159
  546. package/dist/src/agent/workflow/builtins/content-draft.js.map +0 -1
  547. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +0 -11
  548. package/dist/src/agent/workflow/builtins/content-repurpose.js +0 -146
  549. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +0 -1
  550. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +0 -13
  551. package/dist/src/agent/workflow/builtins/debug-incident.js +0 -177
  552. package/dist/src/agent/workflow/builtins/debug-incident.js.map +0 -1
  553. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +0 -13
  554. package/dist/src/agent/workflow/builtins/decision-compare.js +0 -187
  555. package/dist/src/agent/workflow/builtins/decision-compare.js.map +0 -1
  556. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +0 -12
  557. package/dist/src/agent/workflow/builtins/implementation-plan.js +0 -185
  558. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +0 -1
  559. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +0 -11
  560. package/dist/src/agent/workflow/builtins/inbox-triage.js +0 -158
  561. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +0 -1
  562. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +0 -12
  563. package/dist/src/agent/workflow/builtins/meeting-prep.js +0 -152
  564. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +0 -1
  565. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +0 -14
  566. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +0 -171
  567. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +0 -1
  568. package/dist/src/agent/workflow/builtins/offer-design.d.ts +0 -12
  569. package/dist/src/agent/workflow/builtins/offer-design.js +0 -170
  570. package/dist/src/agent/workflow/builtins/offer-design.js.map +0 -1
  571. package/dist/src/agent/workflow/builtins/pr-review.d.ts +0 -12
  572. package/dist/src/agent/workflow/builtins/pr-review.js +0 -178
  573. package/dist/src/agent/workflow/builtins/pr-review.js.map +0 -1
  574. package/dist/src/agent/workflow/builtins/release-check.d.ts +0 -11
  575. package/dist/src/agent/workflow/builtins/release-check.js +0 -174
  576. package/dist/src/agent/workflow/builtins/release-check.js.map +0 -1
  577. package/dist/src/agent/workflow/builtins/research.d.ts +0 -13
  578. package/dist/src/agent/workflow/builtins/research.js +0 -188
  579. package/dist/src/agent/workflow/builtins/research.js.map +0 -1
  580. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +0 -12
  581. package/dist/src/agent/workflow/builtins/weekly-review.js +0 -139
  582. package/dist/src/agent/workflow/builtins/weekly-review.js.map +0 -1
  583. package/dist/src/agent/workflow/last-run-memory.d.ts +0 -42
  584. package/dist/src/agent/workflow/last-run-memory.js +0 -60
  585. package/dist/src/agent/workflow/last-run-memory.js.map +0 -1
  586. package/dist/src/agent/workflow/lint.d.ts +0 -38
  587. package/dist/src/agent/workflow/lint.js +0 -74
  588. package/dist/src/agent/workflow/lint.js.map +0 -1
  589. package/dist/src/agent/workflow/meta-locale.d.ts +0 -12
  590. package/dist/src/agent/workflow/meta-locale.js +0 -62
  591. package/dist/src/agent/workflow/meta-locale.js.map +0 -1
  592. package/dist/src/agent/workflow/parser.d.ts +0 -20
  593. package/dist/src/agent/workflow/parser.js +0 -152
  594. package/dist/src/agent/workflow/parser.js.map +0 -1
  595. package/dist/src/agent/workflow/runtime.d.ts +0 -34
  596. package/dist/src/agent/workflow/runtime.js +0 -402
  597. package/dist/src/agent/workflow/runtime.js.map +0 -1
  598. package/dist/src/connectors/oauth.d.ts +0 -22
  599. package/dist/src/connectors/oauth.js +0 -99
  600. package/dist/src/connectors/oauth.js.map +0 -1
  601. package/dist/src/workflows/runtime/script-runtime.d.ts +0 -3
  602. package/dist/src/workflows/runtime/script-runtime.js +0 -3
  603. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +0 -5
  604. package/dist/src/workflows/runtime/script-workflow-runtime.js +0 -15
  605. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { init_sync_provider_auth, resolveProviderApiKeySync } from "../../auth/sync-provider-auth.js";
2
2
  import { getApiKeySync, init_providers } from "../../providers/index.js";
3
- import { AuthStorage } from "@earendil-works/pi-coding-agent";
3
+ import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
4
4
  //#region src/agent/embedded/xopc-auth-storage.ts
5
5
  init_sync_provider_auth();
6
6
  init_providers();
@@ -15,18 +15,18 @@ function resolveXopcProviderApiKey(providerId) {
15
15
  * pi-coding-agent {@link createAgentSession} defaults to `~/.pi/agent/auth.json` and env.
16
16
  * Gateway / webchat turns inject xopc credentials through {@link applyXopcProviderApiKey}.
17
17
  */
18
- function createEmbeddedAuthStorage() {
19
- return AuthStorage.create();
18
+ function createEmbeddedCredentialStore() {
19
+ return new InMemoryCredentialStore();
20
20
  }
21
21
  /**
22
22
  * Inject the resolved key as a runtime override (highest-priority, in-memory only) before
23
23
  * the session starts so request-time auth resolution finds it.
24
24
  */
25
- function applyXopcProviderApiKey(auth, providerId) {
25
+ async function applyXopcProviderApiKey(modelRuntime, providerId) {
26
26
  const key = resolveXopcProviderApiKey(providerId);
27
- if (key && key !== "extension-managed") auth.setRuntimeApiKey(providerId, key);
27
+ if (key && key !== "extension-managed") await modelRuntime.setRuntimeApiKey(providerId, key);
28
28
  }
29
29
  //#endregion
30
- export { applyXopcProviderApiKey, createEmbeddedAuthStorage, resolveXopcProviderApiKey };
30
+ export { applyXopcProviderApiKey, createEmbeddedCredentialStore, resolveXopcProviderApiKey };
31
31
 
32
32
  //# sourceMappingURL=xopc-auth-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xopc-auth-storage.js","names":[],"sources":["../../../../src/agent/embedded/xopc-auth-storage.ts"],"sourcesContent":["import { AuthStorage } from '@earendil-works/pi-coding-agent';\n\nimport { resolveProviderApiKeySync } from '../../auth/sync-provider-auth.js';\nimport { getApiKeySync } from '../../providers/index.js';\n\n/**\n * Resolve API keys the same way as {@link AgentManager} / gateway settings:\n * auth-profiles (agent + global), OAuth files, models.json, then env.\n */\nexport function resolveXopcProviderApiKey(providerId: string): string | undefined {\n return resolveProviderApiKeySync(providerId) ?? getApiKeySync(providerId);\n}\n\n/**\n * pi-coding-agent {@link createAgentSession} defaults to `~/.pi/agent/auth.json` and env.\n * Gateway / webchat turns inject xopc credentials through {@link applyXopcProviderApiKey}.\n */\nexport function createEmbeddedAuthStorage(): AuthStorage {\n return AuthStorage.create();\n}\n\n/**\n * Inject the resolved key as a runtime override (highest-priority, in-memory only) before\n * the session starts so request-time auth resolution finds it.\n */\nexport function applyXopcProviderApiKey(auth: AuthStorage, providerId: string): void {\n const key = resolveXopcProviderApiKey(providerId);\n if (key && key !== 'extension-managed') {\n auth.setRuntimeApiKey(providerId, key);\n }\n}\n"],"mappings":";;;;yBAE6E;gBACpB;;;;;AAMzD,SAAgB,0BAA0B,YAAwC;AAChF,QAAO,0BAA0B,WAAW,IAAI,cAAc,WAAW;;;;;;AAO3E,SAAgB,4BAAyC;AACvD,QAAO,YAAY,QAAQ;;;;;;AAO7B,SAAgB,wBAAwB,MAAmB,YAA0B;CACnF,MAAM,MAAM,0BAA0B,WAAW;AACjD,KAAI,OAAO,QAAQ,oBACjB,MAAK,iBAAiB,YAAY,IAAI"}
1
+ {"version":3,"file":"xopc-auth-storage.js","names":[],"sources":["../../../../src/agent/embedded/xopc-auth-storage.ts"],"sourcesContent":["import { InMemoryCredentialStore } from '@earendil-works/pi-ai';\nimport type { ModelRuntime } from '@earendil-works/pi-coding-agent';\n\nimport { resolveProviderApiKeySync } from '../../auth/sync-provider-auth.js';\nimport { getApiKeySync } from '../../providers/index.js';\n\n/**\n * Resolve API keys the same way as {@link AgentManager} / gateway settings:\n * auth-profiles (agent + global), OAuth files, models.json, then env.\n */\nexport function resolveXopcProviderApiKey(providerId: string): string | undefined {\n return resolveProviderApiKeySync(providerId) ?? getApiKeySync(providerId);\n}\n\n/**\n * pi-coding-agent {@link createAgentSession} defaults to `~/.pi/agent/auth.json` and env.\n * Gateway / webchat turns inject xopc credentials through {@link applyXopcProviderApiKey}.\n */\nexport function createEmbeddedCredentialStore(): InMemoryCredentialStore {\n return new InMemoryCredentialStore();\n}\n\n/**\n * Inject the resolved key as a runtime override (highest-priority, in-memory only) before\n * the session starts so request-time auth resolution finds it.\n */\nexport async function applyXopcProviderApiKey(\n modelRuntime: Pick<ModelRuntime, 'setRuntimeApiKey'>,\n providerId: string,\n): Promise<void> {\n const key = resolveXopcProviderApiKey(providerId);\n if (key && key !== 'extension-managed') {\n await modelRuntime.setRuntimeApiKey(providerId, key);\n }\n}\n"],"mappings":";;;;yBAG6E;gBACpB;;;;;AAMzD,SAAgB,0BAA0B,YAAwC;AAChF,QAAO,0BAA0B,WAAW,IAAI,cAAc,WAAW;;;;;;AAO3E,SAAgB,gCAAyD;AACvE,QAAO,IAAI,yBAAyB;;;;;;AAOtC,eAAsB,wBACpB,cACA,YACe;CACf,MAAM,MAAM,0BAA0B,WAAW;AACjD,KAAI,OAAO,QAAQ,oBACjB,OAAM,aAAa,iBAAiB,YAAY,IAAI"}
@@ -1,3 +1,4 @@
1
+ import "../../providers/constants.js";
1
2
  import { init_providers } from "../../providers/index.js";
2
3
  import { createExtensionAwareStreamFn } from "../../providers/extension-stream-bridge.js";
3
4
  //#region src/agent/embedded/xopc-stream-bridge.ts
@@ -1 +1 @@
1
- {"version":3,"file":"xopc-stream-bridge.js","names":[],"sources":["../../../../src/agent/embedded/xopc-stream-bridge.ts"],"sourcesContent":["import type { Model, Api, Context, SimpleStreamOptions } from '@earendil-works/pi-ai';\nimport type { StreamFn } from '@earendil-works/pi-agent-core';\n\nimport { EXTENSION_PROVIDER_BASE_URL } from '../../providers/index.js';\nimport { createExtensionAwareStreamFn } from '../../providers/extension-stream-bridge.js';\n\n/**\n * pi-coding-agent's default {@link createAgentSession} streamFn always routes through\n * pi-ai's HTTP `streamSimple`, so xopc plugin providers (whose models carry the sentinel\n * `EXTENSION_PROVIDER_BASE_URL`) never reach their {@link ProviderPluginRegistry}\n * implementation. Wrap the original streamFn so plugin models go through xopc's bridge\n * and everything else falls through to the original auth-aware streamFn.\n *\n * Use this by reassigning {@link Agent.streamFn} after `createAgentSession` returns.\n */\nexport function wrapStreamFnForXopcExtensions(originalStreamFn: StreamFn): StreamFn {\n const extensionStreamFn = createExtensionAwareStreamFn();\n\n return ((model: Model<Api>, context: Context, options?: SimpleStreamOptions) => {\n if (model.baseUrl === EXTENSION_PROVIDER_BASE_URL) {\n return extensionStreamFn(model, context, options);\n }\n return originalStreamFn(model, context, options);\n }) as StreamFn;\n}\n"],"mappings":";;;gBAGuE;;;;;;;;;;AAYvE,SAAgB,8BAA8B,kBAAsC;CAClF,MAAM,oBAAoB,8BAA8B;AAExD,UAAS,OAAmB,SAAkB,YAAkC;AAC9E,MAAI,MAAM,YAAA,8BACR,QAAO,kBAAkB,OAAO,SAAS,QAAQ;AAEnD,SAAO,iBAAiB,OAAO,SAAS,QAAQ"}
1
+ {"version":3,"file":"xopc-stream-bridge.js","names":[],"sources":["../../../../src/agent/embedded/xopc-stream-bridge.ts"],"sourcesContent":["import type { Model, Api, Context, SimpleStreamOptions } from '@earendil-works/pi-ai';\nimport type { StreamFn } from '@earendil-works/pi-agent-core';\n\nimport { EXTENSION_PROVIDER_BASE_URL } from '../../providers/index.js';\nimport { createExtensionAwareStreamFn } from '../../providers/extension-stream-bridge.js';\n\n/**\n * pi-coding-agent's default {@link createAgentSession} streamFn always routes through\n * pi-ai's HTTP `streamSimple`, so xopc plugin providers (whose models carry the sentinel\n * `EXTENSION_PROVIDER_BASE_URL`) never reach their {@link ProviderPluginRegistry}\n * implementation. Wrap the original streamFn so plugin models go through xopc's bridge\n * and everything else falls through to the original auth-aware streamFn.\n *\n * Use this by reassigning {@link Agent.streamFn} after `createAgentSession` returns.\n */\nexport function wrapStreamFnForXopcExtensions(originalStreamFn: StreamFn): StreamFn {\n const extensionStreamFn = createExtensionAwareStreamFn();\n\n return ((model: Model<Api>, context: Context, options?: SimpleStreamOptions) => {\n if (model.baseUrl === EXTENSION_PROVIDER_BASE_URL) {\n return extensionStreamFn(model, context, options);\n }\n return originalStreamFn(model, context, options);\n }) as StreamFn;\n}\n"],"mappings":";;;;gBAGuE;;;;;;;;;;AAYvE,SAAgB,8BAA8B,kBAAsC;CAClF,MAAM,oBAAoB,8BAA8B;AAExD,UAAS,OAAmB,SAAkB,YAAkC;AAC9E,MAAI,MAAM,YAAA,8BACR,QAAO,kBAAkB,OAAO,SAAS,QAAQ;AAEnD,SAAO,iBAAiB,OAAO,SAAS,QAAQ"}
@@ -1,4 +1,13 @@
1
1
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
2
  import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
3
+ export type ApplyPatchEnvelopeError = {
4
+ code: 'invalid_patch_envelope';
5
+ field: 'patch';
6
+ issue: 'missing_patch' | 'first_line' | 'control_line' | 'last_line';
7
+ expected: string;
8
+ received?: string;
9
+ retryHint: string;
10
+ };
11
+ export declare function validateApplyPatchEnvelope(params: unknown): ApplyPatchEnvelopeError | null;
3
12
  /** Map xopc {@link AgentTool} instances to pi-coding-agent {@link ToolDefinition}s for `createAgentSession`. */
4
13
  export declare function xopcToolsToDefinitions(tools: AgentTool[]): ToolDefinition[];
@@ -1,4 +1,6 @@
1
1
  //#region src/agent/embedded/xopc-tools-bridge.ts
2
+ const APPLY_PATCH_BEGIN_MARKER = "*** Begin Patch";
3
+ const APPLY_PATCH_END_MARKER = "*** End Patch";
2
4
  const TOOL_PROMPT_HINTS = {
3
5
  read_file: {
4
6
  promptSnippet: "Read targeted file contents",
@@ -9,8 +11,14 @@ const TOOL_PROMPT_HINTS = {
9
11
  promptGuidelines: ["Prefer apply_patch for code changes. Use write_file only for non-code artifacts or deliberate full-file rewrites."]
10
12
  },
11
13
  apply_patch: {
12
- promptSnippet: "Apply strict multi-file patches for code edits",
13
- promptGuidelines: ["Use apply_patch for all source edits. Keep patches small and verify with exec_command."]
14
+ promptSnippet: "Apply patches using the exact apply_patch envelope",
15
+ promptGuidelines: [
16
+ "Use apply_patch for source edits. Keep patches small and verify with exec_command.",
17
+ "The patch must start exactly with `*** Begin Patch` and end exactly with `*** End Patch`.",
18
+ "Patch control lines must not end in ` ***`; do not wrap the patch in a Markdown code fence or add prose.",
19
+ "Use this shape: `*** Begin Patch\\n*** Update File: path\\n@@\\n-old\\n+new\\n*** End Patch`.",
20
+ "If apply_patch rejects the envelope, regenerate the complete patch from this exact shape instead of repeating it."
21
+ ]
14
22
  },
15
23
  exec_command: {
16
24
  promptSnippet: "Run tests, type checks, builds, package scripts, and safe inspection commands",
@@ -23,6 +31,62 @@ const TOOL_PROMPT_HINTS = {
23
31
  grep: { promptSnippet: "Search file contents for literals, errors, config values, and docs" },
24
32
  find: { promptSnippet: "Find files by glob pattern" }
25
33
  };
34
+ function validateApplyPatchEnvelope(params) {
35
+ if (!params || typeof params !== "object" || Array.isArray(params)) return {
36
+ code: "invalid_patch_envelope",
37
+ field: "patch",
38
+ issue: "missing_patch",
39
+ expected: APPLY_PATCH_BEGIN_MARKER,
40
+ retryHint: "Pass a patch string beginning with the exact marker `*** Begin Patch`."
41
+ };
42
+ const patch = params.patch;
43
+ if (typeof patch !== "string") return {
44
+ code: "invalid_patch_envelope",
45
+ field: "patch",
46
+ issue: "missing_patch",
47
+ expected: APPLY_PATCH_BEGIN_MARKER,
48
+ retryHint: "Pass a patch string beginning with the exact marker `*** Begin Patch`."
49
+ };
50
+ const lines = patch.split(/\r?\n/);
51
+ const firstLine = lines[0] ?? "";
52
+ if (firstLine !== APPLY_PATCH_BEGIN_MARKER) return {
53
+ code: "invalid_patch_envelope",
54
+ field: "patch",
55
+ issue: "first_line",
56
+ expected: APPLY_PATCH_BEGIN_MARKER,
57
+ received: firstLine,
58
+ retryHint: "Use `*** Begin Patch` exactly. Do not add trailing ` ***`, prose, or a Markdown code fence."
59
+ };
60
+ const malformedControlLine = lines.slice(1, -1).find((line) => line.startsWith("*** ") && line.endsWith(" ***"));
61
+ if (malformedControlLine) return {
62
+ code: "invalid_patch_envelope",
63
+ field: "patch",
64
+ issue: "control_line",
65
+ expected: malformedControlLine.slice(0, -4),
66
+ received: malformedControlLine,
67
+ retryHint: "Patch control lines must not end in ` ***`. Remove the trailing stars from this control line."
68
+ };
69
+ const lastLine = lines.at(-1) ?? "";
70
+ if (lastLine !== APPLY_PATCH_END_MARKER) return {
71
+ code: "invalid_patch_envelope",
72
+ field: "patch",
73
+ issue: "last_line",
74
+ expected: APPLY_PATCH_END_MARKER,
75
+ received: lastLine,
76
+ retryHint: "End the patch with `*** End Patch` exactly. Do not add trailing ` ***` or prose."
77
+ };
78
+ return null;
79
+ }
80
+ function invalidApplyPatchEnvelopeResult(error) {
81
+ const received = error.received === void 0 ? "" : ` Received: ${JSON.stringify(error.received)}.`;
82
+ return {
83
+ content: [{
84
+ type: "text",
85
+ text: `apply_patch input rejected (${error.issue}). Expected: ${error.expected}.${received} ${error.retryHint} Use this exact envelope:\n${APPLY_PATCH_BEGIN_MARKER}\n*** Update File: path\n@@\n-old\n+new\n${APPLY_PATCH_END_MARKER}`
86
+ }],
87
+ details: error
88
+ };
89
+ }
26
90
  /** Map xopc {@link AgentTool} instances to pi-coding-agent {@link ToolDefinition}s for `createAgentSession`. */
27
91
  function xopcToolsToDefinitions(tools) {
28
92
  return tools.map((tool) => {
@@ -35,12 +99,16 @@ function xopcToolsToDefinitions(tools) {
35
99
  ...promptHints?.promptGuidelines ? { promptGuidelines: promptHints.promptGuidelines } : {},
36
100
  parameters: tool.parameters,
37
101
  async execute(toolCallId, params, signal, onUpdate) {
102
+ if (tool.name === "apply_patch") {
103
+ const envelopeError = validateApplyPatchEnvelope(params);
104
+ if (envelopeError) return invalidApplyPatchEnvelopeResult(envelopeError);
105
+ }
38
106
  return tool.execute(toolCallId, params, signal, onUpdate);
39
107
  }
40
108
  };
41
109
  });
42
110
  }
43
111
  //#endregion
44
- export { xopcToolsToDefinitions };
112
+ export { validateApplyPatchEnvelope, xopcToolsToDefinitions };
45
113
 
46
114
  //# sourceMappingURL=xopc-tools-bridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xopc-tools-bridge.js","names":[],"sources":["../../../../src/agent/embedded/xopc-tools-bridge.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\n\nconst TOOL_PROMPT_HINTS: Record<string, { promptSnippet?: string; promptGuidelines?: string[] }> = {\n read_file: {\n promptSnippet: 'Read targeted file contents',\n promptGuidelines: ['Use read_file to inspect source files before editing.'],\n },\n write_file: {\n promptSnippet: 'Create new files or intentional complete rewrites',\n promptGuidelines: ['Prefer apply_patch for code changes. Use write_file only for non-code artifacts or deliberate full-file rewrites.'],\n },\n apply_patch: {\n promptSnippet: 'Apply strict multi-file patches for code edits',\n promptGuidelines: ['Use apply_patch for all source edits. Keep patches small and verify with exec_command.'],\n },\n exec_command: {\n promptSnippet: 'Run tests, type checks, builds, package scripts, and safe inspection commands',\n promptGuidelines: ['Use exec_command for verification and safe inspection, not routine file editing.'],\n },\n update_plan: {\n promptSnippet: 'Update the visible multi-step coding plan',\n promptGuidelines: ['Use update_plan for multi-step coding work and keep the active step current.'],\n },\n grep: {\n promptSnippet: 'Search file contents for literals, errors, config values, and docs',\n },\n find: {\n promptSnippet: 'Find files by glob pattern',\n },\n};\n\n/** Map xopc {@link AgentTool} instances to pi-coding-agent {@link ToolDefinition}s for `createAgentSession`. */\nexport function xopcToolsToDefinitions(tools: AgentTool[]): ToolDefinition[] {\n return tools.map((tool) => {\n const promptHints = TOOL_PROMPT_HINTS[tool.name];\n const def = {\n name: tool.name,\n label: tool.label ?? tool.name,\n description: tool.description ?? tool.name,\n ...(promptHints?.promptSnippet ? { promptSnippet: promptHints.promptSnippet } : {}),\n ...(promptHints?.promptGuidelines ? { promptGuidelines: promptHints.promptGuidelines } : {}),\n parameters: tool.parameters,\n async execute(\n toolCallId: string,\n params: unknown,\n signal: AbortSignal | undefined,\n onUpdate: unknown,\n ) {\n return (tool as { execute: (...a: never[]) => unknown }).execute(\n toolCallId as never,\n params as never,\n signal as never,\n onUpdate as never,\n ) as never;\n },\n };\n return def as unknown as ToolDefinition;\n });\n}\n"],"mappings":";AAGA,MAAM,oBAA6F;CACjG,WAAW;EACT,eAAe;EACf,kBAAkB,CAAC,wDAAwD;EAC5E;CACD,YAAY;EACV,eAAe;EACf,kBAAkB,CAAC,oHAAoH;EACxI;CACD,aAAa;EACX,eAAe;EACf,kBAAkB,CAAC,yFAAyF;EAC7G;CACD,cAAc;EACZ,eAAe;EACf,kBAAkB,CAAC,mFAAmF;EACvG;CACD,aAAa;EACX,eAAe;EACf,kBAAkB,CAAC,+EAA+E;EACnG;CACD,MAAM,EACJ,eAAe,sEAChB;CACD,MAAM,EACJ,eAAe,8BAChB;CACF;;AAGD,SAAgB,uBAAuB,OAAsC;AAC3E,QAAO,MAAM,KAAK,SAAS;EACzB,MAAM,cAAc,kBAAkB,KAAK;AAsB3C,SAAO;GApBL,MAAM,KAAK;GACX,OAAO,KAAK,SAAS,KAAK;GAC1B,aAAa,KAAK,eAAe,KAAK;GACtC,GAAI,aAAa,gBAAgB,EAAE,eAAe,YAAY,eAAe,GAAG,EAAE;GAClF,GAAI,aAAa,mBAAmB,EAAE,kBAAkB,YAAY,kBAAkB,GAAG,EAAE;GAC3F,YAAY,KAAK;GACjB,MAAM,QACJ,YACA,QACA,QACA,UACA;AACA,WAAQ,KAAiD,QACvD,YACA,QACA,QACA,SACD;;GAGK;GACV"}
1
+ {"version":3,"file":"xopc-tools-bridge.js","names":[],"sources":["../../../../src/agent/embedded/xopc-tools-bridge.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\n\nconst APPLY_PATCH_BEGIN_MARKER = '*** Begin Patch';\nconst APPLY_PATCH_END_MARKER = '*** End Patch';\n\nexport type ApplyPatchEnvelopeError = {\n code: 'invalid_patch_envelope';\n field: 'patch';\n issue: 'missing_patch' | 'first_line' | 'control_line' | 'last_line';\n expected: string;\n received?: string;\n retryHint: string;\n};\n\nconst TOOL_PROMPT_HINTS: Record<string, { promptSnippet?: string; promptGuidelines?: string[] }> = {\n read_file: {\n promptSnippet: 'Read targeted file contents',\n promptGuidelines: ['Use read_file to inspect source files before editing.'],\n },\n write_file: {\n promptSnippet: 'Create new files or intentional complete rewrites',\n promptGuidelines: ['Prefer apply_patch for code changes. Use write_file only for non-code artifacts or deliberate full-file rewrites.'],\n },\n apply_patch: {\n promptSnippet: 'Apply patches using the exact apply_patch envelope',\n promptGuidelines: [\n 'Use apply_patch for source edits. Keep patches small and verify with exec_command.',\n 'The patch must start exactly with `*** Begin Patch` and end exactly with `*** End Patch`.',\n 'Patch control lines must not end in ` ***`; do not wrap the patch in a Markdown code fence or add prose.',\n 'Use this shape: `*** Begin Patch\\\\n*** Update File: path\\\\n@@\\\\n-old\\\\n+new\\\\n*** End Patch`.',\n 'If apply_patch rejects the envelope, regenerate the complete patch from this exact shape instead of repeating it.',\n ],\n },\n exec_command: {\n promptSnippet: 'Run tests, type checks, builds, package scripts, and safe inspection commands',\n promptGuidelines: ['Use exec_command for verification and safe inspection, not routine file editing.'],\n },\n update_plan: {\n promptSnippet: 'Update the visible multi-step coding plan',\n promptGuidelines: ['Use update_plan for multi-step coding work and keep the active step current.'],\n },\n grep: {\n promptSnippet: 'Search file contents for literals, errors, config values, and docs',\n },\n find: {\n promptSnippet: 'Find files by glob pattern',\n },\n};\n\nexport function validateApplyPatchEnvelope(params: unknown): ApplyPatchEnvelopeError | null {\n if (!params || typeof params !== 'object' || Array.isArray(params)) {\n return {\n code: 'invalid_patch_envelope',\n field: 'patch',\n issue: 'missing_patch',\n expected: APPLY_PATCH_BEGIN_MARKER,\n retryHint: 'Pass a patch string beginning with the exact marker `*** Begin Patch`.',\n };\n }\n\n const patch = (params as { patch?: unknown }).patch;\n if (typeof patch !== 'string') {\n return {\n code: 'invalid_patch_envelope',\n field: 'patch',\n issue: 'missing_patch',\n expected: APPLY_PATCH_BEGIN_MARKER,\n retryHint: 'Pass a patch string beginning with the exact marker `*** Begin Patch`.',\n };\n }\n\n const lines = patch.split(/\\r?\\n/);\n const firstLine = lines[0] ?? '';\n if (firstLine !== APPLY_PATCH_BEGIN_MARKER) {\n return {\n code: 'invalid_patch_envelope',\n field: 'patch',\n issue: 'first_line',\n expected: APPLY_PATCH_BEGIN_MARKER,\n received: firstLine,\n retryHint: 'Use `*** Begin Patch` exactly. Do not add trailing ` ***`, prose, or a Markdown code fence.',\n };\n }\n\n const malformedControlLine = lines.slice(1, -1).find((line) => line.startsWith('*** ') && line.endsWith(' ***'));\n if (malformedControlLine) {\n return {\n code: 'invalid_patch_envelope',\n field: 'patch',\n issue: 'control_line',\n expected: malformedControlLine.slice(0, -4),\n received: malformedControlLine,\n retryHint: 'Patch control lines must not end in ` ***`. Remove the trailing stars from this control line.',\n };\n }\n\n const lastLine = lines.at(-1) ?? '';\n if (lastLine !== APPLY_PATCH_END_MARKER) {\n return {\n code: 'invalid_patch_envelope',\n field: 'patch',\n issue: 'last_line',\n expected: APPLY_PATCH_END_MARKER,\n received: lastLine,\n retryHint: 'End the patch with `*** End Patch` exactly. Do not add trailing ` ***` or prose.',\n };\n }\n\n return null;\n}\n\nfunction invalidApplyPatchEnvelopeResult(error: ApplyPatchEnvelopeError) {\n const received = error.received === undefined ? '' : ` Received: ${JSON.stringify(error.received)}.`;\n return {\n content: [{\n type: 'text' as const,\n text: `apply_patch input rejected (${error.issue}). Expected: ${error.expected}.${received} ${error.retryHint} Use this exact envelope:\\n${APPLY_PATCH_BEGIN_MARKER}\\n*** Update File: path\\n@@\\n-old\\n+new\\n${APPLY_PATCH_END_MARKER}`,\n }],\n details: error,\n };\n}\n\n/** Map xopc {@link AgentTool} instances to pi-coding-agent {@link ToolDefinition}s for `createAgentSession`. */\nexport function xopcToolsToDefinitions(tools: AgentTool[]): ToolDefinition[] {\n return tools.map((tool) => {\n const promptHints = TOOL_PROMPT_HINTS[tool.name];\n const def = {\n name: tool.name,\n label: tool.label ?? tool.name,\n description: tool.description ?? tool.name,\n ...(promptHints?.promptSnippet ? { promptSnippet: promptHints.promptSnippet } : {}),\n ...(promptHints?.promptGuidelines ? { promptGuidelines: promptHints.promptGuidelines } : {}),\n parameters: tool.parameters,\n async execute(\n toolCallId: string,\n params: unknown,\n signal: AbortSignal | undefined,\n onUpdate: unknown,\n ) {\n if (tool.name === 'apply_patch') {\n const envelopeError = validateApplyPatchEnvelope(params);\n if (envelopeError) {\n return invalidApplyPatchEnvelopeResult(envelopeError) as never;\n }\n }\n\n return (tool as { execute: (...a: never[]) => unknown }).execute(\n toolCallId as never,\n params as never,\n signal as never,\n onUpdate as never,\n ) as never;\n },\n };\n return def as unknown as ToolDefinition;\n });\n}\n"],"mappings":";AAGA,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAW/B,MAAM,oBAA6F;CACjG,WAAW;EACT,eAAe;EACf,kBAAkB,CAAC,wDAAwD;EAC5E;CACD,YAAY;EACV,eAAe;EACf,kBAAkB,CAAC,oHAAoH;EACxI;CACD,aAAa;EACX,eAAe;EACf,kBAAkB;GAChB;GACA;GACA;GACA;GACA;GACD;EACF;CACD,cAAc;EACZ,eAAe;EACf,kBAAkB,CAAC,mFAAmF;EACvG;CACD,aAAa;EACX,eAAe;EACf,kBAAkB,CAAC,+EAA+E;EACnG;CACD,MAAM,EACJ,eAAe,sEAChB;CACD,MAAM,EACJ,eAAe,8BAChB;CACF;AAED,SAAgB,2BAA2B,QAAiD;AAC1F,KAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,CAChE,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;EACP,UAAU;EACV,WAAW;EACZ;CAGH,MAAM,QAAS,OAA+B;AAC9C,KAAI,OAAO,UAAU,SACnB,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;EACP,UAAU;EACV,WAAW;EACZ;CAGH,MAAM,QAAQ,MAAM,MAAM,QAAQ;CAClC,MAAM,YAAY,MAAM,MAAM;AAC9B,KAAI,cAAc,yBAChB,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW;EACZ;CAGH,MAAM,uBAAuB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,SAAS,KAAK,WAAW,OAAO,IAAI,KAAK,SAAS,OAAO,CAAC;AAChH,KAAI,qBACF,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;EACP,UAAU,qBAAqB,MAAM,GAAG,GAAG;EAC3C,UAAU;EACV,WAAW;EACZ;CAGH,MAAM,WAAW,MAAM,GAAG,GAAG,IAAI;AACjC,KAAI,aAAa,uBACf,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW;EACZ;AAGH,QAAO;;AAGT,SAAS,gCAAgC,OAAgC;CACvE,MAAM,WAAW,MAAM,aAAa,KAAA,IAAY,KAAK,cAAc,KAAK,UAAU,MAAM,SAAS,CAAC;AAClG,QAAO;EACL,SAAS,CAAC;GACR,MAAM;GACN,MAAM,+BAA+B,MAAM,MAAM,eAAe,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,UAAU,6BAA6B,yBAAyB,2CAA2C;GAChN,CAAC;EACF,SAAS;EACV;;;AAIH,SAAgB,uBAAuB,OAAsC;AAC3E,QAAO,MAAM,KAAK,SAAS;EACzB,MAAM,cAAc,kBAAkB,KAAK;AA6B3C,SAAO;GA3BL,MAAM,KAAK;GACX,OAAO,KAAK,SAAS,KAAK;GAC1B,aAAa,KAAK,eAAe,KAAK;GACtC,GAAI,aAAa,gBAAgB,EAAE,eAAe,YAAY,eAAe,GAAG,EAAE;GAClF,GAAI,aAAa,mBAAmB,EAAE,kBAAkB,YAAY,kBAAkB,GAAG,EAAE;GAC3F,YAAY,KAAK;GACjB,MAAM,QACJ,YACA,QACA,QACA,UACA;AACA,QAAI,KAAK,SAAS,eAAe;KAC/B,MAAM,gBAAgB,2BAA2B,OAAO;AACxD,SAAI,cACF,QAAO,gCAAgC,cAAc;;AAIzD,WAAQ,KAAiD,QACvD,YACA,QACA,QACA,SACD;;GAGK;GACV"}
@@ -1,8 +1,8 @@
1
1
  import { init_providers, resolveModel } from "../../providers/index.js";
2
+ import { completeWithResolvedCredentials } from "../../providers/model-call.js";
2
3
  import { JUDGE_REASON_EN } from "../../i18n/goals-bundle.js";
3
4
  import { goalUiLocaleOrFallback, judgeReasonText, judgeResponseLanguageNote, localizeJudgeReasonText } from "./goal-locale.js";
4
5
  import { DEFAULT_JUDGE_TIMEOUT_MS, extractAssistantText, getAssistantMessageErrorReason, resolveGoalJudgeApiKey, stripCodeFences, truncateGoalText } from "./judge.js";
5
- import { complete } from "@earendil-works/pi-ai/compat";
6
6
  //#region src/agent/goals/checklist-judge.ts
7
7
  init_providers();
8
8
  const GOAL_TRUNC = 4e3;
@@ -59,7 +59,7 @@ async function decomposeGoalChecklist(opts) {
59
59
  timestamp: Date.now()
60
60
  };
61
61
  const apiKey = await resolveGoalJudgeApiKey(model);
62
- const result = await complete(model, { messages: [user] }, {
62
+ const result = await completeWithResolvedCredentials(model, { messages: [user] }, {
63
63
  apiKey,
64
64
  maxTokens: 2e3,
65
65
  temperature: 0,
@@ -138,7 +138,7 @@ async function evaluateGoalChecklistJudge(opts) {
138
138
  timestamp: Date.now()
139
139
  };
140
140
  const apiKey = await resolveGoalJudgeApiKey(model);
141
- const result = await complete(model, { messages: [user] }, {
141
+ const result = await completeWithResolvedCredentials(model, { messages: [user] }, {
142
142
  apiKey,
143
143
  maxTokens: 1500,
144
144
  temperature: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"checklist-judge.js","names":[],"sources":["../../../../src/agent/goals/checklist-judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\nimport { complete } from '@earendil-works/pi-ai/compat';\n\nimport { resolveModel } from '../../providers/index.js';\n\nimport {\n DEFAULT_JUDGE_TIMEOUT_MS,\n extractAssistantText,\n getAssistantMessageErrorReason,\n resolveGoalJudgeApiKey,\n stripCodeFences,\n truncateGoalText,\n} from './judge.js';\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeReasonText,\n judgeResponseLanguageNote,\n JUDGE_REASON_EN,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst GOAL_TRUNC = 4000;\nconst RESPONSE_SNIPPET = 4000;\nconst HISTORY_TRUNC = 24_000;\n\nconst DECOMPOSE_SYSTEM = (\n 'You break a user goal into an EXTREMELY detailed checklist of concrete, verifiable completion criteria. ' +\n 'Bias toward more items. Each item is one factual statement about finished work.\\n\\n' +\n 'If existing acceptance criteria are provided, return only missing supplemental criteria. ' +\n 'Do not repeat, rewrite, or replace existing criteria.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"items\":[{\"text\":\"...\"},...]}\\n' +\n 'Use at least 3 items when the goal warrants it.'\n);\n\nconst DECOMPOSE_USER = 'Goal:\\n{goal}\\n\\nReturn JSON only.';\n\nconst EVALUATE_CHECKLIST_SYSTEM = (\n 'You evaluate an autonomous agent\\'s progress on a goal with a numbered checklist.\\n' +\n 'For each pending item, decide if evidence in the agent snippet and/or history excerpt shows it is satisfied.\\n' +\n 'Flip pending→completed only with clear evidence; pending→impossible only if truly unachievable here.\\n' +\n 'Do not regress completed/impossible items — omit them from updates.\\n\\n' +\n 'Reply ONLY with one JSON object on one line:\\n' +\n '{\"verdict\":\"continue|done|blocked|needs_input\",\"confidence\":0.0,\"reason\":\"...\",' +\n '\"nextAction\":\"...\",\"missingEvidence\":[\"...\"],\"userQuestion\":\"...\",' +\n '\"updates\":[{\"index\":1,\"status\":\"completed|impossible\",\"evidence\":\"short citation\"}],' +\n '\"new_items\":[{\"text\":\"...\"}]}\\n' +\n 'Use verdict=done only when all checklist criteria are complete/impossible. ' +\n 'Use needs_input when the next step requires user input. Use blocked when external progress is impossible.'\n);\n\nfunction extractJsonObject(raw: string): Record<string, unknown> | null {\n if (!raw?.trim()) return null;\n const text = stripCodeFences(raw);\n try {\n const data = JSON.parse(text) as unknown;\n return data && typeof data === 'object' && !Array.isArray(data) ? (data as Record<string, unknown>) : null;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n try {\n const data = JSON.parse(text.slice(start, end + 1)) as unknown;\n return data && typeof data === 'object' && !Array.isArray(data) ? (data as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n }\n}\n\nexport type DecomposeChecklistResult = {\n items: { text: string }[];\n parseFailed: boolean;\n errorReason?: string;\n};\n\nexport async function decomposeGoalChecklist(opts: {\n goal: string;\n existingChecklist?: string;\n judgeModelRef: string;\n signal?: AbortSignal;\n judgeTimeoutMs?: number;\n uiLocale?: GoalUiLocale;\n}): Promise<DecomposeChecklistResult> {\n const locale = goalUiLocaleOrFallback(opts.uiLocale);\n const goal = opts.goal.trim();\n if (!goal)\n return { items: [], parseFailed: false, errorReason: judgeReasonText('empty_goal', locale) };\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(opts.judgeModelRef);\n } catch {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('judge_model_not_configured', locale),\n };\n }\n\n const timeoutMs =\n typeof opts.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = opts.signal ? AbortSignal.any([opts.signal, controller.signal]) : controller.signal;\n\n try {\n const existingChecklist = opts.existingChecklist?.trim();\n const decomposeUser = DECOMPOSE_USER.replace('{goal}', truncateGoalText(goal, GOAL_TRUNC)) +\n (existingChecklist\n ? `\\n\\nExisting acceptance criteria:\\n${truncateGoalText(existingChecklist, GOAL_TRUNC)}\\n\\nReturn only missing supplemental criteria as JSON.`\n : '');\n const user: UserMessage = {\n role: 'user',\n content:\n `${DECOMPOSE_SYSTEM}\\n\\n${decomposeUser}` +\n judgeResponseLanguageNote(locale),\n timestamp: Date.now(),\n };\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await complete(\n model,\n { messages: [user] },\n { apiKey, maxTokens: 2000, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('decompose_call_failed', locale),\n };\n }\n\n const text = extractAssistantText(result.content);\n const data = extractJsonObject(text);\n if (!data)\n return {\n items: [],\n parseFailed: true,\n errorReason: judgeReasonText('decompose_reply_not_json', locale),\n };\n const rawItems = data.items ?? data.checklist;\n if (!Array.isArray(rawItems))\n return {\n items: [],\n parseFailed: true,\n errorReason: judgeReasonText('missing_items_array', locale),\n };\n const items: { text: string }[] = [];\n for (const row of rawItems) {\n if (typeof row === 'string') {\n const t = row.trim();\n if (t) items.push({ text: t });\n } else if (row && typeof row === 'object' && !Array.isArray(row)) {\n const t = String((row as { text?: string }).text ?? '').trim();\n if (t) items.push({ text: t });\n }\n }\n if (!items.length)\n return { items: [], parseFailed: true, errorReason: judgeReasonText('empty_checklist', locale) };\n return { items, parseFailed: false };\n } catch {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('decompose_call_failed', locale),\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport type ChecklistJudgeUpdate = {\n index: number;\n status: 'completed' | 'impossible';\n evidence?: string | null;\n};\n\nexport type ChecklistEvaluateParsed = {\n verdict: 'continue' | 'done' | 'blocked' | 'needs_input';\n confidence: number;\n updates: ChecklistJudgeUpdate[];\n newItems: { text: string }[];\n reason: string;\n nextAction?: string;\n missingEvidence?: string[];\n userQuestion?: string;\n};\n\nexport type EvaluateChecklistResult = {\n parsed: ChecklistEvaluateParsed;\n parseFailed: boolean;\n};\n\nexport async function evaluateGoalChecklistJudge(opts: {\n goal: string;\n numberedChecklist: string;\n lastResponse: string;\n historyExcerpt: string;\n goalContextExcerpt?: string;\n judgeModelRef: string;\n signal?: AbortSignal;\n judgeTimeoutMs?: number;\n uiLocale?: GoalUiLocale;\n}): Promise<EvaluateChecklistResult> {\n const locale = goalUiLocaleOrFallback(opts.uiLocale);\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(opts.judgeModelRef);\n } catch {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_model_not_configured', locale),\n },\n parseFailed: false,\n };\n }\n\n const userBody =\n `Goal:\\n${truncateGoalText(opts.goal, 2000)}\\n\\n` +\n `Current checklist (1-based indices):\\n${opts.numberedChecklist}\\n\\n` +\n `Original goal context and attachments:\\n${truncateGoalText(opts.goalContextExcerpt ?? '', 4000) || '(none)'}\\n\\n` +\n `Agent's most recent response (snippet):\\n${truncateGoalText(opts.lastResponse, RESPONSE_SNIPPET)}\\n\\n` +\n `Recent conversation excerpt (JSON or text, may be truncated):\\n` +\n `${truncateGoalText(opts.historyExcerpt, HISTORY_TRUNC) || '(none)'}`;\n\n const timeoutMs =\n typeof opts.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = opts.signal ? AbortSignal.any([opts.signal, controller.signal]) : controller.signal;\n\n try {\n const user: UserMessage = {\n role: 'user',\n content: `${EVALUATE_CHECKLIST_SYSTEM}\\n\\n${userBody}` + judgeResponseLanguageNote(locale),\n timestamp: Date.now(),\n };\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await complete(\n model,\n { messages: [user] },\n { apiKey, maxTokens: 1500, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_call_failed', locale),\n },\n parseFailed: false,\n };\n }\n\n const text = extractAssistantText(result.content);\n const data = extractJsonObject(text);\n if (!data) {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_reply_not_json', locale),\n },\n parseFailed: true,\n };\n }\n const updatesRaw = data.updates;\n const newRaw = data.new_items ?? data.newItems;\n const verdictRaw = String(data.verdict ?? '').trim().toLowerCase();\n const verdict =\n verdictRaw === 'done' || verdictRaw === 'blocked' || verdictRaw === 'needs_input'\n ? verdictRaw\n : 'continue';\n const confidenceRaw = Number(data.confidence);\n const confidence = Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : 0;\n const nextAction = typeof data.nextAction === 'string' ? data.nextAction.trim() : undefined;\n const userQuestion = typeof data.userQuestion === 'string' ? data.userQuestion.trim() : undefined;\n const missingEvidenceRaw = data.missingEvidence ?? data.missing_evidence;\n const trimmed = typeof data.reason === 'string' ? data.reason.trim() : '';\n const inner = trimmed || JUDGE_REASON_EN.no_reason_provided;\n const reason = localizeJudgeReasonText(inner, locale);\n const updates: ChecklistJudgeUpdate[] = [];\n if (Array.isArray(updatesRaw)) {\n for (const u of updatesRaw) {\n if (!u || typeof u !== 'object' || Array.isArray(u)) continue;\n const rec = u as Record<string, unknown>;\n const idx1 = Number(rec.index);\n if (!Number.isFinite(idx1)) continue;\n const idx0 = Math.floor(idx1) - 1;\n const st = String(rec.status ?? '').trim().toLowerCase();\n if (st !== 'completed' && st !== 'impossible') continue;\n const evidence = typeof rec.evidence === 'string' ? rec.evidence : null;\n updates.push({ index: idx0, status: st, evidence });\n }\n }\n const newItems: { text: string }[] = [];\n if (Array.isArray(newRaw)) {\n for (const row of newRaw) {\n if (typeof row === 'string') {\n const t = row.trim();\n if (t) newItems.push({ text: t });\n } else if (row && typeof row === 'object' && !Array.isArray(row)) {\n const t = String((row as { text?: string }).text ?? '').trim();\n if (t) newItems.push({ text: t });\n }\n }\n }\n const missingEvidence: string[] = [];\n if (Array.isArray(missingEvidenceRaw)) {\n for (const item of missingEvidenceRaw) {\n if (typeof item === 'string' && item.trim()) missingEvidence.push(item.trim());\n }\n }\n return {\n parsed: {\n verdict,\n confidence,\n updates,\n newItems,\n reason: reason || judgeReasonText('no_reason_provided', locale),\n ...(nextAction ? { nextAction } : {}),\n ...(missingEvidence.length ? { missingEvidence } : {}),\n ...(userQuestion ? { userQuestion } : {}),\n },\n parseFailed: false,\n };\n } catch {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_call_failed', locale),\n },\n parseFailed: false,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":";;;;;;gBAGwD;AAmBxD,MAAM,aAAa;AACnB,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AAEtB,MAAM,mBACJ;AASF,MAAM,iBAAiB;AAEvB,MAAM,4BACJ;AAaF,SAAS,kBAAkB,KAA6C;AACtE,KAAI,CAAC,KAAK,MAAM,CAAE,QAAO;CACzB,MAAM,OAAO,gBAAgB,IAAI;AACjC,KAAI;EACF,MAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,SAAO,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAI,OAAmC;SAChG;EACN,MAAM,QAAQ,KAAK,QAAQ,IAAI;EAC/B,MAAM,MAAM,KAAK,YAAY,IAAI;AACjC,MAAI,UAAU,MAAM,OAAO,MAAO,QAAO;AACzC,MAAI;GACF,MAAM,OAAO,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,EAAE,CAAC;AACnD,UAAO,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAI,OAAmC;UAChG;AACN,UAAO;;;;AAWb,eAAsB,uBAAuB,MAOP;CACpC,MAAM,SAAS,uBAAuB,KAAK,SAAS;CACpD,MAAM,OAAO,KAAK,KAAK,MAAM;AAC7B,KAAI,CAAC,KACH,QAAO;EAAE,OAAO,EAAE;EAAE,aAAa;EAAO,aAAa,gBAAgB,cAAc,OAAO;EAAE;CAE9F,IAAI;AACJ,KAAI;AACF,UAAQ,aAAa,KAAK,cAAc;SAClC;AACN,SAAO;GACL,OAAO,EAAE;GACT,aAAa;GACb,aAAa,gBAAgB,8BAA8B,OAAO;GACnE;;CAGH,MAAM,YACJ,OAAO,KAAK,mBAAmB,YAAY,OAAO,SAAS,KAAK,eAAe,GAC3E,KAAK,IAAI,KAAO,KAAK,IAAI,MAAS,KAAK,MAAM,KAAK,eAAe,CAAC,CAAC,GACnE;CACN,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,UAAU;CAC7D,MAAM,SAAS,KAAK,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,WAAW,OAAO,CAAC,GAAG,WAAW;AAE5F,KAAI;EACF,MAAM,oBAAoB,KAAK,mBAAmB,MAAM;EAKxD,MAAM,OAAoB;GACxB,MAAM;GACN,SACE,GAAG,iBAAiB,MAPF,eAAe,QAAQ,UAAU,iBAAiB,MAAM,WAAW,CAAC,IACvF,oBACG,sCAAsC,iBAAiB,mBAAmB,WAAW,CAAC,0DACtF,QAKF,0BAA0B,OAAO;GACnC,WAAW,KAAK,KAAK;GACtB;EACD,MAAM,SAAS,MAAM,uBAAuB,MAAM;EAClD,MAAM,SAAS,MAAM,SACnB,OACA,EAAE,UAAU,CAAC,KAAK,EAAE,EACpB;GAAE;GAAQ,WAAW;GAAM,aAAa;GAAG,QAAQ;GAAQ,CAC5D;AAED,MADoB,+BAA+B,OACpC,CACb,QAAO;GACL,OAAO,EAAE;GACT,aAAa;GACb,aAAa,gBAAgB,yBAAyB,OAAO;GAC9D;EAIH,MAAM,OAAO,kBADA,qBAAqB,OAAO,QACN,CAAC;AACpC,MAAI,CAAC,KACH,QAAO;GACL,OAAO,EAAE;GACT,aAAa;GACb,aAAa,gBAAgB,4BAA4B,OAAO;GACjE;EACH,MAAM,WAAW,KAAK,SAAS,KAAK;AACpC,MAAI,CAAC,MAAM,QAAQ,SAAS,CAC1B,QAAO;GACL,OAAO,EAAE;GACT,aAAa;GACb,aAAa,gBAAgB,uBAAuB,OAAO;GAC5D;EACH,MAAM,QAA4B,EAAE;AACpC,OAAK,MAAM,OAAO,SAChB,KAAI,OAAO,QAAQ,UAAU;GAC3B,MAAM,IAAI,IAAI,MAAM;AACpB,OAAI,EAAG,OAAM,KAAK,EAAE,MAAM,GAAG,CAAC;aACrB,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,IAAI,EAAE;GAChE,MAAM,IAAI,OAAQ,IAA0B,QAAQ,GAAG,CAAC,MAAM;AAC9D,OAAI,EAAG,OAAM,KAAK,EAAE,MAAM,GAAG,CAAC;;AAGlC,MAAI,CAAC,MAAM,OACT,QAAO;GAAE,OAAO,EAAE;GAAE,aAAa;GAAM,aAAa,gBAAgB,mBAAmB,OAAO;GAAE;AAClG,SAAO;GAAE;GAAO,aAAa;GAAO;SAC9B;AACN,SAAO;GACL,OAAO,EAAE;GACT,aAAa;GACb,aAAa,gBAAgB,yBAAyB,OAAO;GAC9D;WACO;AACR,eAAa,MAAM;;;AA0BvB,eAAsB,2BAA2B,MAUZ;CACnC,MAAM,SAAS,uBAAuB,KAAK,SAAS;CACpD,IAAI;AACJ,KAAI;AACF,UAAQ,aAAa,KAAK,cAAc;SAClC;AACN,SAAO;GACL,QAAQ;IACN,SAAS;IACT,YAAY;IACZ,SAAS,EAAE;IACX,UAAU,EAAE;IACZ,QAAQ,gBAAgB,8BAA8B,OAAO;IAC9D;GACD,aAAa;GACd;;CAGH,MAAM,WACJ,UAAU,iBAAiB,KAAK,MAAM,IAAK,CAAC,4CACH,KAAK,kBAAkB,8CACrB,iBAAiB,KAAK,sBAAsB,IAAI,IAAK,IAAI,SAAS,+CACjE,iBAAiB,KAAK,cAAc,iBAAiB,CAAC,qEAE/F,iBAAiB,KAAK,gBAAgB,cAAc,IAAI;CAE7D,MAAM,YACJ,OAAO,KAAK,mBAAmB,YAAY,OAAO,SAAS,KAAK,eAAe,GAC3E,KAAK,IAAI,KAAO,KAAK,IAAI,MAAS,KAAK,MAAM,KAAK,eAAe,CAAC,CAAC,GACnE;CACN,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,UAAU;CAC7D,MAAM,SAAS,KAAK,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,WAAW,OAAO,CAAC,GAAG,WAAW;AAE5F,KAAI;EACF,MAAM,OAAoB;GACxB,MAAM;GACN,SAAS,GAAG,0BAA0B,MAAM,aAAa,0BAA0B,OAAO;GAC1F,WAAW,KAAK,KAAK;GACtB;EACD,MAAM,SAAS,MAAM,uBAAuB,MAAM;EAClD,MAAM,SAAS,MAAM,SACnB,OACA,EAAE,UAAU,CAAC,KAAK,EAAE,EACpB;GAAE;GAAQ,WAAW;GAAM,aAAa;GAAG,QAAQ;GAAQ,CAC5D;AAED,MADoB,+BAA+B,OACpC,CACb,QAAO;GACL,QAAQ;IACN,SAAS;IACT,YAAY;IACZ,SAAS,EAAE;IACX,UAAU,EAAE;IACZ,QAAQ,gBAAgB,qBAAqB,OAAO;IACrD;GACD,aAAa;GACd;EAIH,MAAM,OAAO,kBADA,qBAAqB,OAAO,QACN,CAAC;AACpC,MAAI,CAAC,KACH,QAAO;GACL,QAAQ;IACN,SAAS;IACT,YAAY;IACZ,SAAS,EAAE;IACX,UAAU,EAAE;IACZ,QAAQ,gBAAgB,wBAAwB,OAAO;IACxD;GACD,aAAa;GACd;EAEH,MAAM,aAAa,KAAK;EACxB,MAAM,SAAS,KAAK,aAAa,KAAK;EACtC,MAAM,aAAa,OAAO,KAAK,WAAW,GAAG,CAAC,MAAM,CAAC,aAAa;EAClE,MAAM,UACJ,eAAe,UAAU,eAAe,aAAa,eAAe,gBAChE,aACA;EACN,MAAM,gBAAgB,OAAO,KAAK,WAAW;EAC7C,MAAM,aAAa,OAAO,SAAS,cAAc,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,cAAc,CAAC,GAAG;EAC9F,MAAM,aAAa,OAAO,KAAK,eAAe,WAAW,KAAK,WAAW,MAAM,GAAG,KAAA;EAClF,MAAM,eAAe,OAAO,KAAK,iBAAiB,WAAW,KAAK,aAAa,MAAM,GAAG,KAAA;EACxF,MAAM,qBAAqB,KAAK,mBAAmB,KAAK;EAGxD,MAAM,SAAS,yBAFC,OAAO,KAAK,WAAW,WAAW,KAAK,OAAO,MAAM,GAAG,OAC9C,gBAAgB,oBACK,OAAO;EACrD,MAAM,UAAkC,EAAE;AAC1C,MAAI,MAAM,QAAQ,WAAW,CAC3B,MAAK,MAAM,KAAK,YAAY;AAC1B,OAAI,CAAC,KAAK,OAAO,MAAM,YAAY,MAAM,QAAQ,EAAE,CAAE;GACrD,MAAM,MAAM;GACZ,MAAM,OAAO,OAAO,IAAI,MAAM;AAC9B,OAAI,CAAC,OAAO,SAAS,KAAK,CAAE;GAC5B,MAAM,OAAO,KAAK,MAAM,KAAK,GAAG;GAChC,MAAM,KAAK,OAAO,IAAI,UAAU,GAAG,CAAC,MAAM,CAAC,aAAa;AACxD,OAAI,OAAO,eAAe,OAAO,aAAc;GAC/C,MAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AACnE,WAAQ,KAAK;IAAE,OAAO;IAAM,QAAQ;IAAI;IAAU,CAAC;;EAGvD,MAAM,WAA+B,EAAE;AACvC,MAAI,MAAM,QAAQ,OAAO;QAClB,MAAM,OAAO,OAChB,KAAI,OAAO,QAAQ,UAAU;IAC3B,MAAM,IAAI,IAAI,MAAM;AACpB,QAAI,EAAG,UAAS,KAAK,EAAE,MAAM,GAAG,CAAC;cACxB,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,IAAI,EAAE;IAChE,MAAM,IAAI,OAAQ,IAA0B,QAAQ,GAAG,CAAC,MAAM;AAC9D,QAAI,EAAG,UAAS,KAAK,EAAE,MAAM,GAAG,CAAC;;;EAIvC,MAAM,kBAA4B,EAAE;AACpC,MAAI,MAAM,QAAQ,mBAAmB;QAC9B,MAAM,QAAQ,mBACjB,KAAI,OAAO,SAAS,YAAY,KAAK,MAAM,CAAE,iBAAgB,KAAK,KAAK,MAAM,CAAC;;AAGlF,SAAO;GACL,QAAQ;IACN;IACA;IACA;IACA;IACA,QAAQ,UAAU,gBAAgB,sBAAsB,OAAO;IAC/D,GAAI,aAAa,EAAE,YAAY,GAAG,EAAE;IACpC,GAAI,gBAAgB,SAAS,EAAE,iBAAiB,GAAG,EAAE;IACrD,GAAI,eAAe,EAAE,cAAc,GAAG,EAAE;IACzC;GACD,aAAa;GACd;SACK;AACN,SAAO;GACL,QAAQ;IACN,SAAS;IACT,YAAY;IACZ,SAAS,EAAE;IACX,UAAU,EAAE;IACZ,QAAQ,gBAAgB,qBAAqB,OAAO;IACrD;GACD,aAAa;GACd;WACO;AACR,eAAa,MAAM"}
1
+ {"version":3,"file":"checklist-judge.js","names":[],"sources":["../../../../src/agent/goals/checklist-judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\n\nimport { resolveModel } from '../../providers/index.js';\nimport { completeWithResolvedCredentials } from '../../providers/model-call.js';\n\nimport {\n DEFAULT_JUDGE_TIMEOUT_MS,\n extractAssistantText,\n getAssistantMessageErrorReason,\n resolveGoalJudgeApiKey,\n stripCodeFences,\n truncateGoalText,\n} from './judge.js';\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeReasonText,\n judgeResponseLanguageNote,\n JUDGE_REASON_EN,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst GOAL_TRUNC = 4000;\nconst RESPONSE_SNIPPET = 4000;\nconst HISTORY_TRUNC = 24_000;\n\nconst DECOMPOSE_SYSTEM = (\n 'You break a user goal into an EXTREMELY detailed checklist of concrete, verifiable completion criteria. ' +\n 'Bias toward more items. Each item is one factual statement about finished work.\\n\\n' +\n 'If existing acceptance criteria are provided, return only missing supplemental criteria. ' +\n 'Do not repeat, rewrite, or replace existing criteria.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"items\":[{\"text\":\"...\"},...]}\\n' +\n 'Use at least 3 items when the goal warrants it.'\n);\n\nconst DECOMPOSE_USER = 'Goal:\\n{goal}\\n\\nReturn JSON only.';\n\nconst EVALUATE_CHECKLIST_SYSTEM = (\n 'You evaluate an autonomous agent\\'s progress on a goal with a numbered checklist.\\n' +\n 'For each pending item, decide if evidence in the agent snippet and/or history excerpt shows it is satisfied.\\n' +\n 'Flip pending→completed only with clear evidence; pending→impossible only if truly unachievable here.\\n' +\n 'Do not regress completed/impossible items — omit them from updates.\\n\\n' +\n 'Reply ONLY with one JSON object on one line:\\n' +\n '{\"verdict\":\"continue|done|blocked|needs_input\",\"confidence\":0.0,\"reason\":\"...\",' +\n '\"nextAction\":\"...\",\"missingEvidence\":[\"...\"],\"userQuestion\":\"...\",' +\n '\"updates\":[{\"index\":1,\"status\":\"completed|impossible\",\"evidence\":\"short citation\"}],' +\n '\"new_items\":[{\"text\":\"...\"}]}\\n' +\n 'Use verdict=done only when all checklist criteria are complete/impossible. ' +\n 'Use needs_input when the next step requires user input. Use blocked when external progress is impossible.'\n);\n\nfunction extractJsonObject(raw: string): Record<string, unknown> | null {\n if (!raw?.trim()) return null;\n const text = stripCodeFences(raw);\n try {\n const data = JSON.parse(text) as unknown;\n return data && typeof data === 'object' && !Array.isArray(data) ? (data as Record<string, unknown>) : null;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n try {\n const data = JSON.parse(text.slice(start, end + 1)) as unknown;\n return data && typeof data === 'object' && !Array.isArray(data) ? (data as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n }\n}\n\nexport type DecomposeChecklistResult = {\n items: { text: string }[];\n parseFailed: boolean;\n errorReason?: string;\n};\n\nexport async function decomposeGoalChecklist(opts: {\n goal: string;\n existingChecklist?: string;\n judgeModelRef: string;\n signal?: AbortSignal;\n judgeTimeoutMs?: number;\n uiLocale?: GoalUiLocale;\n}): Promise<DecomposeChecklistResult> {\n const locale = goalUiLocaleOrFallback(opts.uiLocale);\n const goal = opts.goal.trim();\n if (!goal)\n return { items: [], parseFailed: false, errorReason: judgeReasonText('empty_goal', locale) };\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(opts.judgeModelRef);\n } catch {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('judge_model_not_configured', locale),\n };\n }\n\n const timeoutMs =\n typeof opts.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = opts.signal ? AbortSignal.any([opts.signal, controller.signal]) : controller.signal;\n\n try {\n const existingChecklist = opts.existingChecklist?.trim();\n const decomposeUser = DECOMPOSE_USER.replace('{goal}', truncateGoalText(goal, GOAL_TRUNC)) +\n (existingChecklist\n ? `\\n\\nExisting acceptance criteria:\\n${truncateGoalText(existingChecklist, GOAL_TRUNC)}\\n\\nReturn only missing supplemental criteria as JSON.`\n : '');\n const user: UserMessage = {\n role: 'user',\n content:\n `${DECOMPOSE_SYSTEM}\\n\\n${decomposeUser}` +\n judgeResponseLanguageNote(locale),\n timestamp: Date.now(),\n };\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await completeWithResolvedCredentials(\n model,\n { messages: [user] },\n { apiKey, maxTokens: 2000, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('decompose_call_failed', locale),\n };\n }\n\n const text = extractAssistantText(result.content);\n const data = extractJsonObject(text);\n if (!data)\n return {\n items: [],\n parseFailed: true,\n errorReason: judgeReasonText('decompose_reply_not_json', locale),\n };\n const rawItems = data.items ?? data.checklist;\n if (!Array.isArray(rawItems))\n return {\n items: [],\n parseFailed: true,\n errorReason: judgeReasonText('missing_items_array', locale),\n };\n const items: { text: string }[] = [];\n for (const row of rawItems) {\n if (typeof row === 'string') {\n const t = row.trim();\n if (t) items.push({ text: t });\n } else if (row && typeof row === 'object' && !Array.isArray(row)) {\n const t = String((row as { text?: string }).text ?? '').trim();\n if (t) items.push({ text: t });\n }\n }\n if (!items.length)\n return { items: [], parseFailed: true, errorReason: judgeReasonText('empty_checklist', locale) };\n return { items, parseFailed: false };\n } catch {\n return {\n items: [],\n parseFailed: false,\n errorReason: judgeReasonText('decompose_call_failed', locale),\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport type ChecklistJudgeUpdate = {\n index: number;\n status: 'completed' | 'impossible';\n evidence?: string | null;\n};\n\nexport type ChecklistEvaluateParsed = {\n verdict: 'continue' | 'done' | 'blocked' | 'needs_input';\n confidence: number;\n updates: ChecklistJudgeUpdate[];\n newItems: { text: string }[];\n reason: string;\n nextAction?: string;\n missingEvidence?: string[];\n userQuestion?: string;\n};\n\nexport type EvaluateChecklistResult = {\n parsed: ChecklistEvaluateParsed;\n parseFailed: boolean;\n};\n\nexport async function evaluateGoalChecklistJudge(opts: {\n goal: string;\n numberedChecklist: string;\n lastResponse: string;\n historyExcerpt: string;\n goalContextExcerpt?: string;\n judgeModelRef: string;\n signal?: AbortSignal;\n judgeTimeoutMs?: number;\n uiLocale?: GoalUiLocale;\n}): Promise<EvaluateChecklistResult> {\n const locale = goalUiLocaleOrFallback(opts.uiLocale);\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(opts.judgeModelRef);\n } catch {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_model_not_configured', locale),\n },\n parseFailed: false,\n };\n }\n\n const userBody =\n `Goal:\\n${truncateGoalText(opts.goal, 2000)}\\n\\n` +\n `Current checklist (1-based indices):\\n${opts.numberedChecklist}\\n\\n` +\n `Original goal context and attachments:\\n${truncateGoalText(opts.goalContextExcerpt ?? '', 4000) || '(none)'}\\n\\n` +\n `Agent's most recent response (snippet):\\n${truncateGoalText(opts.lastResponse, RESPONSE_SNIPPET)}\\n\\n` +\n `Recent conversation excerpt (JSON or text, may be truncated):\\n` +\n `${truncateGoalText(opts.historyExcerpt, HISTORY_TRUNC) || '(none)'}`;\n\n const timeoutMs =\n typeof opts.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = opts.signal ? AbortSignal.any([opts.signal, controller.signal]) : controller.signal;\n\n try {\n const user: UserMessage = {\n role: 'user',\n content: `${EVALUATE_CHECKLIST_SYSTEM}\\n\\n${userBody}` + judgeResponseLanguageNote(locale),\n timestamp: Date.now(),\n };\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await completeWithResolvedCredentials(\n model,\n { messages: [user] },\n { apiKey, maxTokens: 1500, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_call_failed', locale),\n },\n parseFailed: false,\n };\n }\n\n const text = extractAssistantText(result.content);\n const data = extractJsonObject(text);\n if (!data) {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_reply_not_json', locale),\n },\n parseFailed: true,\n };\n }\n const updatesRaw = data.updates;\n const newRaw = data.new_items ?? data.newItems;\n const verdictRaw = String(data.verdict ?? '').trim().toLowerCase();\n const verdict =\n verdictRaw === 'done' || verdictRaw === 'blocked' || verdictRaw === 'needs_input'\n ? verdictRaw\n : 'continue';\n const confidenceRaw = Number(data.confidence);\n const confidence = Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : 0;\n const nextAction = typeof data.nextAction === 'string' ? data.nextAction.trim() : undefined;\n const userQuestion = typeof data.userQuestion === 'string' ? data.userQuestion.trim() : undefined;\n const missingEvidenceRaw = data.missingEvidence ?? data.missing_evidence;\n const trimmed = typeof data.reason === 'string' ? data.reason.trim() : '';\n const inner = trimmed || JUDGE_REASON_EN.no_reason_provided;\n const reason = localizeJudgeReasonText(inner, locale);\n const updates: ChecklistJudgeUpdate[] = [];\n if (Array.isArray(updatesRaw)) {\n for (const u of updatesRaw) {\n if (!u || typeof u !== 'object' || Array.isArray(u)) continue;\n const rec = u as Record<string, unknown>;\n const idx1 = Number(rec.index);\n if (!Number.isFinite(idx1)) continue;\n const idx0 = Math.floor(idx1) - 1;\n const st = String(rec.status ?? '').trim().toLowerCase();\n if (st !== 'completed' && st !== 'impossible') continue;\n const evidence = typeof rec.evidence === 'string' ? rec.evidence : null;\n updates.push({ index: idx0, status: st, evidence });\n }\n }\n const newItems: { text: string }[] = [];\n if (Array.isArray(newRaw)) {\n for (const row of newRaw) {\n if (typeof row === 'string') {\n const t = row.trim();\n if (t) newItems.push({ text: t });\n } else if (row && typeof row === 'object' && !Array.isArray(row)) {\n const t = String((row as { text?: string }).text ?? '').trim();\n if (t) newItems.push({ text: t });\n }\n }\n }\n const missingEvidence: string[] = [];\n if (Array.isArray(missingEvidenceRaw)) {\n for (const item of missingEvidenceRaw) {\n if (typeof item === 'string' && item.trim()) missingEvidence.push(item.trim());\n }\n }\n return {\n parsed: {\n verdict,\n confidence,\n updates,\n newItems,\n reason: reason || judgeReasonText('no_reason_provided', locale),\n ...(nextAction ? { nextAction } : {}),\n ...(missingEvidence.length ? { missingEvidence } : {}),\n ...(userQuestion ? { userQuestion } : {}),\n },\n parseFailed: false,\n };\n } catch {\n return {\n parsed: {\n verdict: 'continue',\n confidence: 0,\n updates: [],\n newItems: [],\n reason: judgeReasonText('judge_call_failed', locale),\n },\n parseFailed: false,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { getApiKey, init_providers, resolveModel } from "../../providers/index.js";
2
+ import { completeWithResolvedCredentials } from "../../providers/model-call.js";
2
3
  import { JUDGE_REASON_EN } from "../../i18n/goals-bundle.js";
3
4
  import { goalUiLocaleOrFallback, judgeFreeformBuiltinMessages, judgeResponseLanguageNote, localizeJudgeReasonText } from "./goal-locale.js";
4
- import { complete } from "@earendil-works/pi-ai/compat";
5
5
  //#region src/agent/goals/judge.ts
6
6
  init_providers();
7
7
  const JUDGE_RESPONSE_SNIPPET_CHARS = 4e3;
@@ -144,7 +144,7 @@ async function judgeGoalHermesStyle(goal, lastResponse, judgeModelRef, signal, o
144
144
  timestamp: Date.now()
145
145
  };
146
146
  const apiKey = await resolveGoalJudgeApiKey(model);
147
- const result = await complete(model, { messages: [combinedUser] }, {
147
+ const result = await completeWithResolvedCredentials(model, { messages: [combinedUser] }, {
148
148
  apiKey,
149
149
  maxTokens: 200,
150
150
  temperature: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"judge.js","names":[],"sources":["../../../../src/agent/goals/judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\nimport { complete } from '@earendil-works/pi-ai/compat';\n\nimport { getApiKey, resolveModel } from '../../providers/index.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeFreeformBuiltinMessages,\n JUDGE_REASON_EN,\n judgeResponseLanguageNote,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst JUDGE_RESPONSE_SNIPPET_CHARS = 4000;\n\n/**\n * Extract visible text from a pi-ai `AssistantMessage.content` array.\n * Handles `TextContent` (`type: 'text'`) and falls back to `ThinkingContent`\n * (`type: 'thinking'`) when the text blocks are empty — reasoning models\n * (DeepSeek-R1, Qwen-thinking, etc.) may place the entire response inside\n * thinking blocks, leaving the text portion blank.\n */\nexport function extractAssistantText(content: unknown): string {\n if (!Array.isArray(content)) return '';\n\n let textParts = '';\n let thinkingParts = '';\n\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const typed = block as Record<string, unknown>;\n const blockType = typed.type;\n if (blockType === 'text' && typeof typed.text === 'string') {\n textParts += typed.text;\n } else if (blockType === 'thinking') {\n const thinking =\n typeof typed.thinking === 'string'\n ? typed.thinking\n : typeof typed.text === 'string'\n ? typed.text\n : '';\n thinkingParts += thinking;\n }\n }\n\n // Prefer text blocks; fall back to thinking blocks when text is empty.\n return textParts.trim() ? textParts : thinkingParts;\n}\n\n/**\n * Strip markdown code fences (opening AND closing) from raw model output.\n * Handles `` ```json ``, `` ``` ``, and trailing `` ``` `` with optional whitespace.\n */\nexport function stripCodeFences(raw: string): string {\n let text = raw.trim();\n\n // Remove opening code fence: ```<optional-lang>\\n\n const openMatch = text.match(/^`{3,}[^\\n]*\\n?/);\n if (openMatch) {\n text = text.slice(openMatch[0].length);\n }\n\n // Remove closing code fence: \\n```<optional-whitespace>\n const closeMatch = text.match(/\\n?`{3,}\\s*$/);\n if (closeMatch) {\n text = text.slice(0, -closeMatch[0].length);\n }\n\n return text.trim();\n}\n\n/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */\nexport const JUDGE_SYSTEM_PROMPT =\n 'You are a strict judge evaluating whether an autonomous agent has ' +\n \"achieved a user's stated goal. You receive the goal text and the \" +\n \"agent's most recent response. Your only job is to decide whether \" +\n 'the goal is fully satisfied based on that response.\\n\\n' +\n 'A goal is DONE only when:\\n' +\n '- The response explicitly confirms the goal was completed, OR\\n' +\n '- The response clearly shows the final deliverable was produced, OR\\n' +\n '- The response explains the goal is unachievable / blocked / needs ' +\n 'user input (treat this as DONE with reason describing the block).\\n\\n' +\n 'Otherwise the goal is NOT done — CONTINUE.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"done\": <true|false>, \"reason\": \"<one-sentence rationale>\"}';\n\nexport const JUDGE_USER_PROMPT_TEMPLATE =\n 'Goal:\\n{goal}\\n\\n' + \"Agent's most recent response:\\n{response}\\n\\n\" + 'Is the goal satisfied?';\n\nexport const DEFAULT_JUDGE_TIMEOUT_MS = 60_000;\n\nexport function truncateGoalText(text: string, limit: number): string {\n if (!text) return '';\n if (text.length <= limit) return text;\n return text.slice(0, limit) + '… [truncated]';\n}\n\nexport async function resolveGoalJudgeApiKey(\n model: ReturnType<typeof resolveModel>,\n): Promise<string | undefined> {\n try {\n return await getApiKey(model.provider);\n } catch {\n return undefined;\n }\n}\n\nexport function getAssistantMessageErrorReason(message: unknown): string | null {\n if (!message || typeof message !== 'object') return null;\n\n const record = message as Record<string, unknown>;\n const stopReason = record.stopReason;\n const errorMessage = typeof record.errorMessage === 'string' ? record.errorMessage.trim() : '';\n\n if (stopReason === 'error') {\n return errorMessage || 'Judge model call failed.';\n }\n\n return null;\n}\n\n/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */\nexport function parseJudgeResponseFailOpen(raw: string): {\n done: boolean;\n reason: string;\n parseFailed: boolean;\n} {\n if (!raw?.trim()) {\n return { done: false, reason: JUDGE_REASON_EN.judge_returned_empty, parseFailed: true };\n }\n\n const text = stripCodeFences(raw);\n\n let data: Record<string, unknown> | null = null;\n try {\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start !== -1 && end > start) {\n try {\n data = JSON.parse(text.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n data = null;\n }\n }\n }\n\n if (!data || typeof data !== 'object') {\n return { done: false, reason: JUDGE_REASON_EN.judge_reply_not_json, parseFailed: true };\n }\n\n const doneVal = data.done;\n let done: boolean;\n if (typeof doneVal === 'string') {\n done = ['true', 'yes', '1', 'done'].includes(doneVal.trim().toLowerCase());\n } else {\n done = Boolean(doneVal);\n }\n const reason = typeof data.reason === 'string' ? data.reason.trim() : '';\n return { done, reason: reason || JUDGE_REASON_EN.no_reason_provided, parseFailed: false };\n}\n\nexport type GoalJudgeVerdict = 'done' | 'continue' | 'skipped';\n\n/**\n * Ask the configured model whether the goal is satisfied.\n * Fail-open: any error → `continue` (Hermes — turn budget is the backstop).\n */\nexport async function judgeGoalHermesStyle(\n goal: string,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { judgeTimeoutMs?: number; uiLocale?: GoalUiLocale },\n): Promise<{ verdict: GoalJudgeVerdict; reason: string; parseFailed: boolean }> {\n const locale = goalUiLocaleOrFallback(opts?.uiLocale);\n const b = judgeFreeformBuiltinMessages(locale);\n\n if (!goal.trim()) {\n return { verdict: 'skipped', reason: b.emptyGoal, parseFailed: false };\n }\n if (!lastResponse.trim()) {\n return { verdict: 'continue', reason: b.emptyResponse, parseFailed: false };\n }\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(judgeModelRef);\n } catch {\n return { verdict: 'continue', reason: b.noModel, parseFailed: false };\n }\n\n const userContent =\n JUDGE_USER_PROMPT_TEMPLATE.replace('{goal}', truncateGoalText(goal, 2000)).replace(\n '{response}',\n truncateGoalText(lastResponse, JUDGE_RESPONSE_SNIPPET_CHARS),\n ) + judgeResponseLanguageNote(locale);\n\n const timeoutMs =\n typeof opts?.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;\n\n try {\n const combinedUser: UserMessage = {\n role: 'user',\n content: `${JUDGE_SYSTEM_PROMPT}\\n\\n${userContent}`,\n timestamp: Date.now(),\n };\n\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await complete(\n model,\n {\n messages: [combinedUser],\n },\n { apiKey, maxTokens: 200, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n }\n\n const text = extractAssistantText(result.content);\n const { done, reason, parseFailed } = parseJudgeResponseFailOpen(text);\n const reasonOut = localizeJudgeReasonText(reason, locale);\n return { verdict: done ? 'done' : 'continue', reason: reasonOut, parseFailed };\n } catch {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":";;;;;gBAGmE;AAWnE,MAAM,+BAA+B;;;;;;;;AASrC,SAAgB,qBAAqB,SAA0B;AAC7D,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;CAEpC,IAAI,YAAY;CAChB,IAAI,gBAAgB;AAEpB,MAAK,MAAM,SAAS,SAAS;AAC3B,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU;EACzC,MAAM,QAAQ;EACd,MAAM,YAAY,MAAM;AACxB,MAAI,cAAc,UAAU,OAAO,MAAM,SAAS,SAChD,cAAa,MAAM;WACV,cAAc,YAAY;GACnC,MAAM,WACJ,OAAO,MAAM,aAAa,WACtB,MAAM,WACN,OAAO,MAAM,SAAS,WACpB,MAAM,OACN;AACR,oBAAiB;;;AAKrB,QAAO,UAAU,MAAM,GAAG,YAAY;;;;;;AAOxC,SAAgB,gBAAgB,KAAqB;CACnD,IAAI,OAAO,IAAI,MAAM;CAGrB,MAAM,YAAY,KAAK,MAAM,kBAAkB;AAC/C,KAAI,UACF,QAAO,KAAK,MAAM,UAAU,GAAG,OAAO;CAIxC,MAAM,aAAa,KAAK,MAAM,eAAe;AAC7C,KAAI,WACF,QAAO,KAAK,MAAM,GAAG,CAAC,WAAW,GAAG,OAAO;AAG7C,QAAO,KAAK,MAAM;;;AAIpB,MAAa,sBACX;AAaF,MAAa,6BACX;AAEF,MAAa,2BAA2B;AAExC,SAAgB,iBAAiB,MAAc,OAAuB;AACpE,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,KAAK,UAAU,MAAO,QAAO;AACjC,QAAO,KAAK,MAAM,GAAG,MAAM,GAAG;;AAGhC,eAAsB,uBACpB,OAC6B;AAC7B,KAAI;AACF,SAAO,MAAM,UAAU,MAAM,SAAS;SAChC;AACN;;;AAIJ,SAAgB,+BAA+B,SAAiC;AAC9E,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;CAEpD,MAAM,SAAS;CACf,MAAM,aAAa,OAAO;CAC1B,MAAM,eAAe,OAAO,OAAO,iBAAiB,WAAW,OAAO,aAAa,MAAM,GAAG;AAE5F,KAAI,eAAe,QACjB,QAAO,gBAAgB;AAGzB,QAAO;;;AAIT,SAAgB,2BAA2B,KAIzC;AACA,KAAI,CAAC,KAAK,MAAM,CACd,QAAO;EAAE,MAAM;EAAO,QAAQ,gBAAgB;EAAsB,aAAa;EAAM;CAGzF,MAAM,OAAO,gBAAgB,IAAI;CAEjC,IAAI,OAAuC;AAC3C,KAAI;AACF,SAAO,KAAK,MAAM,KAAK;SACjB;EACN,MAAM,QAAQ,KAAK,QAAQ,IAAI;EAC/B,MAAM,MAAM,KAAK,YAAY,IAAI;AACjC,MAAI,UAAU,MAAM,MAAM,MACxB,KAAI;AACF,UAAO,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,EAAE,CAAC;UACvC;AACN,UAAO;;;AAKb,KAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,QAAO;EAAE,MAAM;EAAO,QAAQ,gBAAgB;EAAsB,aAAa;EAAM;CAGzF,MAAM,UAAU,KAAK;CACrB,IAAI;AACJ,KAAI,OAAO,YAAY,SACrB,QAAO;EAAC;EAAQ;EAAO;EAAK;EAAO,CAAC,SAAS,QAAQ,MAAM,CAAC,aAAa,CAAC;KAE1E,QAAO,QAAQ,QAAQ;CAEzB,MAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,OAAO,MAAM,GAAG;AACtE,QAAO;EAAE;EAAM,QAAQ,UAAU,gBAAgB;EAAoB,aAAa;EAAO;;;;;;AAS3F,eAAsB,qBACpB,MACA,cACA,eACA,QACA,MAC8E;CAC9E,MAAM,SAAS,uBAAuB,MAAM,SAAS;CACrD,MAAM,IAAI,6BAA6B,OAAO;AAE9C,KAAI,CAAC,KAAK,MAAM,CACd,QAAO;EAAE,SAAS;EAAW,QAAQ,EAAE;EAAW,aAAa;EAAO;AAExE,KAAI,CAAC,aAAa,MAAM,CACtB,QAAO;EAAE,SAAS;EAAY,QAAQ,EAAE;EAAe,aAAa;EAAO;CAG7E,IAAI;AACJ,KAAI;AACF,UAAQ,aAAa,cAAc;SAC7B;AACN,SAAO;GAAE,SAAS;GAAY,QAAQ,EAAE;GAAS,aAAa;GAAO;;CAGvE,MAAM,cACJ,2BAA2B,QAAQ,UAAU,iBAAiB,MAAM,IAAK,CAAC,CAAC,QACzE,cACA,iBAAiB,cAAc,6BAA6B,CAC7D,GAAG,0BAA0B,OAAO;CAEvC,MAAM,YACJ,OAAO,MAAM,mBAAmB,YAAY,OAAO,SAAS,KAAK,eAAe,GAC5E,KAAK,IAAI,KAAO,KAAK,IAAI,MAAS,KAAK,MAAM,KAAK,eAAe,CAAC,CAAC,GACnE;CACN,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,UAAU;CAC7D,MAAM,SAAS,SAAS,YAAY,IAAI,CAAC,QAAQ,WAAW,OAAO,CAAC,GAAG,WAAW;AAElF,KAAI;EACF,MAAM,eAA4B;GAChC,MAAM;GACN,SAAS,GAAG,oBAAoB,MAAM;GACtC,WAAW,KAAK,KAAK;GACtB;EAED,MAAM,SAAS,MAAM,uBAAuB,MAAM;EAClD,MAAM,SAAS,MAAM,SACnB,OACA,EACE,UAAU,CAAC,aAAa,EACzB,EACD;GAAE;GAAQ,WAAW;GAAK,aAAa;GAAG,QAAQ;GAAQ,CAC3D;AAED,MADoB,+BAA+B,OACpC,CACb,QAAO;GAAE,SAAS;GAAY,QAAQ,EAAE;GAAY,aAAa;GAAO;EAI1E,MAAM,EAAE,MAAM,QAAQ,gBAAgB,2BADzB,qBAAqB,OAAO,QAC4B,CAAC;EACtE,MAAM,YAAY,wBAAwB,QAAQ,OAAO;AACzD,SAAO;GAAE,SAAS,OAAO,SAAS;GAAY,QAAQ;GAAW;GAAa;SACxE;AACN,SAAO;GAAE,SAAS;GAAY,QAAQ,EAAE;GAAY,aAAa;GAAO;WAChE;AACR,eAAa,MAAM"}
1
+ {"version":3,"file":"judge.js","names":[],"sources":["../../../../src/agent/goals/judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\n\nimport { getApiKey, resolveModel } from '../../providers/index.js';\nimport { completeWithResolvedCredentials } from '../../providers/model-call.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeFreeformBuiltinMessages,\n JUDGE_REASON_EN,\n judgeResponseLanguageNote,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst JUDGE_RESPONSE_SNIPPET_CHARS = 4000;\n\n/**\n * Extract visible text from a pi-ai `AssistantMessage.content` array.\n * Handles `TextContent` (`type: 'text'`) and falls back to `ThinkingContent`\n * (`type: 'thinking'`) when the text blocks are empty — reasoning models\n * (DeepSeek-R1, Qwen-thinking, etc.) may place the entire response inside\n * thinking blocks, leaving the text portion blank.\n */\nexport function extractAssistantText(content: unknown): string {\n if (!Array.isArray(content)) return '';\n\n let textParts = '';\n let thinkingParts = '';\n\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const typed = block as Record<string, unknown>;\n const blockType = typed.type;\n if (blockType === 'text' && typeof typed.text === 'string') {\n textParts += typed.text;\n } else if (blockType === 'thinking') {\n const thinking =\n typeof typed.thinking === 'string'\n ? typed.thinking\n : typeof typed.text === 'string'\n ? typed.text\n : '';\n thinkingParts += thinking;\n }\n }\n\n // Prefer text blocks; fall back to thinking blocks when text is empty.\n return textParts.trim() ? textParts : thinkingParts;\n}\n\n/**\n * Strip markdown code fences (opening AND closing) from raw model output.\n * Handles `` ```json ``, `` ``` ``, and trailing `` ``` `` with optional whitespace.\n */\nexport function stripCodeFences(raw: string): string {\n let text = raw.trim();\n\n // Remove opening code fence: ```<optional-lang>\\n\n const openMatch = text.match(/^`{3,}[^\\n]*\\n?/);\n if (openMatch) {\n text = text.slice(openMatch[0].length);\n }\n\n // Remove closing code fence: \\n```<optional-whitespace>\n const closeMatch = text.match(/\\n?`{3,}\\s*$/);\n if (closeMatch) {\n text = text.slice(0, -closeMatch[0].length);\n }\n\n return text.trim();\n}\n\n/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */\nexport const JUDGE_SYSTEM_PROMPT =\n 'You are a strict judge evaluating whether an autonomous agent has ' +\n \"achieved a user's stated goal. You receive the goal text and the \" +\n \"agent's most recent response. Your only job is to decide whether \" +\n 'the goal is fully satisfied based on that response.\\n\\n' +\n 'A goal is DONE only when:\\n' +\n '- The response explicitly confirms the goal was completed, OR\\n' +\n '- The response clearly shows the final deliverable was produced, OR\\n' +\n '- The response explains the goal is unachievable / blocked / needs ' +\n 'user input (treat this as DONE with reason describing the block).\\n\\n' +\n 'Otherwise the goal is NOT done — CONTINUE.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"done\": <true|false>, \"reason\": \"<one-sentence rationale>\"}';\n\nexport const JUDGE_USER_PROMPT_TEMPLATE =\n 'Goal:\\n{goal}\\n\\n' + \"Agent's most recent response:\\n{response}\\n\\n\" + 'Is the goal satisfied?';\n\nexport const DEFAULT_JUDGE_TIMEOUT_MS = 60_000;\n\nexport function truncateGoalText(text: string, limit: number): string {\n if (!text) return '';\n if (text.length <= limit) return text;\n return text.slice(0, limit) + '… [truncated]';\n}\n\nexport async function resolveGoalJudgeApiKey(\n model: ReturnType<typeof resolveModel>,\n): Promise<string | undefined> {\n try {\n return await getApiKey(model.provider);\n } catch {\n return undefined;\n }\n}\n\nexport function getAssistantMessageErrorReason(message: unknown): string | null {\n if (!message || typeof message !== 'object') return null;\n\n const record = message as Record<string, unknown>;\n const stopReason = record.stopReason;\n const errorMessage = typeof record.errorMessage === 'string' ? record.errorMessage.trim() : '';\n\n if (stopReason === 'error') {\n return errorMessage || 'Judge model call failed.';\n }\n\n return null;\n}\n\n/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */\nexport function parseJudgeResponseFailOpen(raw: string): {\n done: boolean;\n reason: string;\n parseFailed: boolean;\n} {\n if (!raw?.trim()) {\n return { done: false, reason: JUDGE_REASON_EN.judge_returned_empty, parseFailed: true };\n }\n\n const text = stripCodeFences(raw);\n\n let data: Record<string, unknown> | null = null;\n try {\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start !== -1 && end > start) {\n try {\n data = JSON.parse(text.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n data = null;\n }\n }\n }\n\n if (!data || typeof data !== 'object') {\n return { done: false, reason: JUDGE_REASON_EN.judge_reply_not_json, parseFailed: true };\n }\n\n const doneVal = data.done;\n let done: boolean;\n if (typeof doneVal === 'string') {\n done = ['true', 'yes', '1', 'done'].includes(doneVal.trim().toLowerCase());\n } else {\n done = Boolean(doneVal);\n }\n const reason = typeof data.reason === 'string' ? data.reason.trim() : '';\n return { done, reason: reason || JUDGE_REASON_EN.no_reason_provided, parseFailed: false };\n}\n\nexport type GoalJudgeVerdict = 'done' | 'continue' | 'skipped';\n\n/**\n * Ask the configured model whether the goal is satisfied.\n * Fail-open: any error → `continue` (Hermes — turn budget is the backstop).\n */\nexport async function judgeGoalHermesStyle(\n goal: string,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { judgeTimeoutMs?: number; uiLocale?: GoalUiLocale },\n): Promise<{ verdict: GoalJudgeVerdict; reason: string; parseFailed: boolean }> {\n const locale = goalUiLocaleOrFallback(opts?.uiLocale);\n const b = judgeFreeformBuiltinMessages(locale);\n\n if (!goal.trim()) {\n return { verdict: 'skipped', reason: b.emptyGoal, parseFailed: false };\n }\n if (!lastResponse.trim()) {\n return { verdict: 'continue', reason: b.emptyResponse, parseFailed: false };\n }\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(judgeModelRef);\n } catch {\n return { verdict: 'continue', reason: b.noModel, parseFailed: false };\n }\n\n const userContent =\n JUDGE_USER_PROMPT_TEMPLATE.replace('{goal}', truncateGoalText(goal, 2000)).replace(\n '{response}',\n truncateGoalText(lastResponse, JUDGE_RESPONSE_SNIPPET_CHARS),\n ) + judgeResponseLanguageNote(locale);\n\n const timeoutMs =\n typeof opts?.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;\n\n try {\n const combinedUser: UserMessage = {\n role: 'user',\n content: `${JUDGE_SYSTEM_PROMPT}\\n\\n${userContent}`,\n timestamp: Date.now(),\n };\n\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await completeWithResolvedCredentials(\n model,\n {\n messages: [combinedUser],\n },\n { apiKey, maxTokens: 200, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n }\n\n const text = extractAssistantText(result.content);\n const { done, reason, parseFailed } = parseJudgeResponseFailOpen(text);\n const reasonOut = localizeJudgeReasonText(reason, locale);\n return { verdict: done ? 'done' : 'continue', reason: reasonOut, parseFailed };\n } catch {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"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"}
@@ -102,8 +102,9 @@ async function handlePersistentGoalPostTurn(opts) {
102
102
  uiLocale: resolveGoalUiLocale(state)
103
103
  });
104
104
  const completionReadiness = goalService.getCompletionReadiness(goal.id);
105
- if (decision.verdict === "done" && completionReadiness && !completionReadiness.ready && decision.newState) {
106
- const reason = `Completion evidence still needed: ${completionReadiness.missingEvidence.join("; ")}`;
105
+ const executionGaps = completionReadiness ? [...completionReadiness.missingEvidence, ...completionReadiness.pendingOutcome] : [];
106
+ if (decision.verdict === "done" && executionGaps.length > 0 && decision.newState) {
107
+ const reason = `Completion evidence or outcome still needed: ${executionGaps.join("; ")}`;
107
108
  decision = {
108
109
  ...decision,
109
110
  newState: {
@@ -113,11 +114,11 @@ async function handlePersistentGoalPostTurn(opts) {
113
114
  lastReason: reason
114
115
  },
115
116
  shouldContinue: true,
116
- continuationPrompt: `Before declaring the goal complete, collect this evidence:\n${completionReadiness.missingEvidence.map((item) => `- ${item}`).join("\n")}`,
117
+ continuationPrompt: `Before declaring the goal complete, address these gaps:\n${executionGaps.map((item) => `- ${item}`).join("\n")}`,
117
118
  verdict: "continue",
118
119
  reason,
119
120
  message: reason,
120
- missingEvidence: completionReadiness.missingEvidence
121
+ missingEvidence: executionGaps
121
122
  };
122
123
  }
123
124
  if (decision.newState) {
@@ -1 +1 @@
1
- {"version":3,"file":"post-turn.js","names":[],"sources":["../../../../src/agent/goals/post-turn.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config, GoalsConfig } from '../../config/schema.js';\nimport { getAgentDefaultModelRef } from '../../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { GoalService } from '../../goals/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { evaluateAfterTurnHermesLike } from './evaluate-turn.js';\nimport { resolveGoalUiLocale } from './goal-locale.js';\nimport type { PersistentGoalApis } from './persistent-goal-apis.js';\nimport type { PersistentGoalState } from './state.js';\n\nconst log = createLogger('PersistentGoal');\nconst goalService = new GoalService();\n\nfunction buildHistoryExcerpt(messages: AgentMessage[], maxChars: number): string {\n if (maxChars <= 0) return '';\n try {\n const raw = JSON.stringify(messages);\n if (raw.length <= maxChars) return raw;\n return raw.slice(-maxChars);\n } catch {\n return '';\n }\n}\n\nfunction buildGoalContextText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n const lines = [`Title: ${goal.contract?.objective || goal.title}`];\n if (goal.contract?.scopeBoundary) {\n lines.push(`Scope boundary:\\n${goal.contract.scopeBoundary}`);\n }\n if (goal.contract?.evidencePlan.length) {\n lines.push(`Expected completion evidence:\\n${goal.contract.evidencePlan.map((item) => `- ${item}`).join('\\n')}`);\n }\n if (goal.contextMessage?.text.trim()) {\n lines.push(`Context:\\n${goal.contextMessage.text.trim()}`);\n }\n if (goal.contextMessage?.attachments.length) {\n lines.push(\n [\n 'Attachments:',\n ...goal.contextMessage.attachments.map((attachment) =>\n `- ${attachment.name} (${attachment.mimeType}, ${attachment.size} bytes) ${attachment.uri}`,\n ),\n ].join('\\n'),\n );\n }\n return lines.join('\\n\\n');\n}\n\nfunction resolveJudgeModelRef(\n config: Config | undefined,\n sessionKey: string,\n storedJudge?: string,\n runtimeSessionModelRef?: string,\n): string | undefined {\n const fromCfg = config?.goals?.judgeModelRef?.trim();\n if (fromCfg) return fromCfg;\n if (storedJudge?.trim()) return storedJudge.trim();\n if (config) {\n const profile = resolveEffectiveAgentProfileForSession(config, sessionKey);\n if (profile.primaryModelRef?.trim()) return profile.primaryModelRef.trim();\n }\n if (runtimeSessionModelRef?.trim()) return runtimeSessionModelRef.trim();\n if (config) return getAgentDefaultModelRef(config);\n return undefined;\n}\n\nexport function shouldRunInitialChecklistDecomposition(input: {\n checklistLength: number;\n turnsUsed: number;\n checklistDecomposePolicy?: GoalsConfig['checklistDecomposePolicy'];\n}): boolean {\n if (input.checklistLength === 0) return true;\n return input.checklistDecomposePolicy === 'supplement_existing' && input.turnsUsed === 0;\n}\n\nasync function appendAssistantLine(apis: PersistentGoalApis, sessionKey: string, text: string): Promise<void> {\n await apis.appendAssistantReceipt(sessionKey, text);\n}\n\nexport async function handlePersistentGoalPostTurn(opts: {\n apis: PersistentGoalApis;\n sessionKey: string;\n assistantPlainText: string;\n aborted: boolean;\n streamError?: string;\n skipPersistentGoalPostTurn: boolean;\n config: Config | undefined;\n /** Active session model (overrides, per-agent defaults) when goals/global defaults are unset. */\n runtimeSessionModelRef?: string;\n signal?: AbortSignal;\n /** Hermes-style: verdict line also sent as a normal outbound message (non-webchat). */\n publishVerdictToChannel?: (text: string) => Promise<void>;\n onGoalStatusUpdated?: (payload: {\n goalId: string;\n sessionKey: string;\n previousStatus: string;\n status: string;\n goal: import('../../goals/types.js').GoalWithDetails;\n }) => void;\n}): Promise<void> {\n const {\n apis,\n sessionKey,\n assistantPlainText,\n aborted,\n streamError,\n skipPersistentGoalPostTurn,\n config,\n runtimeSessionModelRef,\n signal,\n publishVerdictToChannel,\n onGoalStatusUpdated,\n } = opts;\n\n if (skipPersistentGoalPostTurn) return;\n if (aborted || streamError) return;\n\n const meta = await apis.getSessionMetadata(sessionKey);\n if (!meta) return;\n\n const goal = goalService.getActiveForSession(sessionKey);\n if (!goal || goal.status !== 'active') return;\n\n const goalsCfg = config?.goals;\n const shouldDecomposeChecklist = shouldRunInitialChecklistDecomposition({\n checklistLength: goal.checklist.length,\n turnsUsed: goal.turnsUsed,\n checklistDecomposePolicy: goalsCfg?.checklistDecomposePolicy,\n });\n const state: PersistentGoalState = {\n goal: buildGoalContextText(goal),\n status: 'active',\n turnsUsed: goal.turnsUsed,\n maxTurns: goal.maxTurns,\n createdAt: goal.createdAt,\n lastTurnAt: goal.updatedAt,\n lastReason: goal.blockedReason,\n judgeModelRef: goal.judgeModelRef,\n decomposed: shouldDecomposeChecklist ? undefined : true,\n uiLocale: goal.uiLocale,\n checklist: goal.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidence: it.evidenceSummary,\n })),\n };\n\n const judgeRef = resolveJudgeModelRef(config, sessionKey, state.judgeModelRef, runtimeSessionModelRef);\n if (!judgeRef) {\n log.warn({ sessionKey }, 'Persistent goal: no judge model ref; skipping post-turn');\n return;\n }\n\n const historyCap = goalsCfg?.checklistHistoryChars ?? 24_000;\n let historyExcerpt = '';\n try {\n const msgs = await apis.loadMessages(sessionKey);\n historyExcerpt = buildHistoryExcerpt(msgs, historyCap);\n } catch (err) {\n log.debug(\n { err, sessionKey },\n `Persistent goal: could not load messages for judge context: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n let decision = await evaluateAfterTurnHermesLike(state, assistantPlainText, judgeRef, signal, {\n goalsSlice: goalsCfg,\n historyExcerpt,\n goalContextExcerpt: buildGoalContextText(goal),\n uiLocale: resolveGoalUiLocale(state),\n });\n\n const completionReadiness = goalService.getCompletionReadiness(goal.id);\n if (decision.verdict === 'done' && completionReadiness && !completionReadiness.ready && decision.newState) {\n const reason = `Completion evidence still needed: ${completionReadiness.missingEvidence.join('; ')}`;\n decision = {\n ...decision,\n newState: {\n ...decision.newState,\n status: 'active',\n lastVerdict: 'continue',\n lastReason: reason,\n },\n shouldContinue: true,\n continuationPrompt: `Before declaring the goal complete, collect this evidence:\\n${completionReadiness.missingEvidence.map((item) => `- ${item}`).join('\\n')}`,\n verdict: 'continue',\n reason,\n message: reason,\n missingEvidence: completionReadiness.missingEvidence,\n };\n }\n\n if (decision.newState) {\n const ns = decision.newState;\n const completedChecklistItemIds = decision.completedChecklistItemIndexes\n ?.map((index) => goal.checklist[index]?.id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n try {\n const updatedGoal = goalService.syncPostTurnState({\n goalId: goal.id,\n sessionKey,\n source: 'chat',\n status: ns.status === 'done'\n ? 'done'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : ns.status === 'paused'\n ? 'paused'\n : 'active',\n turnsUsed: ns.turnsUsed,\n maxTurns: ns.maxTurns,\n reason: ns.pausedReason ?? decision.reason,\n nextAction: decision.continuationPrompt ?? undefined,\n assistantPreview: assistantPlainText,\n verdict: decision.verdict === 'done'\n ? 'done'\n : decision.verdict === 'decompose'\n ? 'decompose'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : 'continue',\n confidence: decision.confidence,\n missingEvidence: decision.missingEvidence,\n userQuestion: decision.userQuestion,\n completedChecklistItemIds,\n checklist: ns.checklist?.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidenceSummary: it.evidence,\n })),\n });\n if (updatedGoal && updatedGoal.status !== goal.status) {\n onGoalStatusUpdated?.({\n goalId: goal.id,\n sessionKey,\n previousStatus: goal.status,\n status: updatedGoal.status,\n goal: updatedGoal,\n });\n }\n } catch (err) {\n log.warn(\n { err, sessionKey, goalId: goal.id },\n `Persistent goal: SQLite goal update failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n if (decision.message) {\n if (publishVerdictToChannel) {\n try {\n await publishVerdictToChannel(decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: channel verdict send failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n try {\n await appendAssistantLine(apis, sessionKey, decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: failed to append status message: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n if (decision.shouldContinue && decision.continuationPrompt) {\n apis.scheduleContinuation(sessionKey, decision.continuationPrompt);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"post-turn.js","names":[],"sources":["../../../../src/agent/goals/post-turn.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config, GoalsConfig } from '../../config/schema.js';\nimport { getAgentDefaultModelRef } from '../../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { GoalService } from '../../goals/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { evaluateAfterTurnHermesLike } from './evaluate-turn.js';\nimport { resolveGoalUiLocale } from './goal-locale.js';\nimport type { PersistentGoalApis } from './persistent-goal-apis.js';\nimport type { PersistentGoalState } from './state.js';\n\nconst log = createLogger('PersistentGoal');\nconst goalService = new GoalService();\n\nfunction buildHistoryExcerpt(messages: AgentMessage[], maxChars: number): string {\n if (maxChars <= 0) return '';\n try {\n const raw = JSON.stringify(messages);\n if (raw.length <= maxChars) return raw;\n return raw.slice(-maxChars);\n } catch {\n return '';\n }\n}\n\nfunction buildGoalContextText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n const lines = [`Title: ${goal.contract?.objective || goal.title}`];\n if (goal.contract?.scopeBoundary) {\n lines.push(`Scope boundary:\\n${goal.contract.scopeBoundary}`);\n }\n if (goal.contract?.evidencePlan.length) {\n lines.push(`Expected completion evidence:\\n${goal.contract.evidencePlan.map((item) => `- ${item}`).join('\\n')}`);\n }\n if (goal.contextMessage?.text.trim()) {\n lines.push(`Context:\\n${goal.contextMessage.text.trim()}`);\n }\n if (goal.contextMessage?.attachments.length) {\n lines.push(\n [\n 'Attachments:',\n ...goal.contextMessage.attachments.map((attachment) =>\n `- ${attachment.name} (${attachment.mimeType}, ${attachment.size} bytes) ${attachment.uri}`,\n ),\n ].join('\\n'),\n );\n }\n return lines.join('\\n\\n');\n}\n\nfunction resolveJudgeModelRef(\n config: Config | undefined,\n sessionKey: string,\n storedJudge?: string,\n runtimeSessionModelRef?: string,\n): string | undefined {\n const fromCfg = config?.goals?.judgeModelRef?.trim();\n if (fromCfg) return fromCfg;\n if (storedJudge?.trim()) return storedJudge.trim();\n if (config) {\n const profile = resolveEffectiveAgentProfileForSession(config, sessionKey);\n if (profile.primaryModelRef?.trim()) return profile.primaryModelRef.trim();\n }\n if (runtimeSessionModelRef?.trim()) return runtimeSessionModelRef.trim();\n if (config) return getAgentDefaultModelRef(config);\n return undefined;\n}\n\nexport function shouldRunInitialChecklistDecomposition(input: {\n checklistLength: number;\n turnsUsed: number;\n checklistDecomposePolicy?: GoalsConfig['checklistDecomposePolicy'];\n}): boolean {\n if (input.checklistLength === 0) return true;\n return input.checklistDecomposePolicy === 'supplement_existing' && input.turnsUsed === 0;\n}\n\nasync function appendAssistantLine(apis: PersistentGoalApis, sessionKey: string, text: string): Promise<void> {\n await apis.appendAssistantReceipt(sessionKey, text);\n}\n\nexport async function handlePersistentGoalPostTurn(opts: {\n apis: PersistentGoalApis;\n sessionKey: string;\n assistantPlainText: string;\n aborted: boolean;\n streamError?: string;\n skipPersistentGoalPostTurn: boolean;\n config: Config | undefined;\n /** Active session model (overrides, per-agent defaults) when goals/global defaults are unset. */\n runtimeSessionModelRef?: string;\n signal?: AbortSignal;\n /** Hermes-style: verdict line also sent as a normal outbound message (non-webchat). */\n publishVerdictToChannel?: (text: string) => Promise<void>;\n onGoalStatusUpdated?: (payload: {\n goalId: string;\n sessionKey: string;\n previousStatus: string;\n status: string;\n goal: import('../../goals/types.js').GoalWithDetails;\n }) => void;\n}): Promise<void> {\n const {\n apis,\n sessionKey,\n assistantPlainText,\n aborted,\n streamError,\n skipPersistentGoalPostTurn,\n config,\n runtimeSessionModelRef,\n signal,\n publishVerdictToChannel,\n onGoalStatusUpdated,\n } = opts;\n\n if (skipPersistentGoalPostTurn) return;\n if (aborted || streamError) return;\n\n const meta = await apis.getSessionMetadata(sessionKey);\n if (!meta) return;\n\n const goal = goalService.getActiveForSession(sessionKey);\n if (!goal || goal.status !== 'active') return;\n\n const goalsCfg = config?.goals;\n const shouldDecomposeChecklist = shouldRunInitialChecklistDecomposition({\n checklistLength: goal.checklist.length,\n turnsUsed: goal.turnsUsed,\n checklistDecomposePolicy: goalsCfg?.checklistDecomposePolicy,\n });\n const state: PersistentGoalState = {\n goal: buildGoalContextText(goal),\n status: 'active',\n turnsUsed: goal.turnsUsed,\n maxTurns: goal.maxTurns,\n createdAt: goal.createdAt,\n lastTurnAt: goal.updatedAt,\n lastReason: goal.blockedReason,\n judgeModelRef: goal.judgeModelRef,\n decomposed: shouldDecomposeChecklist ? undefined : true,\n uiLocale: goal.uiLocale,\n checklist: goal.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidence: it.evidenceSummary,\n })),\n };\n\n const judgeRef = resolveJudgeModelRef(config, sessionKey, state.judgeModelRef, runtimeSessionModelRef);\n if (!judgeRef) {\n log.warn({ sessionKey }, 'Persistent goal: no judge model ref; skipping post-turn');\n return;\n }\n\n const historyCap = goalsCfg?.checklistHistoryChars ?? 24_000;\n let historyExcerpt = '';\n try {\n const msgs = await apis.loadMessages(sessionKey);\n historyExcerpt = buildHistoryExcerpt(msgs, historyCap);\n } catch (err) {\n log.debug(\n { err, sessionKey },\n `Persistent goal: could not load messages for judge context: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n let decision = await evaluateAfterTurnHermesLike(state, assistantPlainText, judgeRef, signal, {\n goalsSlice: goalsCfg,\n historyExcerpt,\n goalContextExcerpt: buildGoalContextText(goal),\n uiLocale: resolveGoalUiLocale(state),\n });\n\n const completionReadiness = goalService.getCompletionReadiness(goal.id);\n const executionGaps = completionReadiness\n ? [...completionReadiness.missingEvidence, ...completionReadiness.pendingOutcome]\n : [];\n if (decision.verdict === 'done' && executionGaps.length > 0 && decision.newState) {\n const reason = `Completion evidence or outcome still needed: ${executionGaps.join('; ')}`;\n decision = {\n ...decision,\n newState: {\n ...decision.newState,\n status: 'active',\n lastVerdict: 'continue',\n lastReason: reason,\n },\n shouldContinue: true,\n continuationPrompt: `Before declaring the goal complete, address these gaps:\\n${executionGaps.map((item) => `- ${item}`).join('\\n')}`,\n verdict: 'continue',\n reason,\n message: reason,\n missingEvidence: executionGaps,\n };\n }\n\n if (decision.newState) {\n const ns = decision.newState;\n const completedChecklistItemIds = decision.completedChecklistItemIndexes\n ?.map((index) => goal.checklist[index]?.id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n try {\n const updatedGoal = goalService.syncPostTurnState({\n goalId: goal.id,\n sessionKey,\n source: 'chat',\n status: ns.status === 'done'\n ? 'done'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : ns.status === 'paused'\n ? 'paused'\n : 'active',\n turnsUsed: ns.turnsUsed,\n maxTurns: ns.maxTurns,\n reason: ns.pausedReason ?? decision.reason,\n nextAction: decision.continuationPrompt ?? undefined,\n assistantPreview: assistantPlainText,\n verdict: decision.verdict === 'done'\n ? 'done'\n : decision.verdict === 'decompose'\n ? 'decompose'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : 'continue',\n confidence: decision.confidence,\n missingEvidence: decision.missingEvidence,\n userQuestion: decision.userQuestion,\n completedChecklistItemIds,\n checklist: ns.checklist?.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidenceSummary: it.evidence,\n })),\n });\n if (updatedGoal && updatedGoal.status !== goal.status) {\n onGoalStatusUpdated?.({\n goalId: goal.id,\n sessionKey,\n previousStatus: goal.status,\n status: updatedGoal.status,\n goal: updatedGoal,\n });\n }\n } catch (err) {\n log.warn(\n { err, sessionKey, goalId: goal.id },\n `Persistent goal: SQLite goal update failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n if (decision.message) {\n if (publishVerdictToChannel) {\n try {\n await publishVerdictToChannel(decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: channel verdict send failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n try {\n await appendAssistantLine(apis, sessionKey, decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: failed to append status message: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n if (decision.shouldContinue && decision.continuationPrompt) {\n apis.scheduleContinuation(sessionKey, decision.continuationPrompt);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { getApiKey, getModelsByProvider, init_providers, resolveModel } from "../../../providers/index.js";
2
+ import { completeWithResolvedCredentials } from "../../../providers/model-call.js";
2
3
  import { registerImageUnderstandingProvider, registerImageUnderstandingProviderFactory } from "./provider-registry.js";
3
4
  import { coerceImageAssistantText } from "../image-helpers.js";
4
- import { complete } from "@earendil-works/pi-ai/compat";
5
5
  //#region src/agent/image/understanding/pi-ai-provider.ts
6
6
  init_providers();
7
7
  function resolveMaxTokens(modelMaxTokens, requestedMaxTokens = 4096) {
@@ -39,7 +39,7 @@ function buildPiAiImageUnderstandingProvider(providerId) {
39
39
  const timeoutSignal = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(timeoutMs) : void 0;
40
40
  return {
41
41
  text: coerceImageAssistantText({
42
- message: await complete(model, context, {
42
+ message: await completeWithResolvedCredentials(model, context, {
43
43
  apiKey,
44
44
  maxTokens,
45
45
  signal: (() => {
@@ -1 +1 @@
1
- {"version":3,"file":"pi-ai-provider.js","names":[],"sources":["../../../../../src/agent/image/understanding/pi-ai-provider.ts"],"sourcesContent":["import { complete, type Api, type Context, type Model } from '@earendil-works/pi-ai/compat';\nimport { resolveModel, getApiKey, getModelsByProvider } from '../../../providers/index.js';\nimport { coerceImageAssistantText } from '../image-helpers.js';\nimport {\n registerImageUnderstandingProvider,\n registerImageUnderstandingProviderFactory,\n} from './provider-registry.js';\nimport type { ImageUnderstandingProvider } from './types.js';\n\nfunction resolveMaxTokens(modelMaxTokens: number | undefined, requestedMaxTokens = 4096): number {\n if (\n typeof modelMaxTokens !== 'number' ||\n !Number.isFinite(modelMaxTokens) ||\n modelMaxTokens <= 0\n ) {\n return requestedMaxTokens;\n }\n return Math.min(requestedMaxTokens, modelMaxTokens);\n}\n\nexport function buildPiAiImageUnderstandingProvider(providerId: string): ImageUnderstandingProvider {\n return {\n id: providerId,\n label: `pi-ai (${providerId})`,\n async isConfigured() {\n const apiKey = await getApiKey(providerId);\n return Boolean(apiKey);\n },\n async describeImages(modelId, request) {\n const modelRef = `${providerId}/${modelId}`;\n const model = resolveModel(modelRef) as Model<Api>;\n if (!model.input?.includes('image')) {\n throw new Error(`Model does not support images: ${modelRef}`);\n }\n const apiKey = await getApiKey(providerId);\n if (!apiKey) {\n throw new Error(`No API key configured for provider: ${providerId}`);\n }\n\n const context: Context = {\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt },\n ...request.images.map((img) => ({\n type: 'image' as const,\n data: img.buffer.toString('base64'),\n mimeType: img.mimeType || 'image/jpeg',\n })),\n ],\n timestamp: Date.now(),\n },\n ],\n };\n\n const maxTokens = resolveMaxTokens(model.maxTokens, request.maxTokens ?? 512);\n const timeoutMs = request.timeoutMs ?? 60_000;\n const timeoutSignal =\n typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function'\n ? AbortSignal.timeout(timeoutMs)\n : undefined;\n const signal = (() => {\n if (timeoutSignal && request.signal && typeof AbortSignal.any === 'function') {\n return AbortSignal.any([request.signal, timeoutSignal]);\n }\n if (request.signal) {\n return request.signal;\n }\n if (timeoutSignal) {\n return timeoutSignal;\n }\n const controller = new AbortController();\n setTimeout(() => controller.abort(), timeoutMs);\n return controller.signal;\n })();\n\n const message = await complete(model, context, {\n apiKey,\n maxTokens,\n signal,\n });\n\n const text = coerceImageAssistantText({\n message,\n provider: providerId,\n model: modelId,\n });\n return { text, provider: providerId, model: modelId };\n },\n };\n}\n\nfor (const providerId of ['openai', 'anthropic', 'google']) {\n registerImageUnderstandingProvider(buildPiAiImageUnderstandingProvider(providerId));\n}\n\nregisterImageUnderstandingProviderFactory((providerId) => {\n const hasVisionModel = getModelsByProvider(providerId).some((model) =>\n model.input?.includes('image'),\n );\n return hasVisionModel ? buildPiAiImageUnderstandingProvider(providerId) : undefined;\n});\n"],"mappings":";;;;;gBAC2F;AAQ3F,SAAS,iBAAiB,gBAAoC,qBAAqB,MAAc;AAC/F,KACE,OAAO,mBAAmB,YAC1B,CAAC,OAAO,SAAS,eAAe,IAChC,kBAAkB,EAElB,QAAO;AAET,QAAO,KAAK,IAAI,oBAAoB,eAAe;;AAGrD,SAAgB,oCAAoC,YAAgD;AAClG,QAAO;EACL,IAAI;EACJ,OAAO,UAAU,WAAW;EAC5B,MAAM,eAAe;GACnB,MAAM,SAAS,MAAM,UAAU,WAAW;AAC1C,UAAO,QAAQ,OAAO;;EAExB,MAAM,eAAe,SAAS,SAAS;GACrC,MAAM,WAAW,GAAG,WAAW,GAAG;GAClC,MAAM,QAAQ,aAAa,SAAS;AACpC,OAAI,CAAC,MAAM,OAAO,SAAS,QAAQ,CACjC,OAAM,IAAI,MAAM,kCAAkC,WAAW;GAE/D,MAAM,SAAS,MAAM,UAAU,WAAW;AAC1C,OAAI,CAAC,OACH,OAAM,IAAI,MAAM,uCAAuC,aAAa;GAGtE,MAAM,UAAmB,EACvB,UAAU,CACR;IACE,MAAM;IACN,SAAS,CACP;KAAE,MAAM;KAAQ,MAAM,QAAQ;KAAQ,EACtC,GAAG,QAAQ,OAAO,KAAK,SAAS;KAC9B,MAAM;KACN,MAAM,IAAI,OAAO,SAAS,SAAS;KACnC,UAAU,IAAI,YAAY;KAC3B,EAAE,CACJ;IACD,WAAW,KAAK,KAAK;IACtB,CACF,EACF;GAED,MAAM,YAAY,iBAAiB,MAAM,WAAW,QAAQ,aAAa,IAAI;GAC7E,MAAM,YAAY,QAAQ,aAAa;GACvC,MAAM,gBACJ,OAAO,gBAAgB,eAAe,OAAO,YAAY,YAAY,aACjE,YAAY,QAAQ,UAAU,GAC9B,KAAA;AA2BN,UAAO;IAAE,MALI,yBAAyB;KACpC,SAAA,MAPoB,SAAS,OAAO,SAAS;MAC7C;MACA;MACA,eAlBoB;AACpB,WAAI,iBAAiB,QAAQ,UAAU,OAAO,YAAY,QAAQ,WAChE,QAAO,YAAY,IAAI,CAAC,QAAQ,QAAQ,cAAc,CAAC;AAEzD,WAAI,QAAQ,OACV,QAAO,QAAQ;AAEjB,WAAI,cACF,QAAO;OAET,MAAM,aAAa,IAAI,iBAAiB;AACxC,wBAAiB,WAAW,OAAO,EAAE,UAAU;AAC/C,cAAO,WAAW;UAMZ;MACP,CAAC;KAIA,UAAU;KACV,OAAO;KACR,CACY;IAAE,UAAU;IAAY,OAAO;IAAS;;EAExD;;AAGH,KAAK,MAAM,cAAc;CAAC;CAAU;CAAa;CAAS,CACxD,oCAAmC,oCAAoC,WAAW,CAAC;AAGrF,2CAA2C,eAAe;AAIxD,QAHuB,oBAAoB,WAAW,CAAC,MAAM,UAC3D,MAAM,OAAO,SAAS,QAAQ,CAEX,GAAG,oCAAoC,WAAW,GAAG,KAAA;EAC1E"}
1
+ {"version":3,"file":"pi-ai-provider.js","names":[],"sources":["../../../../../src/agent/image/understanding/pi-ai-provider.ts"],"sourcesContent":["import { type Api, type Context, type Model } from '@earendil-works/pi-ai/compat';\nimport { resolveModel, getApiKey, getModelsByProvider } from '../../../providers/index.js';\nimport { completeWithResolvedCredentials } from '../../../providers/model-call.js';\nimport { coerceImageAssistantText } from '../image-helpers.js';\nimport {\n registerImageUnderstandingProvider,\n registerImageUnderstandingProviderFactory,\n} from './provider-registry.js';\nimport type { ImageUnderstandingProvider } from './types.js';\n\nfunction resolveMaxTokens(modelMaxTokens: number | undefined, requestedMaxTokens = 4096): number {\n if (\n typeof modelMaxTokens !== 'number' ||\n !Number.isFinite(modelMaxTokens) ||\n modelMaxTokens <= 0\n ) {\n return requestedMaxTokens;\n }\n return Math.min(requestedMaxTokens, modelMaxTokens);\n}\n\nexport function buildPiAiImageUnderstandingProvider(providerId: string): ImageUnderstandingProvider {\n return {\n id: providerId,\n label: `pi-ai (${providerId})`,\n async isConfigured() {\n const apiKey = await getApiKey(providerId);\n return Boolean(apiKey);\n },\n async describeImages(modelId, request) {\n const modelRef = `${providerId}/${modelId}`;\n const model = resolveModel(modelRef) as Model<Api>;\n if (!model.input?.includes('image')) {\n throw new Error(`Model does not support images: ${modelRef}`);\n }\n const apiKey = await getApiKey(providerId);\n if (!apiKey) {\n throw new Error(`No API key configured for provider: ${providerId}`);\n }\n\n const context: Context = {\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt },\n ...request.images.map((img) => ({\n type: 'image' as const,\n data: img.buffer.toString('base64'),\n mimeType: img.mimeType || 'image/jpeg',\n })),\n ],\n timestamp: Date.now(),\n },\n ],\n };\n\n const maxTokens = resolveMaxTokens(model.maxTokens, request.maxTokens ?? 512);\n const timeoutMs = request.timeoutMs ?? 60_000;\n const timeoutSignal =\n typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function'\n ? AbortSignal.timeout(timeoutMs)\n : undefined;\n const signal = (() => {\n if (timeoutSignal && request.signal && typeof AbortSignal.any === 'function') {\n return AbortSignal.any([request.signal, timeoutSignal]);\n }\n if (request.signal) {\n return request.signal;\n }\n if (timeoutSignal) {\n return timeoutSignal;\n }\n const controller = new AbortController();\n setTimeout(() => controller.abort(), timeoutMs);\n return controller.signal;\n })();\n\n const message = await completeWithResolvedCredentials(model, context, {\n apiKey,\n maxTokens,\n signal,\n });\n\n const text = coerceImageAssistantText({\n message,\n provider: providerId,\n model: modelId,\n });\n return { text, provider: providerId, model: modelId };\n },\n };\n}\n\nfor (const providerId of ['openai', 'anthropic', 'google']) {\n registerImageUnderstandingProvider(buildPiAiImageUnderstandingProvider(providerId));\n}\n\nregisterImageUnderstandingProviderFactory((providerId) => {\n const hasVisionModel = getModelsByProvider(providerId).some((model) =>\n model.input?.includes('image'),\n );\n return hasVisionModel ? buildPiAiImageUnderstandingProvider(providerId) : undefined;\n});\n"],"mappings":";;;;;gBAC2F;AAS3F,SAAS,iBAAiB,gBAAoC,qBAAqB,MAAc;AAC/F,KACE,OAAO,mBAAmB,YAC1B,CAAC,OAAO,SAAS,eAAe,IAChC,kBAAkB,EAElB,QAAO;AAET,QAAO,KAAK,IAAI,oBAAoB,eAAe;;AAGrD,SAAgB,oCAAoC,YAAgD;AAClG,QAAO;EACL,IAAI;EACJ,OAAO,UAAU,WAAW;EAC5B,MAAM,eAAe;GACnB,MAAM,SAAS,MAAM,UAAU,WAAW;AAC1C,UAAO,QAAQ,OAAO;;EAExB,MAAM,eAAe,SAAS,SAAS;GACrC,MAAM,WAAW,GAAG,WAAW,GAAG;GAClC,MAAM,QAAQ,aAAa,SAAS;AACpC,OAAI,CAAC,MAAM,OAAO,SAAS,QAAQ,CACjC,OAAM,IAAI,MAAM,kCAAkC,WAAW;GAE/D,MAAM,SAAS,MAAM,UAAU,WAAW;AAC1C,OAAI,CAAC,OACH,OAAM,IAAI,MAAM,uCAAuC,aAAa;GAGtE,MAAM,UAAmB,EACvB,UAAU,CACR;IACE,MAAM;IACN,SAAS,CACP;KAAE,MAAM;KAAQ,MAAM,QAAQ;KAAQ,EACtC,GAAG,QAAQ,OAAO,KAAK,SAAS;KAC9B,MAAM;KACN,MAAM,IAAI,OAAO,SAAS,SAAS;KACnC,UAAU,IAAI,YAAY;KAC3B,EAAE,CACJ;IACD,WAAW,KAAK,KAAK;IACtB,CACF,EACF;GAED,MAAM,YAAY,iBAAiB,MAAM,WAAW,QAAQ,aAAa,IAAI;GAC7E,MAAM,YAAY,QAAQ,aAAa;GACvC,MAAM,gBACJ,OAAO,gBAAgB,eAAe,OAAO,YAAY,YAAY,aACjE,YAAY,QAAQ,UAAU,GAC9B,KAAA;AA2BN,UAAO;IAAE,MALI,yBAAyB;KACpC,SAAA,MAPoB,gCAAgC,OAAO,SAAS;MACpE;MACA;MACA,eAlBoB;AACpB,WAAI,iBAAiB,QAAQ,UAAU,OAAO,YAAY,QAAQ,WAChE,QAAO,YAAY,IAAI,CAAC,QAAQ,QAAQ,cAAc,CAAC;AAEzD,WAAI,QAAQ,OACV,QAAO,QAAQ;AAEjB,WAAI,cACF,QAAO;OAET,MAAM,aAAa,IAAI,iBAAiB;AACxC,wBAAiB,WAAW,OAAO,EAAE,UAAU;AAC/C,cAAO,WAAW;UAMZ;MACP,CAAC;KAIA,UAAU;KACV,OAAO;KACR,CACY;IAAE,UAAU;IAAY,OAAO;IAAS;;EAExD;;AAGH,KAAK,MAAM,cAAc;CAAC;CAAU;CAAa;CAAS,CACxD,oCAAmC,oCAAoC,WAAW,CAAC;AAGrF,2CAA2C,eAAe;AAIxD,QAHuB,oBAAoB,WAAW,CAAC,MAAM,UAC3D,MAAM,OAAO,SAAS,QAAQ,CAEX,GAAG,oCAAoC,WAAW,GAAG,KAAA;EAC1E"}
@@ -64,7 +64,10 @@ function resolveMcpTransport(serverName, rawServer) {
64
64
  };
65
65
  }
66
66
  if (resolved.transportType === "streamable-http") return {
67
- transport: new StreamableHTTPClientTransport(new URL(resolved.url), { requestInit: resolved.headers ? { headers: resolved.headers } : void 0 }),
67
+ transport: new StreamableHTTPClientTransport(new URL(resolved.url), {
68
+ requestInit: resolved.headers ? { headers: resolved.headers } : void 0,
69
+ fetch: fetchWithUndici
70
+ }),
68
71
  description: resolved.description,
69
72
  transportType: "streamable-http",
70
73
  connectionTimeoutMs: resolved.connectionTimeoutMs