@xopcai/xopc 0.0.161 → 0.0.162

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 (233) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-o7GRljfD.js → activity-store-hpcNv9MZ.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-9R3szLMc.js → agent-avatar-dicebear-Zf9UQEmQ.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DfVkZlHc.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-jSTqFMq9.js → api-Dnatri09.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-D81cyE76.js → app-management-settings-panel-BBTR9wJP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-Ct6bZQCV.js → appearance-settings-C2zpLCHD.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-BMtAa4Ra.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-CfD7AZKn.js → archive-plugin-9eR_ODY1.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CP_Gaxt3.js → attachment-load-DPuWYUeX.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-BGKM_NDZ.js → automation-suggestion-card-Dw49OJRl.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-BiSAMYTr.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-IPr2EVnS.js → binary-plugins-BdkJpDFm.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-B6aHEGA6.js → block-editor-CAi7SXYU.js} +47 -47
  16. package/dist/gateway/static/root/assets/browser-settings-page-DHmaEJS2.js +8 -0
  17. package/dist/gateway/static/root/assets/browser-workflow-inputs-Dx6wkGz1.js +1 -0
  18. package/dist/gateway/static/root/assets/browser-workflows-page-Skertc-A.js +3 -0
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-B5wSgf4f.js +2 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-CCX9-LjU.js → capability-presets-api-CNFl7dM3.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DyvFZwBj.js +2 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-MmLMLDWf.js → channel-recipient-api-DYQyGDw4.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-BBKEqDZn.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-Drk110ve.js +1 -0
  25. package/dist/gateway/static/root/assets/{connector-logo-BbjzIs87.js → connector-logo-Bng6kxYF.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-HpgaUDQ1.js +2 -0
  27. package/dist/gateway/static/root/assets/desktop-pet-Bpf6oegd.js +1 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-settings-DQLqGLc0.js → desktop-pet-settings-BVUyefSd.js} +1 -1
  29. package/dist/gateway/static/root/assets/{directory-picker-path-field-ClsiXhmz.js → directory-picker-path-field-DjSZAPz_.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dreaming-settings-CjMPPdzg.js → dreaming-settings-CAZk2AM4.js} +3 -3
  31. package/dist/gateway/static/root/assets/{extension-debug-page-57eizjhB.js → extension-debug-page-C2F6vTTd.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-CsbSb3u1.js → extension-page-AnIt4bn4.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-settings-page-DKA9-lyP.js → extension-settings-page-CLSc6682.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-DIPJuzBZ.js → gateway-config-api-DLFyZv33.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-settings-CDLqAQY7.js → gateway-settings-DnQAA-qq.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-DrfSJtvT.js → gateway-startup-retry-DbzLyJ3R.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-DrnKFC6M.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-Cw1hpJkZ.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-lGC10UkU.js → goals-config-api-REmr3QCr.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-BDGkTVma.js +2 -0
  41. package/dist/gateway/static/root/assets/{goals-settings-BWq0pdrA.js → goals-settings-Dz0F3uRO.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-D4o8BJVv.js → heartbeat-settings-CQFY5gYs.js} +1 -1
  43. package/dist/gateway/static/root/assets/index-C8JkTS6d.js +199 -0
  44. package/dist/gateway/static/root/assets/index-hmrG55qg.css +1 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6T2QYehS.js → keyboard-shortcuts-settings-BnOQXU5k.js} +1 -1
  46. package/dist/gateway/static/root/assets/local-app-workbench-page-Bdef1b7F.js +2 -0
  47. package/dist/gateway/static/root/assets/{local-apps-page-DCjg2K9f.js → local-apps-page-KsOtWOyM.js} +1 -1
  48. package/dist/gateway/static/root/assets/{locale-store-Dar-xqQr.js → locale-store-0lpYdNDr.js} +1 -1
  49. package/dist/gateway/static/root/assets/{logs-page-CyYCBqym.js → logs-page-CwLPgrWh.js} +3 -3
  50. package/dist/gateway/static/root/assets/{markdown-split-rt1XO43g.js → markdown-split-D5GRg10r.js} +1 -1
  51. package/dist/gateway/static/root/assets/{media-plugins-Bwo8CJuh.js → media-plugins-C1ryULGs.js} +1 -1
  52. package/dist/gateway/static/root/assets/messages-BwQ3WssU.js +5 -0
  53. package/dist/gateway/static/root/assets/{notes-page-Dp-pkX7d.js → notes-page-CIeZ1_DT.js} +1 -1
  54. package/dist/gateway/static/root/assets/notes-workbench-Cf06q19x.js +4 -0
  55. package/dist/gateway/static/root/assets/{page-tabs-CzZ4iKOb.js → page-tabs-Caj1-E_X.js} +1 -1
  56. package/dist/gateway/static/root/assets/{preview-open-alternatives-3E_Qa-58.js → preview-open-alternatives-DKwEce-9.js} +1 -1
  57. package/dist/gateway/static/root/assets/{product-open-page-B2T48Sbt.js → product-open-page-B90ZskkN.js} +1 -1
  58. package/dist/gateway/static/root/assets/project-detail-page-SHTurM4t.js +1 -0
  59. package/dist/gateway/static/root/assets/projects-page-BcC2qUAw.js +1 -0
  60. package/dist/gateway/static/root/assets/remote-access-hub-6vGefBHv.js +1 -0
  61. package/dist/gateway/static/root/assets/save-bar-controls-BDYt53uQ.js +1 -0
  62. package/dist/gateway/static/root/assets/{schedule-field-TkqUL3wm.js → schedule-field-Bcdni4Pj.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schema-form-DC-iU5IG.js → schema-form-D7oCARF7.js} +1 -1
  64. package/dist/gateway/static/root/assets/sessions-page-C5014a53.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-advanced-gate-CDY3ZI1K.js +1 -0
  66. package/dist/gateway/static/root/assets/{settings-collapsible-section-Dpqth3oA.js → settings-collapsible-section-6eNF8Jey.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-form-section-CNqF6IwY.js → settings-form-section-CARTHCxH.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DkvwitK_.js → settings-loading-skeleton-DEwYqESe.js} +1 -1
  69. package/dist/gateway/static/root/assets/settings-page-B6vVdHeQ.js +1 -0
  70. package/dist/gateway/static/root/assets/{settings-page-layout-DWvNgISx.js → settings-page-layout-D3srt5Bi.js} +1 -1
  71. package/dist/gateway/static/root/assets/setup-status-panel-z-rF0Hdg.js +1 -0
  72. package/dist/gateway/static/root/assets/{share-preview-page-DGpSPW-n.js → share-preview-page-Ck9SxiXw.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-CHZFXE_d.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-B7p2QNXt.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-ncw3tX9P.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-8TxxSbUw.js → system-settings-panel-DLBUQSk2.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-B5FzMWOx.js → theme-store-C1oaqeD2.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-DEGtSA5h.js → typed-models-lib-Divbg_C4.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-channel-catalog-BDU6FneG.js → use-channel-catalog-CP9a_rAf.js} +1 -1
  80. package/dist/gateway/static/root/assets/user-context-page-iYfeSLKI.js +1 -0
  81. package/dist/gateway/static/root/assets/voice-api-key-field-CrwkicvT.js +1 -0
  82. package/dist/gateway/static/root/assets/work-discovery-page-BQWxyPg8.js +1 -0
  83. package/dist/gateway/static/root/assets/work-item-detail-page-50ZzGay5.js +1 -0
  84. package/dist/gateway/static/root/assets/work-page-DPqEahx7.js +1 -0
  85. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cwi8Pz7n.js → workflow-run-setup-panel-DbDPYQwB.js} +2 -2
  86. package/dist/gateway/static/root/assets/workflows-page-C3eIC5HZ.js +11 -0
  87. package/dist/gateway/static/root/index.html +7 -7
  88. package/dist/package.js +1 -1
  89. package/dist/src/agent/agent-manager.d.ts +1 -0
  90. package/dist/src/agent/agent-manager.js +1 -0
  91. package/dist/src/agent/client-error-format.js +3 -3
  92. package/dist/src/agent/outcomes/task-evaluation.d.ts +20 -0
  93. package/dist/src/agent/outcomes/task-evaluation.js +48 -0
  94. package/dist/src/agent/outcomes/task-verifier.d.ts +29 -0
  95. package/dist/src/agent/outcomes/task-verifier.js +71 -0
  96. package/dist/src/agent/prompt/memory/index.js +1 -1
  97. package/dist/src/agent/prompt/service-prompt-builder.js +32 -1
  98. package/dist/src/agent/service.js +1 -0
  99. package/dist/src/agent/service.types.d.ts +1 -0
  100. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +1 -7
  101. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +2 -73
  102. package/dist/src/agent/tools/browser/tool/schemas.d.ts +1 -13
  103. package/dist/src/agent/tools/browser/tool/schemas.js +1 -9
  104. package/dist/src/agent/tools/browser-recipe-tool.d.ts +12 -0
  105. package/dist/src/agent/tools/browser-recipe-tool.js +113 -0
  106. package/dist/src/agent/tools/factory.d.ts +2 -0
  107. package/dist/src/agent/tools/factory.js +2 -0
  108. package/dist/src/agent/tools/index.d.ts +1 -0
  109. package/dist/src/agent/tools/index.js +2 -1
  110. package/dist/src/automations/domain/types.d.ts +13 -0
  111. package/dist/src/automations/domain/validation.d.ts +44 -24
  112. package/dist/src/automations/domain/validation.js +27 -18
  113. package/dist/src/automations/draft/automation-draft-validator.d.ts +6 -1
  114. package/dist/src/automations/draft/automation-draft-validator.js +1 -0
  115. package/dist/src/automations/service/action-executor.d.ts +1 -0
  116. package/dist/src/automations/service/action-executor.js +22 -0
  117. package/dist/src/browser/index.d.ts +0 -1
  118. package/dist/src/browser/index.js +1 -2
  119. package/dist/src/browser/pipeline/runner.d.ts +9 -2
  120. package/dist/src/browser/pipeline/runner.js +151 -105
  121. package/dist/src/browser/pipeline/schema.d.ts +21 -15
  122. package/dist/src/browser/pipeline/schema.js +93 -99
  123. package/dist/src/browser/recipes/index.d.ts +3 -0
  124. package/dist/src/browser/recipes/index.js +3 -0
  125. package/dist/src/browser/recipes/repository.d.ts +13 -0
  126. package/dist/src/browser/recipes/repository.js +81 -0
  127. package/dist/src/browser/recipes/runtime-service.d.ts +6 -0
  128. package/dist/src/browser/recipes/runtime-service.js +30 -0
  129. package/dist/src/browser/recipes/service.d.ts +36 -0
  130. package/dist/src/browser/recipes/service.js +186 -0
  131. package/dist/src/browser/recipes/types.d.ts +36 -0
  132. package/dist/src/browser/recipes/types.js +1 -0
  133. package/dist/src/cli/commands/browser-cli-helpers.js +6 -12
  134. package/dist/src/cli/commands/browser.js +4 -3
  135. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  136. package/dist/src/config/agent-profile.js +1 -1
  137. package/dist/src/config/schema.d.ts +3 -3
  138. package/dist/src/config/schema.js +21 -21
  139. package/dist/src/gateway/agents-admin.js +1 -1
  140. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
  141. package/dist/src/gateway/hono/routes/browser-workflows.d.ts +3 -0
  142. package/dist/src/gateway/hono/routes/browser-workflows.js +78 -0
  143. package/dist/src/gateway/hono/routes/home.js +1 -0
  144. package/dist/src/gateway/hono/routes/index.js +4 -0
  145. package/dist/src/gateway/hono/routes/interaction-state.d.ts +3 -0
  146. package/dist/src/gateway/hono/routes/interaction-state.js +45 -0
  147. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  148. package/dist/src/gateway/hono/routes/memory.js +33 -4
  149. package/dist/src/gateway/hono/routes/task-outcomes.d.ts +3 -0
  150. package/dist/src/gateway/hono/routes/task-outcomes.js +109 -0
  151. package/dist/src/gateway/hono/routes/you.d.ts +10 -2
  152. package/dist/src/gateway/hono/routes/you.js +184 -28
  153. package/dist/src/gateway/service/run-gateway-agent.js +84 -0
  154. package/dist/src/gateway/service.d.ts +3 -0
  155. package/dist/src/gateway/service.js +14 -0
  156. package/dist/src/proactive/insight-repository.d.ts +2 -0
  157. package/dist/src/proactive/insight-repository.js +5 -2
  158. package/dist/src/proactive/run-processor.js +22 -1
  159. package/dist/src/proactive/types.d.ts +2 -0
  160. package/dist/src/proactive/value-score.d.ts +13 -0
  161. package/dist/src/proactive/value-score.js +30 -0
  162. package/dist/src/share/share-types.js +5 -5
  163. package/dist/src/share/site-share-types.d.ts +1 -1
  164. package/dist/src/share/site-share-types.js +5 -5
  165. package/dist/src/storage/sqlite/index.d.ts +3 -0
  166. package/dist/src/storage/sqlite/index.js +4 -1
  167. package/dist/src/storage/sqlite/interaction-state-repository.d.ts +17 -0
  168. package/dist/src/storage/sqlite/interaction-state-repository.js +60 -0
  169. package/dist/src/storage/sqlite/memory-records-repository.js +1 -1
  170. package/dist/src/storage/sqlite/migrations/053_browser_recipes.sql +45 -0
  171. package/dist/src/storage/sqlite/migrations/054_task_outcomes.sql +24 -0
  172. package/dist/src/storage/sqlite/migrations/055_relationship_settings.sql +14 -0
  173. package/dist/src/storage/sqlite/migrations/056_task_verification.sql +6 -0
  174. package/dist/src/storage/sqlite/migrations/057_interaction_states.sql +11 -0
  175. package/dist/src/storage/sqlite/migrations/058_proactive_value.sql +3 -0
  176. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  177. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  178. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  179. package/dist/src/storage/sqlite/relationship-settings-repository.d.ts +17 -0
  180. package/dist/src/storage/sqlite/relationship-settings-repository.js +64 -0
  181. package/dist/src/storage/sqlite/schema.js +1 -1
  182. package/dist/src/storage/sqlite/schema.sql +46 -0
  183. package/dist/src/storage/sqlite/task-outcome-repository.d.ts +90 -0
  184. package/dist/src/storage/sqlite/task-outcome-repository.js +138 -0
  185. package/dist/src/user-context/interaction-state.d.ts +13 -0
  186. package/dist/src/user-context/interaction-state.js +69 -0
  187. package/dist/src/user-context/memory-use-audit.d.ts +10 -0
  188. package/dist/src/user-context/memory-use-audit.js +25 -0
  189. package/dist/src/user-context/personal-playbook.d.ts +11 -0
  190. package/dist/src/user-context/personal-playbook.js +41 -0
  191. package/dist/src/user-context/projection.d.ts +4 -0
  192. package/dist/src/user-context/projection.js +5 -1
  193. package/dist/src/user-context/relationship-continuity.d.ts +14 -0
  194. package/dist/src/user-context/relationship-continuity.js +51 -0
  195. package/package.json +1 -1
  196. package/dist/gateway/static/root/assets/action-boundary-settings-panel-BIVBUiNT.js +0 -1
  197. package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +0 -2
  198. package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +0 -1
  199. package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +0 -6
  200. package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +0 -8
  201. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dva9SiPK.js +0 -2
  202. package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +0 -1
  203. package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +0 -1
  204. package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +0 -2
  205. package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +0 -1
  206. package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +0 -1
  207. package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +0 -4
  208. package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +0 -2
  209. package/dist/gateway/static/root/assets/index-CkUHH170.css +0 -1
  210. package/dist/gateway/static/root/assets/index-vq_cJZJC.js +0 -199
  211. package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +0 -2
  212. package/dist/gateway/static/root/assets/messages-CxySDn9d.js +0 -5
  213. package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +0 -2
  214. package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +0 -4
  215. package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +0 -1
  216. package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +0 -1
  217. package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +0 -1
  218. package/dist/gateway/static/root/assets/save-bar-controls-CkeKasGm.js +0 -1
  219. package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +0 -1
  220. package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +0 -1
  221. package/dist/gateway/static/root/assets/settings-page-qPG7I2zd.js +0 -1
  222. package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +0 -1
  223. package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +0 -1
  224. package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +0 -1
  225. package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +0 -2
  226. package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +0 -1
  227. package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +0 -1
  228. package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +0 -1
  229. package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +0 -1
  230. package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +0 -1
  231. package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +0 -11
  232. package/dist/src/browser/pipeline/source.d.ts +0 -9
  233. package/dist/src/browser/pipeline/source.js +0 -77
@@ -1,4 +1,5 @@
1
1
  import { runSqliteWriteTransaction } from "../../../storage/sqlite/transaction.js";
2
+ import { getRelationshipSettings, updateRelationshipSettings } from "../../../storage/sqlite/relationship-settings-repository.js";
2
3
  import { deleteMemoryRecord, getMemoryRecord, listMemoryRecords, upsertMemoryRecord } from "../../../storage/sqlite/memory-records-repository.js";
3
4
  import { listKnowledgeSourceItems, listKnowledgeSyncRuns } from "../../../storage/sqlite/knowledge-repository.js";
4
5
  import { getConnectorConnection, listConnectorConnections } from "../../../storage/sqlite/connector-repository.js";
@@ -15,6 +16,7 @@ import "../../../goals/index.js";
15
16
  import { revokeComposioConnection } from "../../../connectors/composio.js";
16
17
  import { listConnectorCatalog } from "../../../connectors/catalog.js";
17
18
  import { nextMemoryReviewAt, resolveMemoryStability } from "../../../agent/memory/lifecycle.js";
19
+ import { PERSONAL_PLAYBOOK_DISABLED_TAG, PERSONAL_PLAYBOOK_ORDER_PREFIX, PERSONAL_PLAYBOOK_RULE_TAG, patchPersonalPlaybookContextTags, personalPlaybookContext } from "../../../user-context/personal-playbook.js";
18
20
  import { listConnectorInstances } from "../../../connectors/instances.js";
19
21
  import { uninstallConnector } from "../../../connectors/install.js";
20
22
  import { readUserProfileFile, writeUserProfileFile } from "../../agents-admin.js";
@@ -44,8 +46,13 @@ const PLAYBOOK_IDS = [
44
46
  "execution",
45
47
  "routines"
46
48
  ];
47
- const PLAYBOOK_DISABLED_TAG = "playbook:disabled";
48
- const PLAYBOOK_ORDER_PREFIX = "playbook:order:";
49
+ const PLAYBOOK_SUPPORT_NEEDS = new Set([
50
+ "listen",
51
+ "clarify",
52
+ "advise",
53
+ "act",
54
+ "unknown"
55
+ ]);
49
56
  const PROFILE_FIELD_LIMITS = {
50
57
  callName: 80,
51
58
  pronouns: 80,
@@ -154,34 +161,57 @@ function parseProfilePatch(body) {
154
161
  return Object.keys(patch).length > 0 ? { patch } : { error: "No profile fields provided" };
155
162
  }
156
163
  function playbookForRecord(record) {
164
+ if (!record.tags?.includes("playbook:rule")) return void 0;
157
165
  if (record.kind === "preference" || record.kind === "boundary" || record.kind === "tool_preference") return "communication";
158
166
  if (record.kind === "task_lesson" || record.kind === "derived_insight") return "execution";
159
167
  if (record.kind === "routine") return "routines";
160
168
  }
161
169
  function playbookRuleOrder(record) {
162
- const tag = record.tags?.find((value) => value.startsWith(PLAYBOOK_ORDER_PREFIX));
163
- const parsed = tag ? Number.parseInt(tag.slice(15), 10) : NaN;
170
+ const tag = record.tags?.find((value) => value.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
171
+ const parsed = tag ? Number.parseInt(tag.slice(PERSONAL_PLAYBOOK_ORDER_PREFIX.length), 10) : NaN;
164
172
  return Number.isFinite(parsed) ? parsed : 1e3;
165
173
  }
166
174
  function patchPlaybookRuleTags(record, patch) {
167
- let tags = (record.tags ?? []).filter((tag) => !tag.startsWith(PLAYBOOK_ORDER_PREFIX));
168
- if (patch.enabled === true) tags = tags.filter((tag) => tag !== PLAYBOOK_DISABLED_TAG);
169
- if (patch.enabled === false) tags.push(PLAYBOOK_DISABLED_TAG);
170
- if (patch.order !== void 0) tags.push(`${PLAYBOOK_ORDER_PREFIX}${patch.order}`);
175
+ let tags = (record.tags ?? []).filter((tag) => !tag.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
176
+ if (patch.enabled === true) tags = tags.filter((tag) => tag !== PERSONAL_PLAYBOOK_DISABLED_TAG);
177
+ if (patch.enabled === false) tags.push(PERSONAL_PLAYBOOK_DISABLED_TAG);
178
+ if (patch.order !== void 0) tags.push(`${PERSONAL_PLAYBOOK_ORDER_PREFIX}${patch.order}`);
171
179
  return [...new Set(tags)];
172
180
  }
181
+ function parsePlaybookContext(value) {
182
+ if (value === void 0) return { context: {} };
183
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { error: "context must be an object" };
184
+ const input = value;
185
+ const context = {};
186
+ if ("channel" in input) {
187
+ if (input.channel !== null && (typeof input.channel !== "string" || !/^[a-z0-9_-]{1,40}$/i.test(input.channel))) return { error: "context.channel is invalid" };
188
+ context.channel = input.channel === null ? void 0 : String(input.channel);
189
+ }
190
+ if ("supportNeed" in input) {
191
+ if (input.supportNeed !== null && !PLAYBOOK_SUPPORT_NEEDS.has(String(input.supportNeed))) return { error: "context.supportNeed is invalid" };
192
+ context.supportNeed = input.supportNeed === null ? void 0 : input.supportNeed;
193
+ }
194
+ return { context };
195
+ }
173
196
  function buildPersonalPlaybooks(records) {
174
197
  return PLAYBOOK_IDS.map((id) => {
175
- const rules = records.filter((record) => playbookForRecord(record) === id).sort((left, right) => playbookRuleOrder(left) - playbookRuleOrder(right) || left.updatedAt.localeCompare(right.updatedAt));
198
+ const rules = records.filter((record) => record.status === "active" && playbookForRecord(record) === id).sort((left, right) => playbookRuleOrder(left) - playbookRuleOrder(right) || left.updatedAt.localeCompare(right.updatedAt));
176
199
  return {
177
200
  id,
178
- enabled: rules.some((record) => !record.tags?.includes(PLAYBOOK_DISABLED_TAG)),
201
+ enabled: rules.some((record) => !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG)),
179
202
  rules: rules.map((record) => ({
180
203
  id: record.id,
181
204
  statement: record.content,
182
205
  origin: record.explicitness,
183
- enabled: !record.tags?.includes(PLAYBOOK_DISABLED_TAG),
184
- order: playbookRuleOrder(record)
206
+ enabled: !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG),
207
+ order: playbookRuleOrder(record),
208
+ context: personalPlaybookContext(record),
209
+ versions: playbookVersionChain(records, record.id).map((version) => ({
210
+ id: version.id,
211
+ statement: version.content,
212
+ updatedAt: version.updatedAt,
213
+ current: version.id === record.id
214
+ }))
185
215
  })),
186
216
  updatedAt: rules.map((record) => record.updatedAt).sort().at(-1)
187
217
  };
@@ -195,7 +225,7 @@ function buildInsightSuggestions(records) {
195
225
  id: record.id,
196
226
  insight: record.content,
197
227
  kind: record.kind,
198
- action: record.kind === "routine" ? "make_repeatable" : "start_progress",
228
+ action: record.kind === "routine" ? "make_repeatable" : record.kind === "task_lesson" || record.kind === "derived_insight" ? "add_playbook" : "start_progress",
199
229
  evidenceCount: record.evidence?.length ?? 0,
200
230
  confidence: record.confidence,
201
231
  sourceName: record.source.provider ?? "local"
@@ -216,11 +246,11 @@ function editableRecord(recordId) {
216
246
  if (!record || !VISIBLE_STATUSES.has(record.status) || !isUserContextRecord(record)) return null;
217
247
  return record;
218
248
  }
219
- function preserveRecord(record, patch) {
220
- return upsertMemoryRecord({
221
- id: record.id,
249
+ function memoryRecordInput(record) {
250
+ return {
222
251
  providerId: record.source.provider ?? "local",
223
252
  kind: record.kind,
253
+ userId: record.scope.userId,
224
254
  sourceAgentId: record.provenance.sourceAgentId,
225
255
  workspaceId: record.scope.workspaceId,
226
256
  sessionKey: record.scope.sessionKey,
@@ -242,8 +272,41 @@ function preserveRecord(record, patch) {
242
272
  validFrom: record.validFrom,
243
273
  validTo: record.validTo,
244
274
  supersedesRecordId: record.supersedesRecordId,
245
- conflictGroupId: record.conflictGroupId,
246
- ...patch
275
+ conflictGroupId: record.conflictGroupId
276
+ };
277
+ }
278
+ function preserveRecord(record, patch) {
279
+ return upsertMemoryRecord({
280
+ ...memoryRecordInput(record),
281
+ ...patch,
282
+ id: record.id
283
+ });
284
+ }
285
+ function playbookVersionChain(records, recordId) {
286
+ const relatedIds = new Set([recordId]);
287
+ let previousSize = 0;
288
+ while (previousSize !== relatedIds.size) {
289
+ previousSize = relatedIds.size;
290
+ for (const record of records) {
291
+ if (!record.supersedesRecordId) continue;
292
+ if (relatedIds.has(record.id) || relatedIds.has(record.supersedesRecordId)) {
293
+ relatedIds.add(record.id);
294
+ relatedIds.add(record.supersedesRecordId);
295
+ }
296
+ }
297
+ }
298
+ return records.filter((record) => relatedIds.has(record.id) && playbookForRecord(record) !== void 0).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt));
299
+ }
300
+ function versionPlaybookRule(record, patch) {
301
+ return upsertMemoryRecord({
302
+ ...memoryRecordInput(record),
303
+ ...patch,
304
+ status: "active",
305
+ supersedesRecordId: record.id,
306
+ source: {
307
+ provider: "local",
308
+ path: "you://playbook/version"
309
+ }
247
310
  });
248
311
  }
249
312
  function registerYouRoutes(authenticated, deps) {
@@ -291,13 +354,14 @@ function registerYouRoutes(authenticated, deps) {
291
354
  }),
292
355
  conflictGroups: buildConflictGroups(allUserContextRecords),
293
356
  insights: buildInsightSuggestions(records),
294
- playbooks: buildPersonalPlaybooks(records.filter((record) => record.status === "active")),
357
+ playbooks: buildPersonalPlaybooks(allUserContextRecords),
295
358
  sources,
296
359
  sourceRecommendations: buildGoalSourceRecommendations(sourceDefinitions.filter((definition) => definition.capabilities.includes("context") || definition.capabilities.includes("memory_source")), new Set(sourceInstances.map((instance) => instance.connectorId)), activeGoals),
297
360
  controls: {
298
361
  mode: config.userContext.memory.mode,
299
362
  sensitiveWritePolicy: config.userContext.privacy.sensitiveWritePolicy
300
363
  },
364
+ relationship: getRelationshipSettings(),
301
365
  trust: {
302
366
  defaultActionLevel: trustPolicy.defaultActionLevel,
303
367
  levels: USER_TRUST_LEVELS,
@@ -305,6 +369,41 @@ function registerYouRoutes(authenticated, deps) {
305
369
  }
306
370
  });
307
371
  });
372
+ authenticated.patch("/api/you/relationship", deps.strictRateLimitMiddleware, async (c) => {
373
+ const body = await c.req.json().catch(() => null);
374
+ if (!body || typeof body !== "object" || Array.isArray(body)) return c.json({ error: "Invalid relationship settings" }, 400);
375
+ const input = body;
376
+ const patch = {};
377
+ if ("supportMode" in input) {
378
+ if (![
379
+ "efficient",
380
+ "coach",
381
+ "companion",
382
+ "auto"
383
+ ].includes(String(input.supportMode))) return c.json({ error: "Invalid supportMode" }, 400);
384
+ patch.supportMode = input.supportMode;
385
+ }
386
+ if ("proactiveEnabled" in input) {
387
+ if (typeof input.proactiveEnabled !== "boolean") return c.json({ error: "proactiveEnabled must be boolean" }, 400);
388
+ patch.proactiveEnabled = input.proactiveEnabled;
389
+ }
390
+ for (const field of ["quietStart", "quietEnd"]) {
391
+ if (!(field in input)) continue;
392
+ const value = input[field];
393
+ if (value !== null && (typeof value !== "string" || !/^([01]\d|2[0-3]):[0-5]\d$/.test(value))) return c.json({ error: `${field} must use HH:mm` }, 400);
394
+ patch[field] = value === null ? void 0 : String(value);
395
+ }
396
+ for (const field of ["allowedTopics", "blockedTopics"]) {
397
+ if (!(field in input)) continue;
398
+ if (!Array.isArray(input[field]) || input[field].length > 20 || input[field].some((value) => typeof value !== "string" || !value.trim() || value.length > 80)) return c.json({ error: `${field} must contain up to 20 short topics` }, 400);
399
+ patch[field] = [...new Set(input[field].map((value) => value.trim()))];
400
+ }
401
+ if (Object.keys(patch).length === 0) return c.json({ error: "No relationship settings provided" }, 400);
402
+ return c.json({
403
+ ok: true,
404
+ relationship: updateRelationshipSettings(patch)
405
+ });
406
+ });
308
407
  authenticated.get("/api/you/profile", async (c) => {
309
408
  return c.json(await readProfileBundle(deps.service.currentConfig));
310
409
  });
@@ -523,7 +622,7 @@ function registerYouRoutes(authenticated, deps) {
523
622
  limit: 500
524
623
  }).filter(isUserContextRecord).filter((record) => playbookForRecord(record) === id);
525
624
  runSqliteWriteTransaction(() => {
526
- for (const record of active) preserveRecord(record, { tags: patchPlaybookRuleTags(record, { enabled }) });
625
+ for (const record of active) versionPlaybookRule(record, { tags: patchPlaybookRuleTags(record, { enabled }) });
527
626
  });
528
627
  const current = active.map((record) => ({
529
628
  ...record,
@@ -540,6 +639,8 @@ function registerYouRoutes(authenticated, deps) {
540
639
  const body = await c.req.json().catch(() => ({}));
541
640
  const statement = typeof body.statement === "string" ? body.statement.trim() : "";
542
641
  if (!statement || statement.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
642
+ const parsedContext = parsePlaybookContext(body.context);
643
+ if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
543
644
  const record = upsertMemoryRecord({
544
645
  providerId: "local",
545
646
  kind: id === "communication" ? "preference" : id === "execution" ? "task_lesson" : "routine",
@@ -550,11 +651,11 @@ function registerYouRoutes(authenticated, deps) {
550
651
  path: "you://playbook"
551
652
  },
552
653
  confidence: 1,
553
- tags: [
654
+ tags: patchPersonalPlaybookContextTags([
554
655
  "user-understanding",
555
- "playbook:explicit",
556
- `${PLAYBOOK_ORDER_PREFIX}${Number.isInteger(body.order) ? body.order : 1e3}`
557
- ],
656
+ PERSONAL_PLAYBOOK_RULE_TAG,
657
+ `${PERSONAL_PLAYBOOK_ORDER_PREFIX}${Number.isInteger(body.order) ? body.order : 1e3}`
658
+ ], parsedContext.context),
558
659
  status: "active",
559
660
  sensitivity: "normal",
560
661
  explicitness: "explicit",
@@ -576,12 +677,14 @@ function registerYouRoutes(authenticated, deps) {
576
677
  if (!content || content.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
577
678
  if (body.enabled !== void 0 && typeof body.enabled !== "boolean") return c.json({ error: "enabled must be boolean" }, 400);
578
679
  if (body.order !== void 0 && (!Number.isInteger(body.order) || body.order < 0 || body.order > 1e4)) return c.json({ error: "order must be an integer between 0 and 10000" }, 400);
579
- const updated = preserveRecord(record, {
680
+ const parsedContext = parsePlaybookContext(body.context);
681
+ if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
682
+ const updated = versionPlaybookRule(record, {
580
683
  content,
581
- tags: patchPlaybookRuleTags(record, {
684
+ tags: patchPersonalPlaybookContextTags(patchPlaybookRuleTags(record, {
582
685
  enabled: body.enabled,
583
686
  order: body.order
584
- }),
687
+ }), parsedContext.context),
585
688
  explicitness: body.statement === void 0 ? record.explicitness : "explicit"
586
689
  });
587
690
  return c.json({
@@ -593,9 +696,32 @@ function registerYouRoutes(authenticated, deps) {
593
696
  const id = c.req.param("id");
594
697
  const record = editableRecord(c.req.param("recordId"));
595
698
  if (!PLAYBOOK_IDS.includes(id) || !record || playbookForRecord(record) !== id) return c.json({ error: "Playbook rule not found" }, 404);
596
- deleteMemoryRecord(record.id);
699
+ preserveRecord(record, {
700
+ status: "archived",
701
+ validTo: (/* @__PURE__ */ new Date()).toISOString()
702
+ });
597
703
  return c.json({ ok: true });
598
704
  });
705
+ authenticated.post("/api/you/playbooks/:id/rules/:recordId/rollback", deps.strictRateLimitMiddleware, async (c) => {
706
+ const id = c.req.param("id");
707
+ const current = editableRecord(c.req.param("recordId"));
708
+ if (!PLAYBOOK_IDS.includes(id) || !current || playbookForRecord(current) !== id) return c.json({ error: "Playbook rule not found" }, 404);
709
+ const body = await c.req.json().catch(() => ({}));
710
+ const versionId = typeof body.versionId === "string" ? body.versionId : "";
711
+ const all = listAllUserContextRecords(ALL_MEMORY_STATUSES);
712
+ const target = playbookVersionChain(all, current.id).find((record) => record.id === versionId);
713
+ if (!target || target.id === current.id) return c.json({ error: "Previous version not found" }, 404);
714
+ const rolledBack = versionPlaybookRule(current, {
715
+ content: target.content,
716
+ tags: target.tags,
717
+ evidence: target.evidence,
718
+ explicitness: "explicit"
719
+ });
720
+ return c.json({
721
+ ok: true,
722
+ rule: buildPersonalPlaybooks([...all, rolledBack]).find((playbook) => playbook.id === id)?.rules.find((rule) => rule.id === rolledBack.id)
723
+ });
724
+ });
599
725
  authenticated.patch("/api/you/insights/:id", deps.strictRateLimitMiddleware, async (c) => {
600
726
  const config = deps.service.currentConfig;
601
727
  const existing = editableRecord(c.req.param("id"));
@@ -622,6 +748,36 @@ function registerYouRoutes(authenticated, deps) {
622
748
  status: "drafting",
623
749
  href: buildRoutineAutomationDraftHref(existing)
624
750
  });
751
+ if (existing.kind === "task_lesson" || existing.kind === "derived_insight") {
752
+ upsertMemoryRecord({
753
+ providerId: "local",
754
+ kind: "task_lesson",
755
+ sourceAgentId: selectedAgentId(config),
756
+ content: existing.content,
757
+ source: {
758
+ provider: "local",
759
+ path: "you://insight-proposal"
760
+ },
761
+ confidence: 1,
762
+ tags: [
763
+ "user-understanding",
764
+ PERSONAL_PLAYBOOK_RULE_TAG,
765
+ `${PERSONAL_PLAYBOOK_ORDER_PREFIX}1000`
766
+ ],
767
+ status: "active",
768
+ sensitivity: existing.sensitivity,
769
+ explicitness: "explicit",
770
+ durability: "durable",
771
+ importance: existing.importance,
772
+ disclosurePolicy: existing.disclosurePolicy,
773
+ evidence: existing.evidence
774
+ });
775
+ preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_ACCEPTED_TAG])] });
776
+ return c.json({
777
+ ok: true,
778
+ status: "saved"
779
+ });
780
+ }
625
781
  const title = existing.content.trim().split(/\r?\n/)[0].slice(0, 72);
626
782
  const uiLocale = body.uiLocale === "zh" ? "zh" : "en";
627
783
  const contractDraft = await draftGoalContract({
@@ -1,6 +1,11 @@
1
1
  import { inboundCorrelationMetadataFromAsyncLogContext, updateAsyncLogContext } from "../../utils/logger/context.js";
2
2
  import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
+ import { updateInteractionStateFromMessage } from "../../storage/sqlite/interaction-state-repository.js";
5
+ import { completeTaskOutcome, startTaskOutcome, updateTaskOutcome } from "../../storage/sqlite/task-outcome-repository.js";
6
+ import "../../storage/sqlite/index.js";
7
+ import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
8
+ import { recordExplicitRelationshipFollowUp } from "../../user-context/relationship-continuity.js";
4
9
  import { formatAgentRunErrorForClient } from "../../agent/client-error-format.js";
5
10
  import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
6
11
  import { shouldSkipWebchatInboundByAbortCutoff } from "../../session/abort-cutoff.js";
@@ -11,6 +16,7 @@ import { coalesceThinkingDeltas } from "../chat-stream/thinking-delta-coalescer.
11
16
  import crypto from "crypto";
12
17
  //#region src/gateway/service/run-gateway-agent.ts
13
18
  init_logger();
19
+ init_session_key();
14
20
  const log = createLogger("Gateway:Service");
15
21
  /**
16
22
  * @param runOptions.signal — When set (e.g. client disconnect), aborts in-flight generation and persists partial output.
@@ -24,6 +30,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
24
30
  const runId = crypto.randomUUID();
25
31
  const { agentService, bus, runRelay, runAbortControllers, activeWebchatRunBySession, sessionIndex: sessionIndexFromDeps, emit } = deps;
26
32
  const sessionIndex = sessionIndexFromDeps;
33
+ let taskOutcomeStarted = false;
34
+ let taskOutcomeStatus = "failed";
35
+ let taskOutcomeSummary = "Agent run ended unexpectedly";
36
+ let taskContract;
37
+ const taskEvidence = [];
27
38
  let webchatSessionKey;
28
39
  let webchatSessionId;
29
40
  let webchatStaleSkip = false;
@@ -40,15 +51,65 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
40
51
  runAbortControllers.set(runId, new AbortController());
41
52
  }
42
53
  const streamSessionKey = webchatSessionKey ?? chatId;
54
+ if (webchatSessionKey) {
55
+ const parsedSession = parseSessionKey(webchatSessionKey);
56
+ if (!parsedSession) throw new Error("Resolved webchat session key is invalid");
57
+ updateInteractionStateFromMessage({
58
+ sessionKey: webchatSessionKey,
59
+ message
60
+ });
61
+ recordExplicitRelationshipFollowUp({
62
+ sessionKey: webchatSessionKey,
63
+ sourceAgentId: parsedSession.agentId,
64
+ message
65
+ });
66
+ startTaskOutcome({
67
+ runId,
68
+ sessionKey: webchatSessionKey,
69
+ channel,
70
+ objective: message.trim()
71
+ });
72
+ taskOutcomeStarted = true;
73
+ }
43
74
  const mapper = new ChatStreamMapper({
44
75
  runId,
45
76
  sessionKey: streamSessionKey,
46
77
  channel
47
78
  });
48
79
  let registeredActiveWebchatRun = false;
80
+ const addTaskEvidence = (evidence) => {
81
+ if (taskEvidence.some((item) => item.kind === evidence.kind && item.title === evidence.title)) return;
82
+ taskEvidence.push(evidence);
83
+ };
84
+ const captureTaskEvent = (event) => {
85
+ if (event.type === "turn_plan") {
86
+ taskContract = {
87
+ objective: message.trim(),
88
+ deliverables: [],
89
+ acceptanceCriteria: event.payload.plan.map((item) => item.step),
90
+ constraints: [],
91
+ approvalRequired: []
92
+ };
93
+ return;
94
+ }
95
+ if (event.type === "patch_applied") {
96
+ addTaskEvidence({
97
+ kind: "state",
98
+ title: "Changes applied",
99
+ summary: `${event.payload.added} additions and ${event.payload.removed} removals`
100
+ });
101
+ return;
102
+ }
103
+ if (event.type === "command_completed" && event.payload.exitCode === 0 && /(^|\s)(test|vitest|jest|pytest|lint|typecheck|build)(\s|$|:)/i.test(event.payload.command)) addTaskEvidence({
104
+ kind: "test",
105
+ title: event.payload.command.slice(0, 120),
106
+ summary: event.payload.durationMs === void 0 ? "Command completed successfully" : `Command completed successfully in ${event.payload.durationMs} ms`
107
+ });
108
+ };
49
109
  const publishStreamEvent = (event) => channel === "webchat" ? runRelay.publish(runId, event) ?? event : event;
50
110
  const emitAndYield = function* (events) {
51
111
  for (const event of events) {
112
+ if (taskOutcomeStarted) captureTaskEvent(event);
52
113
  const relayedEvent = publishStreamEvent(event);
53
114
  if (channel === "webchat") emit("agent.stream", {
54
115
  sessionKey: streamSessionKey,
@@ -61,6 +122,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
61
122
  try {
62
123
  if (channel === "webchat" && webchatSessionKey) {
63
124
  if (webchatStaleSkip) {
125
+ taskOutcomeStatus = "cancelled";
126
+ taskOutcomeSummary = "Stale inbound message skipped";
64
127
  yield* emitAndYield(mapper.end("cancelled", "Stale inbound after abort (clientCreatedAtMs before cutoff)"));
65
128
  runRelay.complete(runId);
66
129
  runAbortControllers.delete(runId);
@@ -97,6 +160,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
97
160
  for await (const event of coalesceThinkingDeltas(mappedEvents)) yield* emitAndYield([event]);
98
161
  const endStatus = mergedSignal.aborted ? "cancelled" : "success";
99
162
  const endSummary = mergedSignal.aborted ? "Interrupted" : "Message processed successfully";
163
+ taskOutcomeStatus = mergedSignal.aborted ? "cancelled" : "succeeded";
164
+ taskOutcomeSummary = endSummary;
100
165
  yield* emitAndYield(mapper.end(endStatus, endSummary));
101
166
  runRelay.complete(runId);
102
167
  try {
@@ -121,6 +186,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
121
186
  channel: "webchat"
122
187
  }, `Agent processing failed: ${em}`);
123
188
  streamError = em;
189
+ taskOutcomeStatus = "failed";
190
+ taskOutcomeSummary = em;
124
191
  const errorContent = formatAgentRunErrorForClient(streamError);
125
192
  yield* emitAndYield(mapper.error(errorContent));
126
193
  yield* emitAndYield(mapper.end("error", streamError));
@@ -198,12 +265,16 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
198
265
  payload: { messageId }
199
266
  }]);
200
267
  yield* emitAndYield(mapper.end("success", "Message processed"));
268
+ taskOutcomeStatus = "succeeded";
269
+ taskOutcomeSummary = "Message processed";
201
270
  return {
202
271
  status: "ok",
203
272
  summary: "Message processed"
204
273
  };
205
274
  } catch (error) {
206
275
  const em = error instanceof Error ? error.message : String(error);
276
+ taskOutcomeStatus = "failed";
277
+ taskOutcomeSummary = em;
207
278
  log.error({
208
279
  err: error,
209
280
  errorMessage: em,
@@ -213,6 +284,19 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
213
284
  chatId
214
285
  }, `Agent run failed: ${em}`);
215
286
  throw error;
287
+ } finally {
288
+ if (taskOutcomeStarted) {
289
+ updateTaskOutcome({
290
+ runId,
291
+ ...taskContract ? { contract: taskContract } : {},
292
+ evidence: taskEvidence
293
+ });
294
+ completeTaskOutcome({
295
+ runId,
296
+ status: taskOutcomeStatus,
297
+ summary: taskOutcomeSummary
298
+ });
299
+ }
216
300
  }
217
301
  }
218
302
  //#endregion
@@ -11,6 +11,7 @@ import { AgentRunRelay } from './agent-run-relay.js';
11
11
  import { type EnqueueGoalRunOptions } from '../goals/index.js';
12
12
  import { ProjectService } from '../projects/index.js';
13
13
  import { LocalAppService } from '../local-apps/index.js';
14
+ import { type BrowserRecipeService } from '../browser/recipes/index.js';
14
15
  import { GatewaySessionsApi } from './service/sessions-api.js';
15
16
  import { GatewayMarketplaceService } from './service/marketplace-service.js';
16
17
  import { GatewayAgentRunner } from './service/agent-runner.js';
@@ -26,6 +27,7 @@ export declare class GatewayService {
26
27
  private _agentService;
27
28
  private channelManager;
28
29
  private automationService;
30
+ private browserRecipeService;
29
31
  private notesService;
30
32
  private extensionLoader;
31
33
  private extensionMetadataSnapshot;
@@ -42,6 +44,7 @@ export declare class GatewayService {
42
44
  private auth;
43
45
  private readonly sse;
44
46
  getConfig(): Config;
47
+ get browserRecipes(): BrowserRecipeService;
45
48
  private stopGatewayUpdateCheck;
46
49
  /** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */
47
50
  private gatewayShutdownForRestart;
@@ -78,6 +78,8 @@ import { runBootstrapMigrationsSync } from "../migrations/runner.js";
78
78
  import { MobileNotificationService } from "../mobile/notification-service.js";
79
79
  import { LocalAppService } from "../local-apps/service.js";
80
80
  import "../local-apps/index.js";
81
+ import { createRuntimeBrowserRecipeService } from "../browser/recipes/runtime-service.js";
82
+ import "../browser/recipes/index.js";
81
83
  import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
82
84
  import { resolveChannelConnectDeferSet } from "./resolve-channel-connect-defer.js";
83
85
  import { restartGatewayProcessWithFreshPid } from "./respawn.js";
@@ -108,6 +110,7 @@ var GatewayService = class {
108
110
  _agentService = null;
109
111
  channelManager;
110
112
  automationService;
113
+ browserRecipeService = null;
111
114
  notesService;
112
115
  extensionLoader = null;
113
116
  extensionMetadataSnapshot = null;
@@ -126,6 +129,13 @@ var GatewayService = class {
126
129
  getConfig() {
127
130
  return this.config;
128
131
  }
132
+ get browserRecipes() {
133
+ if (!this.browserRecipeService) this.browserRecipeService = createRuntimeBrowserRecipeService({
134
+ getConfig: () => this.config,
135
+ emit: (type, payload) => this.emit(type, payload)
136
+ });
137
+ return this.browserRecipeService;
138
+ }
129
139
  stopGatewayUpdateCheck = null;
130
140
  /** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */
131
141
  gatewayShutdownForRestart = null;
@@ -322,6 +332,7 @@ var GatewayService = class {
322
332
  },
323
333
  extensionRegistry: this.extensionLoader?.getRegistry(),
324
334
  getAutomationService: () => this.automationService,
335
+ getBrowserRecipeService: () => this.browserRecipes,
325
336
  getNotesService: () => this.notesService,
326
337
  getProjectService: () => this.projects,
327
338
  getWorkItemService: () => new WorkItemService(),
@@ -361,6 +372,7 @@ var GatewayService = class {
361
372
  getDefaultAgentId: () => getDefaultAgentId(this.config),
362
373
  getProjectWorkspaceRoot: (projectId) => this.projects.get(projectId)?.workspaceRoot,
363
374
  workflowRunService: this.createWorkflowRunService(),
375
+ browserRecipeService: this.browserRecipes,
364
376
  onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
365
377
  });
366
378
  this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {
@@ -671,6 +683,7 @@ var GatewayService = class {
671
683
  agentService: this.agentService,
672
684
  getDefaultAgentId: () => getDefaultAgentId(this.config),
673
685
  workflowRunService: this.createWorkflowRunService(),
686
+ browserRecipeService: this.browserRecipes,
674
687
  onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
675
688
  });
676
689
  this.startAutomationProductEventBridge();
@@ -822,6 +835,7 @@ var GatewayService = class {
822
835
  this.connectorMemorySyncCoordinator = null;
823
836
  this.connectedKnowledgeCoordinator?.stop();
824
837
  this.connectedKnowledgeCoordinator = null;
838
+ await this.browserRecipeService?.shutdown();
825
839
  if (this.browserExtensionRelease) {
826
840
  await this.browserExtensionRelease();
827
841
  this.browserExtensionRelease = null;
@@ -13,6 +13,8 @@ export declare function createProactiveInsight(input: {
13
13
  whyItMatters: string;
14
14
  nextAction: string;
15
15
  evidence: ProactiveEvidence[];
16
+ valueScore: number;
17
+ valueReasons: string[];
16
18
  nowMs?: number;
17
19
  }): ProactiveInsight | null;
18
20
  export declare function setProactiveInsightStatus(id: string, status: ProactiveInsightStatus, nowMs?: number, expectedStatus?: ProactiveInsightStatus): ProactiveInsight | null;
@@ -14,6 +14,8 @@ function insightFromRow(row) {
14
14
  nextAction: row.next_action,
15
15
  evidence: JSON.parse(row.evidence_json),
16
16
  status: row.status,
17
+ valueScore: row.value_score,
18
+ valueReasons: JSON.parse(row.value_reasons_json),
17
19
  createdAt: row.created_at,
18
20
  updatedAt: row.updated_at
19
21
  };
@@ -58,8 +60,9 @@ function createProactiveInsight(input) {
58
60
  runSqliteWriteTransaction((db) => {
59
61
  created = db.prepare(`INSERT OR IGNORE INTO proactive_insights (
60
62
  insight_id, watch_id, run_id, kind, title, summary, why_it_matters,
61
- next_action, evidence_json, content_hash, status, created_at, updated_at
62
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?)`).run(id, input.watchId, input.runId, input.kind, input.title, input.summary, input.whyItMatters, input.nextAction, JSON.stringify(input.evidence), contentHash, now, now).changes > 0;
63
+ next_action, evidence_json, content_hash, status, value_score,
64
+ value_reasons_json, created_at, updated_at
65
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?, ?, ?)`).run(id, input.watchId, input.runId, input.kind, input.title, input.summary, input.whyItMatters, input.nextAction, JSON.stringify(input.evidence), contentHash, input.valueScore, JSON.stringify(input.valueReasons), now, now).changes > 0;
63
66
  });
64
67
  return created ? listProactiveInsights({ limit: 100 }).find((item) => item.id === id) ?? null : null;
65
68
  }
@@ -1,7 +1,10 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { getRelationshipSettings, isProactiveSupportAllowed } from "../storage/sqlite/relationship-settings-repository.js";
4
+ import "../storage/sqlite/index.js";
3
5
  import { getFocusWatchByAutomationId, recordFocusWatchRun } from "./watch-repository.js";
4
- import { createProactiveInsight } from "./insight-repository.js";
6
+ import { createProactiveInsight, listProactiveInsights } from "./insight-repository.js";
7
+ import { scoreProactiveValue } from "./value-score.js";
5
8
  //#region src/proactive/run-processor.ts
6
9
  init_logger();
7
10
  const log = createLogger("ProactiveRunProcessor");
@@ -105,6 +108,22 @@ function processFocusAutomationRun(run) {
105
108
  nowMs: run.endedAtMs
106
109
  })) return { handled: true };
107
110
  if (!result.meaningful) return { handled: true };
111
+ if (!isProactiveSupportAllowed(getRelationshipSettings(), {
112
+ now: new Date(run.endedAtMs),
113
+ topic: watch.kind
114
+ })) return { handled: true };
115
+ const history = listProactiveInsights({
116
+ status: ["approved", "dismissed"],
117
+ limit: 50
118
+ });
119
+ const value = scoreProactiveValue({
120
+ kind: watch.kind,
121
+ evidenceCount: result.evidence.length,
122
+ hasNextAction: Boolean(result.nextAction),
123
+ approvedCount: history.filter((item) => item.status === "approved").length,
124
+ dismissedCount: history.filter((item) => item.status === "dismissed").length
125
+ });
126
+ if (!value.shouldDeliver) return { handled: true };
108
127
  const insight = createProactiveInsight({
109
128
  watchId: watch.id,
110
129
  runId: run.id,
@@ -114,6 +133,8 @@ function processFocusAutomationRun(run) {
114
133
  whyItMatters: result.whyItMatters,
115
134
  nextAction: result.nextAction,
116
135
  evidence: result.evidence,
136
+ valueScore: value.score,
137
+ valueReasons: value.reasons,
117
138
  nowMs: run.endedAtMs
118
139
  });
119
140
  return insight ? {
@@ -49,6 +49,8 @@ export interface ProactiveInsight {
49
49
  whyItMatters: string;
50
50
  nextAction: string;
51
51
  evidence: ProactiveEvidence[];
52
+ valueScore: number;
53
+ valueReasons: string[];
52
54
  status: ProactiveInsightStatus;
53
55
  createdAt: number;
54
56
  updatedAt: number;