@xopcai/xopc 0.0.188 → 0.0.190

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 (490) hide show
  1. package/README.md +1 -4
  2. package/README.zh-CN.md +0 -3
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store--QoUGhiS.js → activity-store-DstnJCS5.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B0yweLNQ.js → agent-avatar-dicebear-9vAbkroX.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-D1t4SfMQ.js +68 -0
  8. package/dist/gateway/static/root/assets/{api-5laWqfiE.js → api-BTL9kayv.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-BXJ8Jiv_.js → app-management-settings-panel-DkFeIdBf.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-DG9n9D1M.js → appearance-settings-Bxs8Fpaj.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-Cgrgu5OW.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-Ceh5qrZf.js → archive-plugin-Ch2RmLCC.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-jFW7uYf7.js → attachment-load-BhMQM_Ky.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-CtJxstKh.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-XDlkI1r4.js → binary-plugins-D6CqlymH.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-kyKc2IhE.js → block-editor-ClL6HEg9.js} +56 -56
  17. package/dist/gateway/static/root/assets/browser-settings-page-DW99iDmD.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-BJa5Iz_v.js → browser-workflow-inputs-BYy48VhN.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-CTQQOsn5.js → browser-workflows-page-zgLibuMH.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-CHUrT9EB.js +7 -0
  21. package/dist/gateway/static/root/assets/capability-presets-api-BB8t4Ja7.js +1 -0
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Cycrv0YV.js +1 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-BgIkWq01.js → channel-recipient-api-BThDGiO3.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-V96gPUAU.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-Cz7SAAkm.js +1 -0
  26. package/dist/gateway/static/root/assets/connectors-api-DS9ED-EL.js +1 -0
  27. package/dist/gateway/static/root/assets/connectors-page-BhlyQoQI.js +2 -0
  28. package/dist/gateway/static/root/assets/cron-expression-CkgsvhtW.js +2 -0
  29. package/dist/gateway/static/root/assets/{desktop-pet-CSwd00CV.js → desktop-pet-Cv8rGhYW.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-CuNQvHGu.js → desktop-pet-settings-CIeJdwfV.js} +1 -1
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-ct0n5Rje.js → directory-picker-path-field-D8jXEiAY.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-debug-page-BeRBuMUU.js → extension-debug-page-CCZ9u6TZ.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-page-DbK-Cwao.js → extension-page-CV36ILRG.js} +1 -1
  34. package/dist/gateway/static/root/assets/extension-settings-page-IyQrSILY.js +1 -0
  35. package/dist/gateway/static/root/assets/{gateway-config-api-CC7EvEFp.js → gateway-config-api-D4_r5iJM.js} +1 -1
  36. package/dist/gateway/static/root/assets/gateway-settings-CYlntpBH.js +1 -0
  37. package/dist/gateway/static/root/assets/{gateway-startup-retry-B2DmdlwO.js → gateway-startup-retry-EO9mKvzE.js} +1 -1
  38. package/dist/gateway/static/root/assets/heartbeat-settings-D4SyWob8.js +1 -0
  39. package/dist/gateway/static/root/assets/home-page-B2Kagoh8.js +3 -0
  40. package/dist/gateway/static/root/assets/{image-generation-api-GMTaS6eI.js → image-generation-api-Bu7PyVSh.js} +1 -1
  41. package/dist/gateway/static/root/assets/index-CYT5DOzr.js +150 -0
  42. package/dist/gateway/static/root/assets/index-D6e3tPL-.css +1 -0
  43. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DhGYddbI.js → keyboard-shortcuts-settings-BMhCuVBZ.js} +1 -1
  44. package/dist/gateway/static/root/assets/local-app-workbench-page-BHYbFjqy.js +2 -0
  45. package/dist/gateway/static/root/assets/{local-apps-page-CmnrBmWi.js → local-apps-page-ijIe7_y2.js} +1 -1
  46. package/dist/gateway/static/root/assets/locale-store-deR2zRaE.js +1 -0
  47. package/dist/gateway/static/root/assets/logs-page-IIn8Tess.js +2 -0
  48. package/dist/gateway/static/root/assets/management-settings--V_fovKD.js +1 -0
  49. package/dist/gateway/static/root/assets/{markdown-split-CZaBPOVn.js → markdown-split-Dt9-in6W.js} +1 -1
  50. package/dist/gateway/static/root/assets/{media-plugins-CiKvSgCv.js → media-plugins-B3pj_iO0.js} +1 -1
  51. package/dist/gateway/static/root/assets/messages-B4XqB8I6.js +3 -0
  52. package/dist/gateway/static/root/assets/{notes-page-Bisbzqlz.js → notes-page-DZ366lIT.js} +1 -1
  53. package/dist/gateway/static/root/assets/notes-workbench-S2sBVOLw.js +4 -0
  54. package/dist/gateway/static/root/assets/{page-tabs-BxlwhAbH.js → page-tabs-C5ge434C.js} +1 -1
  55. package/dist/gateway/static/root/assets/{preview-open-alternatives-RM8wXxfT.js → preview-open-alternatives-BFa9DgSV.js} +1 -1
  56. package/dist/gateway/static/root/assets/product-delivery-tRr-7IxY.js +1 -0
  57. package/dist/gateway/static/root/assets/{product-open-page-DdBlibek.js → product-open-page-Dc9CcWdu.js} +1 -1
  58. package/dist/gateway/static/root/assets/project-detail-page-BilzoCJ7.js +1 -0
  59. package/dist/gateway/static/root/assets/projects-page-BoQUyacP.js +1 -0
  60. package/dist/gateway/static/root/assets/remote-access-hub-DUyUaCRF.js +1 -0
  61. package/dist/gateway/static/root/assets/{schema-form-BDKbpmXv.js → schema-form-B84DckWe.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schemas-C6onAggk.js → schemas-zIBW3wiV.js} +1 -1
  63. package/dist/gateway/static/root/assets/sessions-page-Dzxlq1F0.js +1 -0
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-TzwlZxU6.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-form-section-Dp9itvdy.js +1 -0
  66. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DgIp8_S6.js → settings-loading-skeleton-CCtlhoy7.js} +1 -1
  67. package/dist/gateway/static/root/assets/settings-page-DQmMKf8r.js +1 -0
  68. package/dist/gateway/static/root/assets/{settings-page-layout-97LmwrzC.js → settings-page-layout-EQIOJa_L.js} +1 -1
  69. package/dist/gateway/static/root/assets/setup-status-panel-Cwi-SPja.js +1 -0
  70. package/dist/gateway/static/root/assets/{share-preview-page-BH7i3g1S.js → share-preview-page-C4_B2jvf.js} +1 -1
  71. package/dist/gateway/static/root/assets/shares-settings-CkyuGlZK.js +1 -0
  72. package/dist/gateway/static/root/assets/skill-reload-api-BJCePQK5.js +1 -0
  73. package/dist/gateway/static/root/assets/skills-page-BYWLfmJi.js +2 -0
  74. package/dist/gateway/static/root/assets/{skills-page.utils-s-a5WV9j.js → skills-page.utils-Jhm24i4h.js} +1 -1
  75. package/dist/gateway/static/root/assets/{system-settings-panel-BxjeMT5k.js → system-settings-panel-Dpx2ags2.js} +1 -1
  76. package/dist/gateway/static/root/assets/{task-detail-page-BahycnfW.js → task-detail-page-DLAdxI6e.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-BRxdsmic.js → theme-store-DnBOcGXi.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-39MjwPSq.js → typed-models-lib-DULmTHUB.js} +1 -1
  79. package/dist/gateway/static/root/assets/use-autosave-BrjVk5VH.js +1 -0
  80. package/dist/gateway/static/root/assets/user-context-page-9AAFpGAL.js +1 -0
  81. package/dist/gateway/static/root/assets/{voice-api-key-field-XU-7sBSg.js → voice-api-key-field-BISTPfq_.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-CJqu8UHq.js → work-discovery-overlay-Wr-uF7VA.js} +1 -1
  83. package/dist/gateway/static/root/assets/work-discovery-page-BWds95sL.js +1 -0
  84. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DXtg8Qxl.js → workflow-run-setup-panel-DHqHP8_6.js} +2 -2
  85. package/dist/gateway/static/root/assets/workflows-page-0b4_DFHr.js +11 -0
  86. package/dist/gateway/static/root/index.html +9 -9
  87. package/dist/package.js +1 -1
  88. package/dist/packages/endpoint-tools-protocol/src/index.js +184 -0
  89. package/dist/packages/gateway-contract/src/tool-activity.js +0 -36
  90. package/dist/packages/realtime-client/src/index.js +256 -0
  91. package/dist/packages/realtime-protocol/src/index.js +88 -0
  92. package/dist/src/agent/agent-manager.d.ts +1 -1
  93. package/dist/src/agent/agent-manager.js +7 -13
  94. package/dist/src/agent/background-review/coordinator.js +1 -1
  95. package/dist/src/agent/background-review/prompts.d.ts +1 -1
  96. package/dist/src/agent/background-review/prompts.js +3 -1
  97. package/dist/src/agent/background-review/run-background-review.d.ts +2 -0
  98. package/dist/src/agent/background-review/run-background-review.js +10 -9
  99. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +0 -1
  100. package/dist/src/agent/bootstrap/bootstrap-cache.js +3 -4
  101. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +0 -4
  102. package/dist/src/agent/bootstrap/bootstrap-files.js +3 -4
  103. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -4
  104. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +0 -1
  105. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -14
  106. package/dist/src/agent/bootstrap/types.d.ts +1 -1
  107. package/dist/src/agent/client-error-format.d.ts +1 -1
  108. package/dist/src/agent/client-error-format.js +1 -1
  109. package/dist/src/agent/context/workspace-templates/SOUL.md +1 -1
  110. package/dist/src/agent/external-tools/endpoint-provider.d.ts +17 -0
  111. package/dist/src/agent/external-tools/endpoint-provider.js +93 -0
  112. package/dist/src/agent/external-tools/gateway-tools.js +1 -1
  113. package/dist/src/agent/external-tools/index.d.ts +4 -5
  114. package/dist/src/agent/external-tools/index.js +8 -2
  115. package/dist/src/agent/external-tools/types.d.ts +8 -1
  116. package/dist/src/agent/external-tools/types.js +2 -1
  117. package/dist/src/agent/inbound/inbound-loop.js +4 -0
  118. package/dist/src/agent/inbound/turn-dispatcher.d.ts +9 -8
  119. package/dist/src/agent/inbound/turn-dispatcher.js +13 -11
  120. package/dist/src/agent/memory/builtin-provider.d.ts +2 -4
  121. package/dist/src/agent/memory/builtin-provider.js +35 -15
  122. package/dist/src/agent/memory/context/types.d.ts +3 -1
  123. package/dist/src/agent/memory/create-memory-manager.js +2 -0
  124. package/dist/src/agent/memory/index.d.ts +1 -1
  125. package/dist/src/agent/memory/index.js +1 -1
  126. package/dist/src/agent/memory/manager.d.ts +9 -1
  127. package/dist/src/agent/memory/manager.js +39 -9
  128. package/dist/src/agent/memory/memory-config.d.ts +1 -1
  129. package/dist/src/agent/memory/memory-config.js +1 -1
  130. package/dist/src/agent/memory/source-origin.js +0 -2
  131. package/dist/src/agent/memory/types.d.ts +5 -1
  132. package/dist/src/agent/memory/understanding/service.d.ts +10 -10
  133. package/dist/src/agent/memory/understanding/service.js +108 -176
  134. package/dist/src/agent/memory/understanding/types.d.ts +7 -8
  135. package/dist/src/agent/memory/user-context-coordinator.d.ts +2 -1
  136. package/dist/src/agent/memory/user-context-coordinator.js +27 -41
  137. package/dist/src/agent/messaging/command-handler.d.ts +2 -2
  138. package/dist/src/agent/messaging/command-handler.js +3 -3
  139. package/dist/src/agent/orchestration/agent-orchestrator.js +4 -7
  140. package/dist/src/agent/prompt/sections/memory-skills.js +4 -4
  141. package/dist/src/agent/prompt/sections/tooling.js +0 -10
  142. package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
  143. package/dist/src/agent/prompt/service-prompt-builder.js +4 -33
  144. package/dist/src/agent/prompt/system-prompt.js +1 -2
  145. package/dist/src/agent/service/async-queue.d.ts +1 -1
  146. package/dist/src/agent/service/async-queue.js +1 -1
  147. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -1
  148. package/dist/src/agent/service/direct-turn-helpers.js +2 -2
  149. package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -1
  150. package/dist/src/agent/service/process-direct-one-shot.js +1 -1
  151. package/dist/src/agent/service/process-direct-streaming.d.ts +7 -5
  152. package/dist/src/agent/service/process-direct-streaming.js +5 -5
  153. package/dist/src/agent/service.d.ts +2 -3
  154. package/dist/src/agent/service.js +10 -21
  155. package/dist/src/agent/service.types.d.ts +2 -0
  156. package/dist/src/agent/session/index.d.ts +1 -1
  157. package/dist/src/agent/session/session-context.d.ts +2 -0
  158. package/dist/src/agent/session/session-context.js +4 -0
  159. package/dist/src/agent/session/session-state-bag.d.ts +4 -4
  160. package/dist/src/agent/session/session-state-bag.js +1 -1
  161. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +1 -1
  162. package/dist/src/agent/streaming/reasoning-visibility.d.ts +6 -0
  163. package/dist/src/agent/streaming/{reasoning-visibility-sse.js → reasoning-visibility.js} +3 -6
  164. package/dist/src/agent/tools/dreaming-tool.d.ts +0 -2
  165. package/dist/src/agent/tools/dreaming-tool.js +13 -38
  166. package/dist/src/agent/tools/factory.d.ts +4 -3
  167. package/dist/src/agent/tools/factory.js +2 -10
  168. package/dist/src/agent/tools/index.d.ts +0 -1
  169. package/dist/src/agent/tools/index.js +1 -2
  170. package/dist/src/agent/tools/memory-tool.js +1 -1
  171. package/dist/src/agent/workspace-runtime/registry.d.ts +3 -5
  172. package/dist/src/agent/workspace-runtime/registry.js +2 -15
  173. package/dist/src/agent-manifest/schema.d.ts +17 -17
  174. package/dist/src/agent-runtime/index.js +1 -1
  175. package/dist/src/agent-runtime/memory-runtime.d.ts +2 -2
  176. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  177. package/dist/src/automations/domain/types.d.ts +2 -1
  178. package/dist/src/automations/domain/validation.d.ts +29 -29
  179. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  180. package/dist/src/automations/service/action-executor.js +4 -1
  181. package/dist/src/channels/pairing/pairing-challenge.d.ts +1 -1
  182. package/dist/src/channels/pairing/pairing-challenge.js +1 -1
  183. package/dist/src/chat-commands/builtins/understanding.js +2 -5
  184. package/dist/src/cli/commands/agent/stream-renderer.js +4 -1
  185. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  186. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  187. package/dist/src/cli/commands/init.js +3 -22
  188. package/dist/src/cli/templates.js +1 -1
  189. package/dist/src/config/index.js +3 -3
  190. package/dist/src/config/paths.d.ts +0 -5
  191. package/dist/src/config/paths.js +2 -11
  192. package/dist/src/config/rules.js +0 -5
  193. package/dist/src/config/schema.d.ts +27 -122
  194. package/dist/src/config/schema.js +9 -42
  195. package/dist/src/config/web-patch.js +0 -1
  196. package/dist/src/connectors/learning-coordinator.js +75 -3
  197. package/dist/src/endpoint-tools/auth.d.ts +20 -0
  198. package/dist/src/endpoint-tools/auth.js +51 -0
  199. package/dist/src/endpoint-tools/index.d.ts +5 -0
  200. package/dist/src/endpoint-tools/index.js +6 -0
  201. package/dist/src/endpoint-tools/invocation-service.d.ts +68 -0
  202. package/dist/src/endpoint-tools/invocation-service.js +190 -0
  203. package/dist/src/endpoint-tools/policy.d.ts +10 -0
  204. package/dist/src/endpoint-tools/policy.js +18 -0
  205. package/dist/src/endpoint-tools/registry.d.ts +45 -0
  206. package/dist/src/endpoint-tools/registry.js +121 -0
  207. package/dist/src/endpoint-tools/runtime.d.ts +23 -0
  208. package/dist/src/endpoint-tools/runtime.js +86 -0
  209. package/dist/src/endpoint-tools/upload-service.d.ts +41 -0
  210. package/dist/src/endpoint-tools/upload-service.js +103 -0
  211. package/dist/src/extensions/types/hooks.d.ts +1 -1
  212. package/dist/src/extensions/update.js +1 -1
  213. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  214. package/dist/src/gateway/agent-builtin-tools.js +0 -5
  215. package/dist/src/gateway/agents-admin.d.ts +0 -7
  216. package/dist/src/gateway/agents-admin.js +3 -32
  217. package/dist/src/gateway/chat-stream/protocol.d.ts +0 -1
  218. package/dist/src/gateway/clarify-bridge.d.ts +5 -4
  219. package/dist/src/gateway/clarify-bridge.js +3 -4
  220. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +3 -3
  221. package/dist/src/gateway/dreaming-automation-reconciler.js +48 -88
  222. package/dist/src/gateway/heartbeat/service.js +4 -1
  223. package/dist/src/gateway/hono/app.js +1 -5
  224. package/dist/src/gateway/hono/index.d.ts +0 -1
  225. package/dist/src/gateway/hono/index.js +1 -2
  226. package/dist/src/gateway/hono/lib/config-payload.d.ts +20 -9
  227. package/dist/src/gateway/hono/lib/config-payload.js +3 -2
  228. package/dist/src/gateway/hono/middleware/auth.js +3 -5
  229. package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
  230. package/dist/src/gateway/hono/oauth-async.js +17 -2
  231. package/dist/src/gateway/hono/routes/agent-stream.js +49 -6
  232. package/dist/src/gateway/hono/routes/agents.js +1 -33
  233. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  234. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +2 -2
  235. package/dist/src/gateway/hono/routes/config-patch/gateway.js +0 -19
  236. package/dist/src/gateway/hono/routes/config-patch/misc.js +17 -1
  237. package/dist/src/gateway/hono/routes/connectors.js +13 -12
  238. package/dist/src/gateway/hono/routes/deps.d.ts +0 -2
  239. package/dist/src/gateway/hono/routes/endpoint-tools.d.ts +3 -0
  240. package/dist/src/gateway/hono/routes/endpoint-tools.js +196 -0
  241. package/dist/src/gateway/hono/routes/index.js +6 -2
  242. package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -5
  243. package/dist/src/gateway/hono/routes/logs.js +0 -4
  244. package/dist/src/gateway/hono/routes/public-gateway.js +2 -2
  245. package/dist/src/gateway/hono/routes/realtime.d.ts +3 -0
  246. package/dist/src/gateway/hono/routes/realtime.js +35 -0
  247. package/dist/src/gateway/hono/routes/status.js +0 -7
  248. package/dist/src/gateway/hono/routes/understanding-sources.d.ts +3 -0
  249. package/dist/src/gateway/hono/routes/understanding-sources.js +203 -0
  250. package/dist/src/gateway/hono/routes/work-discovery.d.ts +2 -0
  251. package/dist/src/gateway/hono/routes/work-discovery.js +3 -134
  252. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  253. package/dist/src/gateway/hono/routes/you.d.ts +0 -31
  254. package/dist/src/gateway/hono/routes/you.js +230 -1161
  255. package/dist/src/gateway/index.d.ts +1 -1
  256. package/dist/src/gateway/index.js +1 -2
  257. package/dist/src/gateway/protocol.d.ts +1 -7
  258. package/dist/src/gateway/security/index.js +1 -1
  259. package/dist/src/gateway/security/operator-scopes.js +1 -1
  260. package/dist/src/gateway/server.js +4 -4
  261. package/dist/src/gateway/service/agent-runner.d.ts +11 -9
  262. package/dist/src/gateway/service/agent-runner.js +18 -18
  263. package/dist/src/gateway/service/config-coordinator.d.ts +3 -3
  264. package/dist/src/gateway/service/run-gateway-agent.d.ts +4 -3
  265. package/dist/src/gateway/service/run-gateway-agent.js +15 -17
  266. package/dist/src/gateway/service/session-input-coordinator.d.ts +3 -0
  267. package/dist/src/gateway/service/session-input-coordinator.js +4 -2
  268. package/dist/src/gateway/service/types.d.ts +0 -5
  269. package/dist/src/gateway/service.d.ts +7 -6
  270. package/dist/src/gateway/service.js +43 -26
  271. package/dist/src/infra/update-runner.js +1 -1
  272. package/dist/src/knowledge/connected-knowledge-pipeline.js +1 -1
  273. package/dist/src/knowledge/connected-understanding-pipeline.d.ts +2 -4
  274. package/dist/src/knowledge/connected-understanding-pipeline.js +31 -81
  275. package/dist/src/knowledge/index.js +2 -2
  276. package/dist/src/knowledge/people-graph.d.ts +22 -25
  277. package/dist/src/knowledge/people-graph.js +76 -43
  278. package/dist/src/mcp/channel-bridge.d.ts +6 -9
  279. package/dist/src/mcp/channel-bridge.js +48 -76
  280. package/dist/src/mcp/channel-server.js +2 -6
  281. package/dist/src/proactive/execution/context.js +8 -13
  282. package/dist/src/realtime/broker.d.ts +31 -0
  283. package/dist/src/realtime/broker.js +114 -0
  284. package/dist/src/realtime/runtime.d.ts +20 -0
  285. package/dist/src/realtime/runtime.js +263 -0
  286. package/dist/src/realtime/tickets.d.ts +15 -0
  287. package/dist/src/realtime/tickets.js +38 -0
  288. package/dist/src/realtime/writer.d.ts +15 -0
  289. package/dist/src/realtime/writer.js +78 -0
  290. package/dist/src/share/share-config.js +0 -1
  291. package/dist/src/share/site-share-config.js +0 -1
  292. package/dist/src/storage/sqlite/connector-account-repository.js +0 -1
  293. package/dist/src/storage/sqlite/context-consolidation-repository.d.ts +37 -0
  294. package/dist/src/storage/sqlite/context-consolidation-repository.js +64 -0
  295. package/dist/src/storage/sqlite/endpoint-principal-repository.d.ts +17 -0
  296. package/dist/src/storage/sqlite/endpoint-principal-repository.js +54 -0
  297. package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.d.ts +25 -0
  298. package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.js +42 -0
  299. package/dist/src/storage/sqlite/fts.d.ts +2 -0
  300. package/dist/src/storage/sqlite/fts.js +29 -1
  301. package/dist/src/storage/sqlite/index.d.ts +6 -6
  302. package/dist/src/storage/sqlite/index.js +7 -7
  303. package/dist/src/storage/sqlite/knowledge-repository.d.ts +9 -2
  304. package/dist/src/storage/sqlite/knowledge-repository.js +58 -10
  305. package/dist/src/storage/sqlite/memory-records-repository.d.ts +7 -56
  306. package/dist/src/storage/sqlite/memory-records-repository.js +68 -218
  307. package/dist/src/storage/sqlite/migrations/109_endpoint_principals.sql +14 -0
  308. package/dist/src/storage/sqlite/migrations/110_session_input_origin.sql +43 -0
  309. package/dist/src/storage/sqlite/migrations/111_endpoint_tool_invocations.sql +18 -0
  310. package/dist/src/storage/sqlite/migrations/112_endpoint_instance_bindings.sql +8 -0
  311. package/dist/src/storage/sqlite/migrations/113_memory_evidence_single_source.sql +54 -0
  312. package/dist/src/storage/sqlite/migrations/114_user_context_domain.sql +193 -0
  313. package/dist/src/storage/sqlite/migrations/115_remove_legacy_user_context.sql +6 -0
  314. package/dist/src/storage/sqlite/migrations/116_structured_context_consolidation.sql +38 -0
  315. package/dist/src/storage/sqlite/migrations/117_unified_understanding_sources.sql +110 -0
  316. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  317. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  318. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  319. package/dist/src/storage/sqlite/schema.js +1 -1
  320. package/dist/src/storage/sqlite/schema.sql +0 -20
  321. package/dist/src/storage/sqlite/session-input-repository.d.ts +3 -0
  322. package/dist/src/storage/sqlite/session-input-repository.js +5 -3
  323. package/dist/src/storage/sqlite/user-context-quality-repository.d.ts +34 -0
  324. package/dist/src/storage/sqlite/user-context-quality-repository.js +74 -0
  325. package/dist/src/storage/sqlite/user-context-repository.d.ts +64 -0
  326. package/dist/src/storage/sqlite/user-context-repository.js +383 -0
  327. package/dist/src/tasks/home-query-service.d.ts +1 -1
  328. package/dist/src/tui/backends/embedded-backend.js +5 -2
  329. package/dist/src/tui/backends/{gateway-sse-backend.d.ts → gateway-realtime-backend.d.ts} +13 -10
  330. package/dist/src/tui/backends/{gateway-sse-backend.js → gateway-realtime-backend.js} +114 -151
  331. package/dist/src/tui/tool-summary.js +1 -7
  332. package/dist/src/tui/tui-agent-events.d.ts +0 -1
  333. package/dist/src/tui/tui-agent-events.js +2 -15
  334. package/dist/src/tui/tui-backend.d.ts +4 -4
  335. package/dist/src/tui/tui-run-state.js +0 -4
  336. package/dist/src/tui/tui-startup-resources.js +1 -2
  337. package/dist/src/tui/tui-types.d.ts +2 -9
  338. package/dist/src/tui/tui-types.js +0 -1
  339. package/dist/src/tui/tui.js +5 -5
  340. package/dist/src/tunnel/gateway-lifecycle.d.ts +1 -1
  341. package/dist/src/tunnel/gateway-lifecycle.js +1 -1
  342. package/dist/src/user-context/config.d.ts +17 -210
  343. package/dist/src/user-context/config.js +19 -85
  344. package/dist/src/user-context/consolidation.d.ts +26 -0
  345. package/dist/src/user-context/consolidation.js +115 -0
  346. package/dist/src/user-context/domain.d.ts +75 -0
  347. package/dist/src/user-context/domain.js +4 -0
  348. package/dist/src/user-context/manual-understanding.d.ts +7 -14
  349. package/dist/src/user-context/manual-understanding.js +19 -49
  350. package/dist/src/{agent/memory/context → user-context}/planner.d.ts +5 -6
  351. package/dist/src/user-context/planner.js +311 -0
  352. package/dist/src/user-context/relationship-continuity.d.ts +3 -6
  353. package/dist/src/user-context/relationship-continuity.js +39 -32
  354. package/dist/src/user-context/sources/catalog.d.ts +2 -0
  355. package/dist/src/user-context/sources/catalog.js +149 -0
  356. package/dist/src/user-context/sources/index.d.ts +3 -0
  357. package/dist/src/user-context/sources/index.js +3 -0
  358. package/dist/src/user-context/sources/repository.d.ts +40 -0
  359. package/dist/src/user-context/sources/repository.js +164 -0
  360. package/dist/src/user-context/sources/types.d.ts +83 -0
  361. package/dist/src/user-context/understandingQuality.d.ts +5 -0
  362. package/dist/src/user-context/understandingQuality.js +44 -0
  363. package/dist/src/utils/logger/log-stream.d.ts +3 -10
  364. package/dist/src/utils/logger/log-stream.js +2 -73
  365. package/dist/src/utils/logger/pino-record.d.ts +1 -1
  366. package/dist/src/utils/logger/streams.js +1 -1
  367. package/dist/src/work-discovery/analyzer.d.ts +4 -3
  368. package/dist/src/work-discovery/analyzer.js +21 -16
  369. package/dist/src/work-discovery/incremental-repository.js +42 -40
  370. package/dist/src/work-discovery/index.js +3 -3
  371. package/dist/src/work-discovery/service.d.ts +7 -7
  372. package/dist/src/work-discovery/service.js +241 -190
  373. package/dist/src/work-discovery/source-repository.js +42 -53
  374. package/dist/src/work-discovery/types.d.ts +2 -14
  375. package/package.json +5 -7
  376. package/dist/gateway/static/root/assets/agents-C6OV-gMm.js +0 -2
  377. package/dist/gateway/static/root/assets/apps-page-Ci14lDeO.js +0 -1
  378. package/dist/gateway/static/root/assets/automations-page-Q1xmb4Rh.js +0 -6
  379. package/dist/gateway/static/root/assets/browser-settings-page-DbowrHXD.js +0 -8
  380. package/dist/gateway/static/root/assets/capabilities-settings-panel-DoZPFdKF.js +0 -7
  381. package/dist/gateway/static/root/assets/capability-presets-api-Dn-7MMEo.js +0 -1
  382. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Bt8Hnx0h.js +0 -1
  383. package/dist/gateway/static/root/assets/channels-settings-Bpsebsru.js +0 -1
  384. package/dist/gateway/static/root/assets/channels-status-swr-DFmdYRE5.js +0 -1
  385. package/dist/gateway/static/root/assets/connector-logo-TRr9ybf6.js +0 -1
  386. package/dist/gateway/static/root/assets/connectors-page-Tg5kl22i.js +0 -2
  387. package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +0 -2
  388. package/dist/gateway/static/root/assets/extension-settings-page-C9ag5tb5.js +0 -1
  389. package/dist/gateway/static/root/assets/gateway-settings-9g8uIry9.js +0 -1
  390. package/dist/gateway/static/root/assets/heartbeat-settings-fl1oC_-5.js +0 -1
  391. package/dist/gateway/static/root/assets/home-page-Bao9jq_z.js +0 -3
  392. package/dist/gateway/static/root/assets/index-Cl5n1f_U.css +0 -1
  393. package/dist/gateway/static/root/assets/index-OJgiMh07.js +0 -223
  394. package/dist/gateway/static/root/assets/local-app-workbench-page-B69NvtvH.js +0 -2
  395. package/dist/gateway/static/root/assets/locale-store-D6hs74o5.js +0 -1
  396. package/dist/gateway/static/root/assets/logs-page-Cq3cABqg.js +0 -7
  397. package/dist/gateway/static/root/assets/messages-D02NNLCZ.js +0 -3
  398. package/dist/gateway/static/root/assets/notes-workbench-BOZfJFhE.js +0 -4
  399. package/dist/gateway/static/root/assets/product-delivery-C8JbSj5Y.js +0 -1
  400. package/dist/gateway/static/root/assets/project-detail-page-TSKFb2tN.js +0 -1
  401. package/dist/gateway/static/root/assets/projects-page-BokeBrTT.js +0 -1
  402. package/dist/gateway/static/root/assets/remote-access-hub-C56anxCX.js +0 -1
  403. package/dist/gateway/static/root/assets/segmented-styles-BL8oLBEp.js +0 -1
  404. package/dist/gateway/static/root/assets/sessions-page-C7TQADrD.js +0 -1
  405. package/dist/gateway/static/root/assets/settings-advanced-gate-BDOPKeAX.js +0 -1
  406. package/dist/gateway/static/root/assets/settings-form-section-zxo5ZGOu.js +0 -1
  407. package/dist/gateway/static/root/assets/settings-page-BUPSIa9P.js +0 -1
  408. package/dist/gateway/static/root/assets/setup-status-panel-BRg766eW.js +0 -1
  409. package/dist/gateway/static/root/assets/shares-settings-DhEAviQ_.js +0 -1
  410. package/dist/gateway/static/root/assets/skill-reload-api-Ct7AV8ls.js +0 -1
  411. package/dist/gateway/static/root/assets/skills-page-DoVuprZm.js +0 -2
  412. package/dist/gateway/static/root/assets/time-picker-BGk_Tbsj.js +0 -1
  413. package/dist/gateway/static/root/assets/use-save-bar-registration-5aVSjTjO.js +0 -1
  414. package/dist/gateway/static/root/assets/user-context-page-B9K41qmy.js +0 -1
  415. package/dist/gateway/static/root/assets/work-discovery-page-BBVnRHju.js +0 -1
  416. package/dist/gateway/static/root/assets/workflows-page-Bs_tYfst.js +0 -11
  417. package/dist/src/agent/code-intelligence/binary.d.ts +0 -15
  418. package/dist/src/agent/code-intelligence/binary.js +0 -372
  419. package/dist/src/agent/code-intelligence/index.d.ts +0 -4
  420. package/dist/src/agent/code-intelligence/index.js +0 -4
  421. package/dist/src/agent/code-intelligence/runtime.d.ts +0 -34
  422. package/dist/src/agent/code-intelligence/runtime.js +0 -280
  423. package/dist/src/agent/code-intelligence/tool-gating.d.ts +0 -5
  424. package/dist/src/agent/code-intelligence/tool-gating.js +0 -6
  425. package/dist/src/agent/code-intelligence/tools.d.ts +0 -6
  426. package/dist/src/agent/code-intelligence/tools.js +0 -266
  427. package/dist/src/agent/code-intelligence/types.d.ts +0 -22
  428. package/dist/src/agent/memory/context/planner.js +0 -286
  429. package/dist/src/agent/memory/dreaming/config.d.ts +0 -48
  430. package/dist/src/agent/memory/dreaming/config.js +0 -98
  431. package/dist/src/agent/memory/dreaming/constants.d.ts +0 -12
  432. package/dist/src/agent/memory/dreaming/constants.js +0 -18
  433. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +0 -19
  434. package/dist/src/agent/memory/dreaming/deep-promotion.js +0 -152
  435. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +0 -16
  436. package/dist/src/agent/memory/dreaming/light-sweep.js +0 -115
  437. package/dist/src/agent/memory/dreaming/preview.d.ts +0 -23
  438. package/dist/src/agent/memory/dreaming/preview.js +0 -52
  439. package/dist/src/agent/memory/dreaming/promotion-lifecycle.d.ts +0 -16
  440. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js +0 -44
  441. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +0 -19
  442. package/dist/src/agent/memory/dreaming/rem-patterns.js +0 -150
  443. package/dist/src/agent/memory/dreaming/runner.d.ts +0 -10
  444. package/dist/src/agent/memory/dreaming/runner.js +0 -78
  445. package/dist/src/agent/memory/dreaming/schedule.d.ts +0 -23
  446. package/dist/src/agent/memory/dreaming/schedule.js +0 -38
  447. package/dist/src/agent/memory/dreaming/scope.d.ts +0 -11
  448. package/dist/src/agent/memory/dreaming/scope.js +0 -33
  449. package/dist/src/agent/memory/dreaming/utils.d.ts +0 -3
  450. package/dist/src/agent/memory/dreaming/utils.js +0 -31
  451. package/dist/src/agent/streaming/reasoning-visibility-sse.d.ts +0 -15
  452. package/dist/src/gateway/agent-run-relay.d.ts +0 -19
  453. package/dist/src/gateway/agent-run-relay.js +0 -169
  454. package/dist/src/gateway/hono/routes/memory.d.ts +0 -3
  455. package/dist/src/gateway/hono/routes/memory.js +0 -460
  456. package/dist/src/gateway/hono/sse.d.ts +0 -53
  457. package/dist/src/gateway/hono/sse.js +0 -207
  458. package/dist/src/gateway/service/sse-hub.d.ts +0 -10
  459. package/dist/src/gateway/service/sse-hub.js +0 -53
  460. package/dist/src/storage/sqlite/dreaming-repository.d.ts +0 -61
  461. package/dist/src/storage/sqlite/dreaming-repository.js +0 -88
  462. package/dist/src/storage/sqlite/memory-readiness-repository.d.ts +0 -7
  463. package/dist/src/storage/sqlite/memory-readiness-repository.js +0 -30
  464. package/dist/src/storage/sqlite/memory-reference-consent-repository.d.ts +0 -27
  465. package/dist/src/storage/sqlite/memory-reference-consent-repository.js +0 -107
  466. package/dist/src/storage/sqlite/user-claims-repository.d.ts +0 -101
  467. package/dist/src/storage/sqlite/user-claims-repository.js +0 -241
  468. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +0 -3
  469. package/dist/src/storage/sqlite/user-profile-setup-repository.js +0 -32
  470. package/dist/src/tui/sse-consumer.d.ts +0 -15
  471. package/dist/src/tui/sse-consumer.js +0 -73
  472. package/dist/src/user-context/context-compiler.d.ts +0 -27
  473. package/dist/src/user-context/context-compiler.js +0 -48
  474. package/dist/src/user-context/import.d.ts +0 -12
  475. package/dist/src/user-context/import.js +0 -51
  476. package/dist/src/user-context/memory-episode-evaluator.d.ts +0 -32
  477. package/dist/src/user-context/memory-episode-evaluator.js +0 -35
  478. package/dist/src/user-context/memory-readiness.d.ts +0 -33
  479. package/dist/src/user-context/memory-readiness.js +0 -41
  480. package/dist/src/user-context/memory-use-audit.d.ts +0 -10
  481. package/dist/src/user-context/memory-use-audit.js +0 -26
  482. package/dist/src/user-context/personal-playbook.d.ts +0 -11
  483. package/dist/src/user-context/personal-playbook.js +0 -41
  484. package/dist/src/user-context/profile.d.ts +0 -37
  485. package/dist/src/user-context/profile.js +0 -163
  486. package/dist/src/user-context/projection.d.ts +0 -120
  487. package/dist/src/user-context/projection.js +0 -262
  488. package/dist/src/user-context/source-recommendations.d.ts +0 -13
  489. package/dist/src/user-context/source-recommendations.js +0 -85
  490. /package/dist/src/{agent/code-intelligence → user-context/sources}/types.js +0 -0
@@ -1,1214 +1,283 @@
1
- import { runSqliteWriteTransaction } from "../../../storage/sqlite/transaction.js";
2
- import { getDreamingRun, listDreamingDecisions, listDreamingRuns } from "../../../storage/sqlite/dreaming-repository.js";
3
- import { getUserClaim, linkUserClaimMemoryRecord, listUserClaimEvidence, listUserClaimStatsBySource, listUserClaims, removeUserClaimEvidenceForSource, setUserClaimDecision } from "../../../storage/sqlite/user-claims-repository.js";
4
- import { listConnectorLearningJobs } from "../../../storage/sqlite/connector-learning-repository.js";
5
- import { setInteractionState } from "../../../storage/sqlite/interaction-state-repository.js";
6
- import { getRelationshipSettings, updateRelationshipSettings } from "../../../storage/sqlite/relationship-settings-repository.js";
7
- import { deleteMemoryRecord, getMemoryRecord, getMemoryTurnFeedback, listMemoryRecords, listMemorySignals, setMemoryTurnFeedback, upsertMemoryRecord } from "../../../storage/sqlite/memory-records-repository.js";
8
- import { listKnowledgeSourceItems, listKnowledgeSyncRuns } from "../../../storage/sqlite/knowledge-repository.js";
9
- import { listConnectorConnections } from "../../../storage/sqlite/connector-repository.js";
10
- import { getConnectorAccount } from "../../../storage/sqlite/connector-account-repository.js";
11
- import { USER_TRUST_LEVELS, isUserTrustLevel } from "../../../user-context/trust-policy.js";
12
- import { getUserTrustPolicy, setUserTrustPolicy } from "../../../storage/sqlite/user-trust-repository.js";
13
- import { decideMemoryReferenceConsent, listMemoryReferenceConsents, revokeMemoryReferenceConsent } from "../../../storage/sqlite/memory-reference-consent-repository.js";
14
- import { getUserProfilePromptState, setUserProfilePromptState } from "../../../storage/sqlite/user-profile-setup-repository.js";
1
+ import { listContextConsolidationRuns } from "../../../storage/sqlite/context-consolidation-repository.js";
2
+ import { createCollaborationRule, createUnderstanding, decideContextConsent, deleteCollaborationRule, deleteUnderstanding, getCollaborationRule, getTurnPersonalization, getUnderstanding, getUserProfile, listCollaborationRules, listUnderstandingEvidence, listUnderstandings, recordContextFeedback, rejectUnderstanding, reviseCollaborationRule, reviseUnderstanding, setCollaborationRuleStatus, setUnderstandingStatus, updateUserProfile } from "../../../storage/sqlite/user-context-repository.js";
15
3
  import "../../../storage/sqlite/index.js";
16
- import { DreamingSettingsSchema, UserContextConfigSchema, init_config } from "../../../user-context/config.js";
17
- import { init_agent_scope, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
18
- import { TaskRepository } from "../../../tasks/task-repository.js";
19
- import { revokeComposioConnection } from "../../../connectors/composio.js";
20
- import { listConnectorCatalog } from "../../../connectors/catalog.js";
21
- import { nextDreamingRunTimes } from "../../../agent/memory/dreaming/schedule.js";
22
- import { resolveDreamingSettings } from "../../../agent/memory/dreaming/config.js";
23
- import { readUserProfileFile, writeUserProfileFile } from "../../agents-admin.js";
24
- import { TaskApplicationService } from "../../../tasks/task-application-service.js";
25
- import { defineTaskContract } from "../../../tasks/task-contract-definition.js";
26
- import "../../../tasks/index.js";
27
- import { nextMemoryReviewAt, resolveMemoryStability } from "../../../agent/memory/lifecycle.js";
28
- import { isUserContextMemoryKind, isUserContextRecord, projectPersonalContextSources, projectUserContextRecord, recordsDerivedFromPersonalContextSource } from "../../../user-context/projection.js";
29
- import { PERSONAL_PLAYBOOK_DISABLED_TAG, PERSONAL_PLAYBOOK_ORDER_PREFIX, PERSONAL_PLAYBOOK_RULE_TAG, patchPersonalPlaybookContextTags, personalPlaybookContext } from "../../../user-context/personal-playbook.js";
30
- import { createManualUnderstanding } from "../../../user-context/manual-understanding.js";
31
- import { resolveDreamingAgentScope } from "../../../agent/memory/dreaming/scope.js";
32
- import { runDreamingPhase } from "../../../agent/memory/dreaming/runner.js";
33
- import { listConnectorInstances } from "../../../connectors/instances.js";
34
- import { uninstallConnector } from "../../../connectors/install.js";
35
- import { renderUserClaim } from "../../../knowledge/connected-understanding-pipeline.js";
36
- import { prepareUserContextImport } from "../../../user-context/import.js";
37
- import { buildUserProfileSetup, parseUserProfileMarkdown, patchUserProfileMarkdown } from "../../../user-context/profile.js";
38
- import { buildTaskSourceRecommendations } from "../../../user-context/source-recommendations.js";
39
- import { randomUUID } from "node:crypto";
4
+ import { userInfo } from "node:os";
5
+ import { createHash } from "node:crypto";
40
6
  //#region src/gateway/hono/routes/you.ts
41
- init_agent_scope();
42
- init_config();
43
- const VISIBLE_STATUSES = new Set([
44
- "active",
45
- "candidate",
46
- "needs_review"
47
- ]);
48
- const FEEDBACK_RATINGS = new Set([
49
- "helpful",
50
- "not_helpful",
51
- "mixed",
52
- "irrelevant",
53
- "incorrect",
54
- "outdated",
55
- "sensitive"
56
- ]);
57
- const ACTIONABLE_INSIGHT_KINDS = new Set([
7
+ const UNDERSTANDING_KINDS = new Set([
8
+ "preference",
9
+ "boundary",
10
+ "relationship",
58
11
  "routine",
59
- "commitment",
12
+ "current_state",
60
13
  "long_term_goal",
61
- "derived_insight",
62
- "task_lesson"
63
- ]);
64
- const INSIGHT_ACCEPTED_TAG = "insight-action:accepted";
65
- const INSIGHT_DISMISSED_TAG = "insight-action:dismissed";
66
- const PLAYBOOK_IDS = [
67
- "communication",
68
- "execution",
69
- "routines"
70
- ];
71
- const PLAYBOOK_SUPPORT_NEEDS = new Set([
72
- "listen",
73
- "clarify",
74
- "advise",
75
- "act",
76
- "unknown"
14
+ "project_context",
15
+ "task_lesson",
16
+ "derived_insight"
77
17
  ]);
78
- const PROFILE_FIELD_LIMITS = {
79
- callName: 80,
80
- pronouns: 80,
81
- timezone: 100,
82
- notes: 5e3
83
- };
84
- const PROFILE_PROMPT_SNOOZE_MS = 10080 * 60 * 1e3;
85
- const ALL_MEMORY_STATUSES = [
18
+ const UNDERSTANDING_STATUSES = new Set([
86
19
  "candidate",
87
20
  "active",
88
21
  "needs_review",
89
22
  "stale",
90
23
  "archived",
91
24
  "rejected"
92
- ];
93
- const MEMORY_SENSITIVITIES = new Set([
94
- "normal",
95
- "personal",
96
- "secret",
97
- "regulated"
98
25
  ]);
99
- const MEMORY_DURABILITIES = new Set([
100
- "ephemeral",
101
- "durable",
102
- "recurring"
26
+ const RULE_CATEGORIES = new Set([
27
+ "communication",
28
+ "execution",
29
+ "boundary",
30
+ "routine",
31
+ "proactive"
103
32
  ]);
104
- const MEMORY_DISCLOSURE_POLICIES = new Set([
105
- "silent",
106
- "referenceable",
107
- "ask_before_reference"
33
+ const RULE_STATUSES = new Set([
34
+ "active",
35
+ "disabled",
36
+ "archived"
108
37
  ]);
109
- function listAllUserContextRecords(statuses) {
110
- return statuses.flatMap((status) => {
111
- const records = [];
112
- let offset = 0;
113
- while (true) {
114
- const page = listMemoryRecords({
115
- status,
116
- limit: 500,
117
- offset
118
- });
119
- records.push(...page);
120
- if (page.length < 500) break;
121
- offset += page.length;
122
- }
123
- return records;
124
- });
125
- }
126
- function projectReferenceConsent(consent, record) {
127
- return {
128
- id: consent.id,
129
- recordId: consent.recordId,
130
- sessionKey: consent.sessionKey,
131
- purpose: consent.purpose,
132
- statement: record.content,
133
- sourceName: record.source.provider ?? "local",
134
- status: consent.status,
135
- grantScope: consent.grantScope,
136
- expiresAt: consent.expiresAt,
137
- createdAt: consent.createdAt,
138
- updatedAt: consent.updatedAt
139
- };
38
+ const FEEDBACK_RATINGS = new Set([
39
+ "helpful",
40
+ "irrelevant",
41
+ "wrong",
42
+ "stale",
43
+ "sensitive"
44
+ ]);
45
+ function asRecord(value) {
46
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
140
47
  }
141
- function buildConflictGroups(records) {
142
- const groups = /* @__PURE__ */ new Map();
143
- for (const record of records) {
144
- if (!record.conflictGroupId) continue;
145
- const group = groups.get(record.conflictGroupId) ?? [];
146
- group.push(record);
147
- groups.set(record.conflictGroupId, group);
48
+ async function readBody(c) {
49
+ try {
50
+ return asRecord(await c.req.json());
51
+ } catch {
52
+ return;
148
53
  }
149
- return [...groups.entries()].filter(([, group]) => group.length > 1 && group.some((record) => VISIBLE_STATUSES.has(record.status))).map(([id, group]) => ({
150
- id,
151
- records: group.sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt)).map((record) => ({
152
- ...projectUserContextRecord(record),
153
- storedStatus: record.status
154
- })),
155
- unresolved: group.filter((record) => VISIBLE_STATUSES.has(record.status)).length > 1
156
- }));
157
54
  }
158
- async function readProfileBundle(config) {
159
- const result = await readUserProfileFile();
160
- const profileContent = result.ok ? result.data.content : "";
161
- const profile = parseUserProfileMarkdown(profileContent);
162
- return {
163
- profileContent,
164
- profile,
165
- profileSetup: buildUserProfileSetup({
166
- profile,
167
- promptState: getUserProfilePromptState(),
168
- config
169
- })
170
- };
55
+ function nonEmptyString(value, max = 2e3) {
56
+ if (typeof value !== "string") return void 0;
57
+ const result = value.trim();
58
+ return result && result.length <= max ? result : void 0;
171
59
  }
172
- function parseProfilePatch(body) {
173
- if (!body || typeof body !== "object" || Array.isArray(body)) return { error: "Invalid profile patch" };
174
- const record = body;
175
- const patch = {};
176
- for (const field of Object.keys(PROFILE_FIELD_LIMITS)) {
177
- if (!(field in record)) continue;
178
- if (typeof record[field] !== "string") return { error: `${field} must be a string` };
179
- const value = record[field].trim();
180
- if (value.length > PROFILE_FIELD_LIMITS[field]) return { error: `${field} is too long` };
181
- patch[field] = value;
182
- }
183
- return Object.keys(patch).length > 0 ? { patch } : { error: "No profile fields provided" };
60
+ function scopeFrom(value) {
61
+ const raw = asRecord(value);
62
+ const type = raw?.type;
63
+ if (type !== "global" && type !== "workspace" && type !== "project" && type !== "session") return void 0;
64
+ if (type === "global") return { type };
65
+ const id = nonEmptyString(raw.id, 500);
66
+ return id ? {
67
+ type,
68
+ id
69
+ } : void 0;
184
70
  }
185
- function playbookForRecord(record) {
186
- if (!record.tags?.includes("playbook:rule")) return void 0;
187
- if (record.kind === "preference" || record.kind === "boundary" || record.kind === "tool_preference") return "communication";
188
- if (record.kind === "task_lesson" || record.kind === "derived_insight") return "execution";
189
- if (record.kind === "routine") return "routines";
71
+ function canonicalKey(kind, statement) {
72
+ const normalized = statement.toLocaleLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
73
+ return `${kind}:${createHash("sha256").update(normalized).digest("hex").slice(0, 20)}`;
190
74
  }
191
- function playbookRuleOrder(record) {
192
- const tag = record.tags?.find((value) => value.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
193
- const parsed = tag ? Number.parseInt(tag.slice(PERSONAL_PLAYBOOK_ORDER_PREFIX.length), 10) : NaN;
194
- return Number.isFinite(parsed) ? parsed : 1e3;
75
+ function sameScope(left, right) {
76
+ return left.type === right.type && left.id === right.id;
195
77
  }
196
- function patchPlaybookRuleTags(record, patch) {
197
- let tags = (record.tags ?? []).filter((tag) => !tag.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
198
- if (patch.enabled === true) tags = tags.filter((tag) => tag !== PERSONAL_PLAYBOOK_DISABLED_TAG);
199
- if (patch.enabled === false) tags.push(PERSONAL_PLAYBOOK_DISABLED_TAG);
200
- if (patch.order !== void 0) tags.push(`${PERSONAL_PLAYBOOK_ORDER_PREFIX}${patch.order}`);
201
- return [...new Set(tags)];
202
- }
203
- function parsePlaybookContext(value) {
204
- if (value === void 0) return { context: {} };
205
- if (!value || typeof value !== "object" || Array.isArray(value)) return { error: "context must be an object" };
206
- const input = value;
207
- const context = {};
208
- if ("channel" in input) {
209
- if (input.channel !== null && (typeof input.channel !== "string" || !/^[a-z0-9_-]{1,40}$/i.test(input.channel))) return { error: "context.channel is invalid" };
210
- context.channel = input.channel === null ? void 0 : String(input.channel);
211
- }
212
- if ("supportNeed" in input) {
213
- if (input.supportNeed !== null && !PLAYBOOK_SUPPORT_NEEDS.has(String(input.supportNeed))) return { error: "context.supportNeed is invalid" };
214
- context.supportNeed = input.supportNeed === null ? void 0 : input.supportNeed;
78
+ function validTimezone(value) {
79
+ if (!value) return true;
80
+ try {
81
+ new Intl.DateTimeFormat("en", { timeZone: value }).format();
82
+ return true;
83
+ } catch {
84
+ return false;
215
85
  }
216
- return { context };
217
- }
218
- function buildPersonalPlaybooks(records) {
219
- return PLAYBOOK_IDS.map((id) => {
220
- const rules = records.filter((record) => record.status === "active" && playbookForRecord(record) === id).sort((left, right) => playbookRuleOrder(left) - playbookRuleOrder(right) || left.updatedAt.localeCompare(right.updatedAt));
221
- return {
222
- id,
223
- enabled: rules.some((record) => !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG)),
224
- rules: rules.map((record) => ({
225
- id: record.id,
226
- statement: record.content,
227
- origin: record.explicitness,
228
- enabled: !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG),
229
- order: playbookRuleOrder(record),
230
- context: personalPlaybookContext(record),
231
- versions: playbookVersionChain(records, record.id).map((version) => ({
232
- id: version.id,
233
- statement: version.content,
234
- updatedAt: version.updatedAt,
235
- current: version.id === record.id
236
- }))
237
- })),
238
- updatedAt: rules.map((record) => record.updatedAt).sort().at(-1)
239
- };
240
- });
241
- }
242
- function buildInsightSuggestions(records) {
243
- return records.filter((record) => record.status === "active").filter((record) => ACTIONABLE_INSIGHT_KINDS.has(record.kind)).filter((record) => !record.tags?.includes(INSIGHT_ACCEPTED_TAG) && !record.tags?.includes(INSIGHT_DISMISSED_TAG)).filter((record) => {
244
- const stability = resolveMemoryStability(record);
245
- return record.explicitness === "explicit" || (record.evidence?.length ?? 0) >= 2 || stability.band === "strong";
246
- }).sort((left, right) => right.importance - left.importance || Date.parse(right.updatedAt) - Date.parse(left.updatedAt)).slice(0, 5).map((record) => ({
247
- id: record.id,
248
- insight: record.content,
249
- kind: record.kind,
250
- action: record.kind === "routine" ? "make_repeatable" : record.kind === "task_lesson" || record.kind === "derived_insight" ? "add_playbook" : "start_progress",
251
- evidenceCount: record.evidence?.length ?? 0,
252
- confidence: record.confidence,
253
- sourceName: record.source.provider ?? "local"
254
- }));
255
- }
256
- function buildRoutineAutomationDraftHref(record) {
257
- return `/automations?${new URLSearchParams({
258
- draft: record.content,
259
- autogenerate: "1",
260
- insight: record.id
261
- }).toString()}`;
262
- }
263
- function selectedAgentId(config) {
264
- return resolveDefaultAgentId(config);
265
86
  }
266
- function editableRecord(recordId) {
267
- const record = getMemoryRecord(recordId);
268
- if (!record || !VISIBLE_STATUSES.has(record.status) || !isUserContextRecord(record)) return null;
269
- return record;
270
- }
271
- function memoryRecordInput(record) {
272
- return {
273
- providerId: record.providerId,
274
- kind: record.kind,
275
- userId: record.scope.userId,
276
- sourceAgentId: record.provenance.sourceAgentId,
277
- workspaceId: record.scope.workspaceId,
278
- sessionKey: record.scope.sessionKey,
279
- projectId: record.scope.projectId,
280
- content: record.content,
281
- source: record.source,
282
- confidence: record.confidence,
283
- tags: record.tags,
284
- status: record.status,
285
- sensitivity: record.sensitivity,
286
- canonicalKey: record.canonicalKey,
287
- explicitness: record.explicitness,
288
- durability: record.durability,
289
- importance: record.importance,
290
- disclosurePolicy: record.disclosurePolicy,
291
- evidence: record.evidence,
292
- reviewAfter: record.reviewAfter,
293
- expiresAt: record.expiresAt,
294
- validFrom: record.validFrom,
295
- validTo: record.validTo,
296
- supersedesRecordId: record.supersedesRecordId,
297
- conflictGroupId: record.conflictGroupId
298
- };
299
- }
300
- function preserveRecord(record, patch) {
301
- return upsertMemoryRecord({
302
- ...memoryRecordInput(record),
303
- ...patch,
304
- id: record.id
305
- });
306
- }
307
- function playbookVersionChain(records, recordId) {
308
- const relatedIds = new Set([recordId]);
309
- let previousSize = 0;
310
- while (previousSize !== relatedIds.size) {
311
- previousSize = relatedIds.size;
312
- for (const record of records) {
313
- if (!record.supersedesRecordId) continue;
314
- if (relatedIds.has(record.id) || relatedIds.has(record.supersedesRecordId)) {
315
- relatedIds.add(record.id);
316
- relatedIds.add(record.supersedesRecordId);
317
- }
318
- }
87
+ function machineCallName() {
88
+ try {
89
+ const username = userInfo().username.trim();
90
+ return [
91
+ "root",
92
+ "admin",
93
+ "administrator",
94
+ "user"
95
+ ].includes(username.toLocaleLowerCase()) ? "" : username.slice(0, 100);
96
+ } catch {
97
+ return "";
319
98
  }
320
- return records.filter((record) => relatedIds.has(record.id) && playbookForRecord(record) !== void 0).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt));
321
- }
322
- function versionPlaybookRule(record, patch) {
323
- return upsertMemoryRecord({
324
- ...memoryRecordInput(record),
325
- ...patch,
326
- status: "active",
327
- supersedesRecordId: record.id,
328
- source: {
329
- provider: "local",
330
- path: "you://playbook/version"
331
- }
332
- });
333
99
  }
334
100
  function registerYouRoutes(authenticated, deps) {
335
- authenticated.get("/api/you", async (c) => {
336
- const config = deps.service.currentConfig;
337
- const agentId = selectedAgentId(config);
338
- const profileBundle = await readProfileBundle(config);
339
- const allUserContextRecords = listAllUserContextRecords(ALL_MEMORY_STATUSES).filter(isUserContextRecord);
340
- const records = allUserContextRecords.filter((record) => VISIBLE_STATUSES.has(record.status));
341
- const recordById = new Map(allUserContextRecords.map((record) => [record.id, record]));
342
- const consents = listMemoryReferenceConsents();
343
- const trustPolicy = getUserTrustPolicy();
344
- const sourceDefinitions = listConnectorCatalog();
345
- const sourceInstances = listConnectorInstances(config);
346
- const sources = projectPersonalContextSources(sourceDefinitions, sourceInstances, {
347
- sourceItems: listKnowledgeSourceItems({ limit: 500 }),
348
- syncRuns: listKnowledgeSyncRuns({ limit: 500 }),
349
- connections: listConnectorConnections({ principalId: "local-owner" }),
350
- learningJobs: listConnectorLearningJobs({ limit: 500 }),
351
- claimStatsBySource: listUserClaimStatsBySource()
352
- });
353
- const activeTasks = new TaskRepository().list({ limit: 20 }).flatMap((task) => {
354
- if (task.delegateAgentId !== agentId || task.phase === "closed") return [];
355
- return [{
356
- id: task.id,
357
- title: task.title,
358
- body: task.body
359
- }];
360
- });
361
- return c.json({
362
- scope: {
363
- profile: "global",
364
- memory: "global",
365
- trust: "global"
366
- },
367
- ...profileBundle,
368
- understanding: records.map(projectUserContextRecord),
369
- connectedClaims: listUserClaims({
370
- agentId,
371
- limit: 100
372
- }).map((claim) => ({
373
- ...claim,
374
- evidence: listUserClaimEvidence(claim.id)
375
- })),
376
- consentRequests: consents.filter((consent) => consent.status === "pending").flatMap((consent) => {
377
- const record = recordById.get(consent.recordId);
378
- return record ? [projectReferenceConsent(consent, record)] : [];
379
- }),
380
- referenceGrants: consents.filter((consent) => consent.status === "granted" && (!consent.expiresAt || Date.parse(consent.expiresAt) > Date.now())).flatMap((consent) => {
381
- const record = recordById.get(consent.recordId);
382
- return record ? [projectReferenceConsent(consent, record)] : [];
383
- }),
384
- conflictGroups: buildConflictGroups(allUserContextRecords),
385
- insights: buildInsightSuggestions(records),
386
- playbooks: buildPersonalPlaybooks(allUserContextRecords),
387
- sources,
388
- sourceRecommendations: buildTaskSourceRecommendations(sourceDefinitions, new Set(sourceInstances.map((instance) => instance.connectorId)), activeTasks),
389
- controls: {
390
- mode: config.userContext.memory.mode,
391
- sensitiveWritePolicy: config.userContext.privacy.sensitiveWritePolicy
392
- },
393
- relationship: getRelationshipSettings(),
394
- trust: {
395
- defaultActionLevel: trustPolicy.defaultActionLevel,
396
- levels: USER_TRUST_LEVELS,
397
- autoRequiresExplicitOptIn: true
398
- }
399
- });
400
- });
401
- authenticated.get("/api/you/feedback/:turnId", (c) => {
402
- const trace = getMemoryTurnFeedback(c.req.param("turnId"));
403
- if (!trace) return c.json({ error: "Turn context not found" }, 404);
404
- const personalContext = trace.selectedRecordIds.map((id) => getMemoryRecord(id)).filter((record) => Boolean(record) && isUserContextRecord(record)).map(projectUserContextRecord);
405
- return c.json({
406
- trace,
407
- personalContext
408
- });
409
- });
410
- authenticated.put("/api/you/feedback/:turnId", deps.strictRateLimitMiddleware, async (c) => {
411
- const body = await c.req.json().catch(() => null);
412
- if (!body || typeof body !== "object" || Array.isArray(body)) return c.json({ error: "Invalid feedback" }, 400);
413
- const input = body;
414
- if (typeof input.rating !== "string" || !FEEDBACK_RATINGS.has(input.rating)) return c.json({ error: "Invalid rating" }, 400);
415
- const records = Array.isArray(input.records) ? input.records.flatMap((value) => {
416
- if (!value || typeof value !== "object" || Array.isArray(value)) return [];
417
- const item = value;
418
- if (typeof item.recordId !== "string" || typeof item.rating !== "string" || !FEEDBACK_RATINGS.has(item.rating)) return [];
419
- return [{
420
- recordId: item.recordId,
421
- rating: item.rating,
422
- ...typeof item.reasonCode === "string" ? { reasonCode: item.reasonCode } : {},
423
- ...typeof item.note === "string" ? { note: item.note } : {}
424
- }];
425
- }) : void 0;
426
- const trace = setMemoryTurnFeedback({
427
- turnId: c.req.param("turnId"),
428
- rating: input.rating,
429
- source: "user",
430
- ...typeof input.score === "number" ? { score: input.score } : {},
431
- ...typeof input.reasonCode === "string" ? { reasonCode: input.reasonCode } : {},
432
- ...typeof input.note === "string" ? { note: input.note } : {},
433
- ...records ? { records } : {}
434
- });
435
- if (!trace) return c.json({ error: "Turn context not found" }, 404);
436
- if (trace.sessionKey && input.rating === "not_helpful" && input.reasonCode === "tone_mismatch") setInteractionState({
437
- sessionKey: trace.sessionKey,
438
- signal: {
439
- supportNeed: "unknown",
440
- confidence: 1,
441
- source: "explicit",
442
- repairStatus: "needed",
443
- repairReason: "tone_mismatch"
444
- }
445
- });
446
- const personalContext = trace.selectedRecordIds.map((id) => getMemoryRecord(id)).filter((record) => Boolean(record) && isUserContextRecord(record)).map(projectUserContextRecord);
447
- return c.json({
448
- trace,
449
- personalContext
450
- });
451
- });
452
- authenticated.get("/api/you/dreaming", (c) => {
453
- const config = deps.service.currentConfig;
454
- const scope = resolveDreamingAgentScope(config);
455
- const settings = resolveDreamingSettings(config);
456
- const signals = listMemorySignals({
457
- workspaceId: scope.workspaceDir,
458
- limit: 500
459
- });
460
- return c.json({
461
- agentId: scope.agentId,
462
- settings,
463
- config: {
464
- ...scope.config,
465
- phases: {
466
- light: {
467
- ...scope.config.phases.light,
468
- nextRunsAt: nextDreamingRunTimes(scope.config.phases.light.schedule, scope.config.timezone)
469
- },
470
- deep: {
471
- ...scope.config.phases.deep,
472
- nextRunsAt: nextDreamingRunTimes(scope.config.phases.deep.schedule, scope.config.timezone)
473
- },
474
- rem: {
475
- ...scope.config.phases.rem,
476
- nextRunsAt: nextDreamingRunTimes(scope.config.phases.rem.schedule, scope.config.timezone)
477
- }
478
- }
479
- },
480
- readiness: scope.readiness,
481
- runs: listDreamingRuns({
482
- agentId: scope.agentId,
483
- limit: 50
484
- }),
485
- signalCount: signals.filter((signal) => signal.source === "dreaming").length
486
- });
487
- });
488
- authenticated.put("/api/you/dreaming", deps.strictRateLimitMiddleware, async (c) => {
489
- const config = deps.service.currentConfig;
490
- const body = await c.req.json().catch(() => ({}));
491
- const settings = DreamingSettingsSchema.safeParse(body);
492
- if (!settings.success) return c.json({ error: settings.error.issues[0]?.message ?? "Invalid Dreaming settings" }, 400);
493
- const currentPhases = config.userContext.dreaming.phases ?? {};
494
- const parsed = UserContextConfigSchema.safeParse({
495
- ...config.userContext,
496
- dreaming: {
497
- ...config.userContext.dreaming,
498
- mode: settings.data.mode,
499
- timezone: settings.data.timezone,
500
- phases: {
501
- light: {
502
- ...currentPhases.light,
503
- ...settings.data.phases.light
504
- },
505
- deep: {
506
- ...currentPhases.deep,
507
- ...settings.data.phases.deep
508
- },
509
- rem: {
510
- ...currentPhases.rem,
511
- ...settings.data.phases.rem
512
- }
513
- }
514
- }
515
- });
516
- if (!parsed.success) return c.json({ error: parsed.error.issues[0]?.message ?? "Invalid Dreaming settings" }, 400);
517
- const saved = await deps.service.saveConfig({
518
- ...config,
519
- userContext: parsed.data
520
- });
521
- if (!saved.saved) return c.json({ error: saved.error ?? "save failed" }, 500);
522
- const savedConfig = deps.service.currentConfig;
523
- return c.json({ settings: resolveDreamingSettings(savedConfig) });
524
- });
525
- authenticated.get("/api/you/readiness", (c) => {
526
- return c.json(resolveDreamingAgentScope(deps.service.currentConfig).readiness);
527
- });
528
- authenticated.post("/api/you/dreaming/runs", deps.strictRateLimitMiddleware, async (c) => {
529
- const body = await c.req.json().catch(() => ({}));
530
- const phase = body.phase === "light" || body.phase === "deep" || body.phase === "rem" ? body.phase : "deep";
531
- try {
532
- const result = await runDreamingPhase({
533
- config: deps.service.currentConfig,
534
- phase,
535
- triggerKind: "manual"
536
- });
537
- return c.json(result);
538
- } catch (error) {
539
- return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
540
- }
541
- });
542
- authenticated.get("/api/you/dreaming/runs/:runId", (c) => {
543
- const scope = resolveDreamingAgentScope(deps.service.currentConfig);
544
- const run = getDreamingRun(c.req.param("runId"));
545
- if (!run || run.agentId !== scope.agentId || run.workspaceId !== scope.workspaceDir) return c.json({ error: "Dreaming run not found" }, 404);
101
+ const write = deps.strictRateLimitMiddleware;
102
+ authenticated.get("/api/you", (c) => c.json({
103
+ profile: getUserProfile(),
104
+ understandings: listUnderstandings(),
105
+ rules: listCollaborationRules(),
106
+ consolidation: { lastRun: listContextConsolidationRuns(1)[0] ?? null }
107
+ }));
108
+ authenticated.get("/api/you/profile", (c) => {
109
+ const profile = getUserProfile();
546
110
  return c.json({
547
- run,
548
- decisions: listDreamingDecisions(run.runId)
111
+ profile,
112
+ suggestedCallName: profile.callName || machineCallName()
549
113
  });
550
114
  });
551
- authenticated.patch("/api/you/relationship", deps.strictRateLimitMiddleware, async (c) => {
552
- const body = await c.req.json().catch(() => null);
553
- if (!body || typeof body !== "object" || Array.isArray(body)) return c.json({ error: "Invalid relationship settings" }, 400);
554
- const input = body;
115
+ authenticated.patch("/api/you/profile", write, async (c) => {
116
+ const body = await readBody(c);
117
+ if (!body) return c.json({ error: "Invalid JSON" }, 400);
555
118
  const patch = {};
556
- if ("supportMode" in input) {
557
- if (![
558
- "efficient",
559
- "coach",
560
- "companion",
561
- "auto"
562
- ].includes(String(input.supportMode))) return c.json({ error: "Invalid supportMode" }, 400);
563
- patch.supportMode = input.supportMode;
564
- }
565
- if ("proactiveEnabled" in input) {
566
- if (typeof input.proactiveEnabled !== "boolean") return c.json({ error: "proactiveEnabled must be boolean" }, 400);
567
- patch.proactiveEnabled = input.proactiveEnabled;
119
+ for (const field of [
120
+ "callName",
121
+ "role",
122
+ "primaryGoal",
123
+ "pronouns",
124
+ "timezone",
125
+ "locale"
126
+ ]) {
127
+ if (body[field] === void 0) continue;
128
+ const max = field === "primaryGoal" ? 500 : field === "role" ? 300 : 100;
129
+ if (typeof body[field] !== "string" || body[field].length > max) return c.json({ error: `${field} must be a string of at most ${max} characters` }, 400);
130
+ patch[field] = body[field].trim();
568
131
  }
569
- for (const field of ["quietStart", "quietEnd"]) {
570
- if (!(field in input)) continue;
571
- const value = input[field];
572
- 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);
573
- patch[field] = value === null ? void 0 : String(value);
132
+ if (body.accessibility !== void 0) {
133
+ const accessibility = asRecord(body.accessibility);
134
+ if (!accessibility) return c.json({ error: "accessibility must be an object" }, 400);
135
+ if (JSON.stringify(accessibility).length > 1e4) return c.json({ error: "accessibility is too large" }, 400);
136
+ patch.accessibility = accessibility;
574
137
  }
575
- for (const field of ["allowedTopics", "blockedTopics"]) {
576
- if (!(field in input)) continue;
577
- 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);
578
- patch[field] = [...new Set(input[field].map((value) => value.trim()))];
579
- }
580
- if (Object.keys(patch).length === 0) return c.json({ error: "No relationship settings provided" }, 400);
581
- return c.json({
582
- ok: true,
583
- relationship: updateRelationshipSettings(patch)
584
- });
585
- });
586
- authenticated.patch("/api/you/claims/:id", deps.strictRateLimitMiddleware, async (c) => {
587
- const body = await c.req.json().catch(() => ({}));
588
- const action = body.action === "confirm" || body.action === "reject" ? body.action : void 0;
589
- if (!action) return c.json({ error: "Action must be confirm or reject" }, 400);
590
- const claim = runSqliteWriteTransaction(() => {
591
- const updated = setUserClaimDecision(c.req.param("id"), action === "confirm" ? "confirmed" : "rejected");
592
- if (!updated) return updated;
593
- const existing = updated.memoryRecordId ? getMemoryRecord(updated.memoryRecordId) : void 0;
594
- if (existing) preserveRecord(existing, {
595
- status: action === "confirm" ? "active" : "rejected",
596
- ...action === "confirm" ? { reviewAfter: nextMemoryReviewAt(existing) } : {}
597
- });
598
- else if (action === "confirm") {
599
- const candidate = renderUserClaim(updated);
600
- const evidence = listUserClaimEvidence(updated.id);
601
- const record = upsertMemoryRecord({
602
- providerId: "local",
603
- kind: candidate.kind,
604
- sourceAgentId: updated.agentId,
605
- content: candidate.content,
606
- canonicalKey: candidate.canonicalKey,
607
- source: { provider: "connected-sources" },
608
- confidence: 1,
609
- status: "active",
610
- sensitivity: candidate.sensitivity,
611
- explicitness: "explicit",
612
- durability: candidate.durability,
613
- importance: candidate.importance,
614
- disclosurePolicy: candidate.disclosurePolicy,
615
- tags: [...new Set([
616
- "user-understanding",
617
- ...candidate.tags ?? [],
618
- "user-confirmed"
619
- ])],
620
- evidence: evidence.map((item) => ({
621
- sourceItemId: item.sourceItemId,
622
- relation: item.relation === "contradicts" ? "contradicts" : "supports",
623
- observedAt: item.observedAt,
624
- confidence: updated.confidence
625
- })),
626
- reviewAfter: nextMemoryReviewAt({
627
- durability: candidate.durability,
628
- explicitness: "explicit"
629
- })
630
- });
631
- linkUserClaimMemoryRecord(updated.id, record.id);
632
- }
633
- return getUserClaim(updated.id);
634
- });
635
- if (!claim) return c.json({ error: "Connected claim not found" }, 404);
636
- return c.json({
637
- ok: true,
638
- claim: {
639
- ...claim,
640
- evidence: listUserClaimEvidence(claim.id)
641
- }
642
- });
643
- });
644
- authenticated.get("/api/you/profile", async (c) => {
645
- return c.json(await readProfileBundle(deps.service.currentConfig));
646
- });
647
- authenticated.get("/api/you/export", async (c) => {
648
- const config = deps.service.currentConfig;
649
- const profileBundle = await readProfileBundle(config);
650
- const understanding = listAllUserContextRecords(ALL_MEMORY_STATUSES).filter(isUserContextRecord).map((record) => ({
651
- statement: record.content,
652
- kind: record.kind,
653
- status: record.status,
654
- sensitivity: record.sensitivity ?? "normal",
655
- durability: record.durability,
656
- disclosurePolicy: record.disclosurePolicy,
657
- sourceName: record.source.provider ?? "local",
658
- updatedAt: record.updatedAt
659
- }));
660
- return c.json({
661
- version: 2,
662
- exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
663
- profile: profileBundle.profile,
664
- understanding
665
- });
666
- });
667
- authenticated.post("/api/you/import", deps.strictRateLimitMiddleware, async (c) => {
668
- const body = await c.req.json().catch(() => null);
669
- if (!body || typeof body !== "object" || Array.isArray(body) || body.version !== 2 || !Array.isArray(body.understanding)) return c.json({ error: "Invalid About You export" }, 400);
670
- if (body.understanding.length > 500) return c.json({ error: "Import is limited to 500 understandings" }, 400);
671
- const config = deps.service.currentConfig;
672
- const agentId = selectedAgentId(config);
673
- const existingStatements = listAllUserContextRecords(ALL_MEMORY_STATUSES).filter(isUserContextRecord).map((record) => record.content);
674
- const { imports, skippedCount } = prepareUserContextImport(body.understanding, existingStatements);
675
- runSqliteWriteTransaction(() => {
676
- for (const item of imports) upsertMemoryRecord({
677
- providerId: "local",
678
- kind: item.kind,
679
- sourceAgentId: agentId,
680
- content: item.statement,
681
- source: {
682
- provider: "local",
683
- path: "import://about-you"
684
- },
685
- confidence: 1,
686
- tags: ["user-understanding", "user-import"],
687
- status: "candidate",
688
- sensitivity: item.sensitivity,
689
- explicitness: "explicit",
690
- durability: item.durability,
691
- importance: .7,
692
- disclosurePolicy: item.disclosurePolicy
693
- });
694
- });
695
- return c.json({
696
- ok: true,
697
- importedCount: imports.length,
698
- skippedCount
699
- });
700
- });
701
- authenticated.post("/api/you/understanding", deps.strictRateLimitMiddleware, async (c) => {
702
- const body = await c.req.json().catch(() => ({}));
703
- const content = typeof body.content === "string" ? body.content.trim() : "";
704
- const kind = isUserContextMemoryKind(body.kind) ? body.kind : void 0;
705
- if (!content || content.length > 5e3) return c.json({ error: "Understanding content must be 1-5000 characters" }, 400);
706
- if (!kind) return c.json({ error: "A valid user understanding kind is required" }, 400);
707
- const scope = body.scope === "session" ? {
708
- type: "session",
709
- sessionKey: typeof body.sessionKey === "string" ? body.sessionKey.trim() : ""
710
- } : body.scope === void 0 || body.scope === "global" ? { type: "global" } : null;
711
- if (!scope || scope.type === "session" && !scope.sessionKey) return c.json({ error: "scope must be global or a session with sessionKey" }, 400);
712
- const sensitivity = MEMORY_SENSITIVITIES.has(body.sensitivity) ? body.sensitivity : "normal";
713
- const durability = MEMORY_DURABILITIES.has(body.durability) ? body.durability : "durable";
714
- const disclosurePolicy = MEMORY_DISCLOSURE_POLICIES.has(body.disclosurePolicy) ? body.disclosurePolicy : "referenceable";
715
- const config = deps.service.currentConfig;
716
- const result = createManualUnderstanding({
717
- agentId: selectedAgentId(config),
718
- content,
719
- kind,
720
- scope,
721
- sensitivity,
722
- durability,
723
- disclosurePolicy
724
- });
725
- if (!result.created) return c.json({
726
- error: "This understanding already exists in the selected scope",
727
- understanding: projectUserContextRecord(result.record)
728
- }, 409);
729
- return c.json({ understanding: projectUserContextRecord(result.record) }, 201);
730
- });
731
- authenticated.get("/api/you/understanding/:id/history", (c) => {
732
- const all = listAllUserContextRecords(ALL_MEMORY_STATUSES).filter(isUserContextRecord);
733
- const target = all.find((record) => record.id === c.req.param("id"));
734
- if (!target) return c.json({ error: "Understanding not found" }, 404);
735
- const relatedIds = new Set([target.id]);
736
- let changed = true;
737
- while (changed) {
738
- changed = false;
739
- for (const record of all) if (record.supersedesRecordId && relatedIds.has(record.supersedesRecordId) || record.supersedesRecordId && relatedIds.has(record.id)) {
740
- if (!relatedIds.has(record.id)) {
741
- relatedIds.add(record.id);
742
- changed = true;
743
- }
744
- if (record.supersedesRecordId && !relatedIds.has(record.supersedesRecordId)) {
745
- relatedIds.add(record.supersedesRecordId);
746
- changed = true;
747
- }
748
- }
749
- }
750
- const history = all.filter((record) => relatedIds.has(record.id)).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt)).map((record) => ({
751
- ...projectUserContextRecord(record),
752
- storedStatus: record.status
753
- }));
754
- return c.json({ history });
755
- });
756
- authenticated.post("/api/you/understanding/batch", deps.strictRateLimitMiddleware, async (c) => {
757
- const body = await c.req.json().catch(() => ({}));
758
- const ids = Array.isArray(body.ids) ? [...new Set(body.ids.filter((id) => typeof id === "string" && id.trim().length > 0).slice(0, 100))] : [];
759
- const action = body.action === "confirm" || body.action === "reject" || body.action === "forget" ? body.action : void 0;
760
- if (!ids.length || !action) return c.json({ error: "ids and a valid action are required" }, 400);
761
- let updatedCount = 0;
762
- runSqliteWriteTransaction(() => {
763
- for (const id of ids) {
764
- const record = editableRecord(id);
765
- if (!record) continue;
766
- if (action === "forget") deleteMemoryRecord(id);
767
- else preserveRecord(record, {
768
- status: action === "confirm" ? "active" : "rejected",
769
- ...action === "confirm" ? { reviewAfter: nextMemoryReviewAt(record) } : {}
770
- });
771
- updatedCount += 1;
772
- }
773
- });
774
- return c.json({
775
- ok: true,
776
- updatedCount
777
- });
778
- });
779
- authenticated.post("/api/you/conflicts/:id/resolve", deps.strictRateLimitMiddleware, async (c) => {
780
- const body = await c.req.json().catch(() => ({}));
781
- const winnerId = typeof body.winnerId === "string" ? body.winnerId : "";
782
- const group = listAllUserContextRecords(ALL_MEMORY_STATUSES).filter(isUserContextRecord).filter((record) => record.conflictGroupId === c.req.param("id"));
783
- const winner = group.find((record) => record.id === winnerId && VISIBLE_STATUSES.has(record.status));
784
- if (group.length < 2 || !winner) return c.json({ error: "Conflict group or winner not found" }, 404);
785
- const now = (/* @__PURE__ */ new Date()).toISOString();
786
- runSqliteWriteTransaction(() => {
787
- for (const record of group) preserveRecord(record, record.id === winnerId ? {
788
- status: "active",
789
- reviewAfter: nextMemoryReviewAt(record)
790
- } : {
791
- status: "archived",
792
- validTo: record.validTo ?? now
793
- });
794
- });
795
- return c.json({
796
- ok: true,
797
- understanding: projectUserContextRecord(getMemoryRecord(winnerId))
798
- });
799
- });
800
- authenticated.patch("/api/you/profile", deps.strictRateLimitMiddleware, async (c) => {
801
- const config = deps.service.currentConfig;
802
- const parsed = parseProfilePatch(await c.req.json().catch(() => null));
803
- if ("error" in parsed) return c.json({ error: parsed.error }, 400);
804
- const current = await readUserProfileFile();
805
- const saved = await writeUserProfileFile(patchUserProfileMarkdown(current.ok ? current.data.content : "", parsed.patch));
806
- if (saved.ok === false) return c.json({ error: saved.error }, saved.status ?? 500);
807
- if (parsed.patch.callName !== void 0) setUserProfilePromptState({ state: "active" });
808
- deps.service.refreshUserProfileContext();
809
- return c.json(await readProfileBundle(config));
810
- });
811
- authenticated.post("/api/you/profile-prompt", deps.strictRateLimitMiddleware, async (c) => {
812
- const body = await c.req.json().catch(() => ({}));
813
- const action = typeof body.action === "string" ? body.action : "";
814
- if (action !== "snooze" && action !== "reset") return c.json({ error: "Action must be snooze or reset" }, 400);
815
- const config = deps.service.currentConfig;
816
- const current = await readProfileBundle(config);
817
- const suggestionHash = current.profileSetup.callNameSuggestion?.id;
818
- const promptState = action === "snooze" ? setUserProfilePromptState({
819
- state: "snoozed",
820
- suggestionHash,
821
- snoozedUntil: new Date(Date.now() + PROFILE_PROMPT_SNOOZE_MS).toISOString()
822
- }) : setUserProfilePromptState({
823
- state: "active",
824
- suggestionHash
825
- });
826
- return c.json({ profileSetup: buildUserProfileSetup({
827
- profile: current.profile,
828
- promptState,
829
- config
830
- }) });
831
- });
832
- authenticated.patch("/api/you/trust", deps.strictRateLimitMiddleware, async (c) => {
833
- const body = await c.req.json().catch(() => ({}));
834
- if (!isUserTrustLevel(body.defaultActionLevel)) return c.json({ error: "Invalid default action level" }, 400);
835
- const policy = setUserTrustPolicy(body.defaultActionLevel);
836
- deps.service.refreshActionTrustPolicy();
837
- return c.json({ trust: {
838
- defaultActionLevel: policy.defaultActionLevel,
839
- levels: USER_TRUST_LEVELS,
840
- autoRequiresExplicitOptIn: true
841
- } });
842
- });
843
- authenticated.patch("/api/you/playbooks/:id", deps.strictRateLimitMiddleware, async (c) => {
844
- const id = c.req.param("id");
845
- if (!PLAYBOOK_IDS.includes(id)) return c.json({ error: "Playbook not found" }, 404);
846
- const enabled = (await c.req.json().catch(() => ({}))).enabled;
847
- if (typeof enabled !== "boolean") return c.json({ error: "enabled must be a boolean" }, 400);
848
- const active = listMemoryRecords({
138
+ if (patch.timezone !== void 0 && !validTimezone(patch.timezone)) return c.json({ error: "timezone must be a valid IANA time zone" }, 400);
139
+ return c.json({ profile: updateUserProfile(patch) });
140
+ });
141
+ authenticated.post("/api/you/understandings", write, async (c) => {
142
+ const body = await readBody(c);
143
+ const statement = nonEmptyString(body?.statement);
144
+ const kind = body?.kind;
145
+ const scope = scopeFrom(body?.scope ?? { type: "global" });
146
+ if (!statement || !UNDERSTANDING_KINDS.has(kind) || !scope) return c.json({ error: "Valid statement, kind, and scope are required" }, 400);
147
+ const typedKind = kind;
148
+ const key = canonicalKey(typedKind, statement);
149
+ if (listUnderstandings().some((item) => item.canonicalKey === key && sameScope(item.scope, scope) && item.status !== "archived" && item.status !== "rejected")) return c.json({ error: "This understanding already exists" }, 409);
150
+ const understanding = createUnderstanding({
151
+ kind: typedKind,
152
+ canonicalKey: key,
849
153
  status: "active",
850
- limit: 500
851
- }).filter(isUserContextRecord).filter((record) => playbookForRecord(record) === id);
852
- runSqliteWriteTransaction(() => {
853
- for (const record of active) versionPlaybookRule(record, { tags: patchPlaybookRuleTags(record, { enabled }) });
854
- });
855
- const current = active.map((record) => ({
856
- ...record,
857
- tags: patchPlaybookRuleTags(record, { enabled })
858
- }));
859
- return c.json({
860
- ok: true,
861
- playbook: buildPersonalPlaybooks(current).find((playbook) => playbook.id === id)
862
- });
863
- });
864
- authenticated.post("/api/you/playbooks/:id/rules", deps.strictRateLimitMiddleware, async (c) => {
865
- const id = c.req.param("id");
866
- if (!PLAYBOOK_IDS.includes(id)) return c.json({ error: "Playbook not found" }, 404);
867
- const body = await c.req.json().catch(() => ({}));
868
- const statement = typeof body.statement === "string" ? body.statement.trim() : "";
869
- if (!statement || statement.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
870
- const parsedContext = parsePlaybookContext(body.context);
871
- if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
872
- const record = upsertMemoryRecord({
873
- providerId: "local",
874
- kind: id === "communication" ? "preference" : id === "execution" ? "task_lesson" : "routine",
875
- sourceAgentId: selectedAgentId(deps.service.currentConfig),
876
- content: statement,
877
- source: {
878
- provider: "local",
879
- path: "you://playbook"
880
- },
881
- confidence: 1,
882
- tags: patchPersonalPlaybookContextTags([
883
- "user-understanding",
884
- PERSONAL_PLAYBOOK_RULE_TAG,
885
- `${PERSONAL_PLAYBOOK_ORDER_PREFIX}${Number.isInteger(body.order) ? body.order : 1e3}`
886
- ], parsedContext.context),
887
- status: "active",
888
- sensitivity: "normal",
154
+ scope,
889
155
  explicitness: "explicit",
890
- durability: id === "routines" ? "recurring" : "durable",
891
- importance: .85,
892
- disclosurePolicy: "referenceable"
893
- });
894
- return c.json({
895
- ok: true,
896
- rule: buildPersonalPlaybooks([record]).find((playbook) => playbook.id === id)?.rules[0]
897
- }, 201);
898
- });
899
- authenticated.patch("/api/you/playbooks/:id/rules/:recordId", deps.strictRateLimitMiddleware, async (c) => {
900
- const id = c.req.param("id");
901
- const record = editableRecord(c.req.param("recordId"));
902
- if (!PLAYBOOK_IDS.includes(id) || !record || playbookForRecord(record) !== id) return c.json({ error: "Playbook rule not found" }, 404);
903
- const body = await c.req.json().catch(() => ({}));
904
- const content = body.statement === void 0 ? record.content : typeof body.statement === "string" ? body.statement.trim() : "";
905
- if (!content || content.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
906
- if (body.enabled !== void 0 && typeof body.enabled !== "boolean") return c.json({ error: "enabled must be boolean" }, 400);
907
- 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);
908
- const parsedContext = parsePlaybookContext(body.context);
909
- if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
910
- const updated = versionPlaybookRule(record, {
911
- content,
912
- tags: patchPersonalPlaybookContextTags(patchPlaybookRuleTags(record, {
913
- enabled: body.enabled,
914
- order: body.order
915
- }), parsedContext.context),
916
- explicitness: body.statement === void 0 ? record.explicitness : "explicit"
917
- });
918
- return c.json({
919
- ok: true,
920
- rule: buildPersonalPlaybooks([updated]).find((playbook) => playbook.id === id)?.rules[0]
156
+ durability: "durable",
157
+ sensitivity: "normal",
158
+ disclosurePolicy: typedKind === "boundary" ? "silent" : "referenceable",
159
+ confidence: 1,
160
+ statement,
161
+ createdBy: "user",
162
+ changeReason: "Created by user"
921
163
  });
164
+ return c.json({ understanding }, 201);
922
165
  });
923
- authenticated.delete("/api/you/playbooks/:id/rules/:recordId", deps.strictRateLimitMiddleware, (c) => {
924
- const id = c.req.param("id");
925
- const record = editableRecord(c.req.param("recordId"));
926
- if (!PLAYBOOK_IDS.includes(id) || !record || playbookForRecord(record) !== id) return c.json({ error: "Playbook rule not found" }, 404);
927
- preserveRecord(record, {
928
- status: "archived",
929
- validTo: (/* @__PURE__ */ new Date()).toISOString()
930
- });
931
- return c.json({ ok: true });
166
+ authenticated.get("/api/you/understandings/:id/evidence", (c) => {
167
+ const understanding = getUnderstanding(c.req.param("id"));
168
+ if (!understanding) return c.json({ error: "Understanding not found" }, 404);
169
+ return c.json({ evidence: listUnderstandingEvidence(understanding.id) });
932
170
  });
933
- authenticated.post("/api/you/playbooks/:id/rules/:recordId/rollback", deps.strictRateLimitMiddleware, async (c) => {
171
+ authenticated.patch("/api/you/understandings/:id", write, async (c) => {
934
172
  const id = c.req.param("id");
935
- const current = editableRecord(c.req.param("recordId"));
936
- if (!PLAYBOOK_IDS.includes(id) || !current || playbookForRecord(current) !== id) return c.json({ error: "Playbook rule not found" }, 404);
937
- const body = await c.req.json().catch(() => ({}));
938
- const versionId = typeof body.versionId === "string" ? body.versionId : "";
939
- const all = listAllUserContextRecords(ALL_MEMORY_STATUSES);
940
- const target = playbookVersionChain(all, current.id).find((record) => record.id === versionId);
941
- if (!target || target.id === current.id) return c.json({ error: "Previous version not found" }, 404);
942
- const rolledBack = versionPlaybookRule(current, {
943
- content: target.content,
944
- tags: target.tags,
945
- evidence: target.evidence,
946
- explicitness: "explicit"
947
- });
948
- return c.json({
949
- ok: true,
950
- rule: buildPersonalPlaybooks([...all, rolledBack]).find((playbook) => playbook.id === id)?.rules.find((rule) => rule.id === rolledBack.id)
951
- });
952
- });
953
- authenticated.patch("/api/you/insights/:id", deps.strictRateLimitMiddleware, async (c) => {
954
- const config = deps.service.currentConfig;
955
- const existing = editableRecord(c.req.param("id"));
956
- if (!existing || existing.status !== "active" || !ACTIONABLE_INSIGHT_KINDS.has(existing.kind)) return c.json({ error: "Insight not found" }, 404);
957
- const body = await c.req.json().catch(() => ({}));
958
- const action = typeof body.action === "string" ? body.action : "";
959
- if (action === "dismiss") {
960
- preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_DISMISSED_TAG])] });
961
- return c.json({
962
- ok: true,
963
- status: "dismissed"
964
- });
965
- }
966
- if (action === "complete" && existing.kind === "routine") {
967
- preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_ACCEPTED_TAG])] });
968
- return c.json({
969
- ok: true,
970
- status: "saved"
173
+ let understanding = getUnderstanding(id);
174
+ if (!understanding) return c.json({ error: "Understanding not found" }, 404);
175
+ const body = await readBody(c);
176
+ if (!body) return c.json({ error: "Invalid JSON" }, 400);
177
+ if (body.statement !== void 0) {
178
+ const statement = nonEmptyString(body.statement);
179
+ if (!statement) return c.json({ error: "statement must be 1-2000 characters" }, 400);
180
+ const key = canonicalKey(understanding.kind, statement);
181
+ if (listUnderstandings().some((item) => item.id !== id && item.canonicalKey === key && sameScope(item.scope, understanding.scope) && item.status !== "archived" && item.status !== "rejected")) return c.json({ error: "This understanding already exists" }, 409);
182
+ understanding = reviseUnderstanding(id, statement, {
183
+ canonicalKey: key,
184
+ explicitness: "explicit",
185
+ confidence: 1,
186
+ changeReason: "Edited by user"
971
187
  });
972
188
  }
973
- if (action !== "apply") return c.json({ error: "Action must be apply, complete, or dismiss" }, 400);
974
- if (existing.kind === "routine") return c.json({
975
- ok: true,
976
- status: "drafting",
977
- href: buildRoutineAutomationDraftHref(existing)
978
- });
979
- if (existing.kind === "task_lesson" || existing.kind === "derived_insight") {
980
- upsertMemoryRecord({
981
- providerId: "local",
982
- kind: "task_lesson",
983
- sourceAgentId: selectedAgentId(config),
984
- content: existing.content,
985
- source: {
986
- provider: "local",
987
- path: "you://insight-proposal"
988
- },
989
- confidence: 1,
990
- tags: [
991
- "user-understanding",
992
- PERSONAL_PLAYBOOK_RULE_TAG,
993
- `${PERSONAL_PLAYBOOK_ORDER_PREFIX}1000`
994
- ],
995
- status: "active",
996
- sensitivity: existing.sensitivity,
189
+ if (body.status !== void 0) {
190
+ if (!UNDERSTANDING_STATUSES.has(body.status)) return c.json({ error: "Invalid status" }, 400);
191
+ understanding = body.status === "rejected" ? rejectUnderstanding(id, nonEmptyString(body.reason, 500) ?? "Rejected by user") : setUnderstandingStatus(id, body.status, body.status === "active" ? {
997
192
  explicitness: "explicit",
998
- durability: "durable",
999
- importance: existing.importance,
1000
- disclosurePolicy: existing.disclosurePolicy,
1001
- evidence: existing.evidence
1002
- });
1003
- preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_ACCEPTED_TAG])] });
1004
- return c.json({
1005
- ok: true,
1006
- status: "saved"
1007
- });
193
+ confidence: 1
194
+ } : void 0);
1008
195
  }
1009
- const title = existing.content.trim().split(/\r?\n/)[0].slice(0, 72);
1010
- const uiLocale = body.uiLocale === "zh" ? "zh" : "en";
1011
- const contract = defineTaskContract(title);
1012
- const created = new TaskApplicationService().create({
1013
- idempotencyKey: randomUUID(),
1014
- title,
1015
- body: existing.content,
1016
- priority: "normal",
1017
- delegateAgentId: selectedAgentId(config),
1018
- locale: uiLocale,
1019
- contract: {
1020
- ...contract,
1021
- acceptancePolicy: "verified_auto",
1022
- outputDestinations: []
1023
- },
1024
- dependencies: [],
1025
- context: [{
1026
- targetKind: "memory",
1027
- targetId: existing.id,
1028
- role: "input",
1029
- pinned: true,
1030
- retrievalPolicy: {},
1031
- metadata: {}
1032
- }],
1033
- authorityGrants: [],
1034
- activation: {
1035
- mode: "start",
1036
- executor: {
1037
- kind: "agent",
1038
- agentId: selectedAgentId(config)
1039
- }
1040
- }
1041
- });
1042
- if (created.ok === false) return c.json({
1043
- ok: false,
1044
- error: created.reason
1045
- }, 409);
1046
- if (created.runId) deps.service.dispatchTaskRuns();
1047
- preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_ACCEPTED_TAG])] });
1048
- return c.json({
1049
- ok: true,
1050
- status: created.runId ? "queued" : "saved",
1051
- taskId: created.model.task.id,
1052
- href: `/tasks/${encodeURIComponent(created.model.task.id)}`
196
+ return c.json({ understanding });
197
+ });
198
+ authenticated.delete("/api/you/understandings/:id", write, (c) => deleteUnderstanding(c.req.param("id")) ? c.json({ ok: true }) : c.json({ error: "Understanding not found" }, 404));
199
+ authenticated.post("/api/you/rules", write, async (c) => {
200
+ const body = await readBody(c);
201
+ const statement = nonEmptyString(body?.statement);
202
+ const category = body?.category;
203
+ const scope = scopeFrom(body?.scope ?? { type: "global" });
204
+ if (!statement || !RULE_CATEGORIES.has(category) || !scope) return c.json({ error: "Valid statement, category, and scope are required" }, 400);
205
+ const priority = typeof body?.priority === "number" && Number.isInteger(body.priority) ? Math.max(0, Math.min(100, body.priority)) : 50;
206
+ const conditions = body?.conditions === void 0 ? {} : asRecord(body.conditions);
207
+ if (!conditions) return c.json({ error: "conditions must be an object" }, 400);
208
+ const rule = createCollaborationRule({
209
+ category,
210
+ priority,
211
+ scope,
212
+ conditions,
213
+ statement
1053
214
  });
215
+ return c.json({ rule }, 201);
1054
216
  });
1055
- authenticated.patch("/api/you/controls", deps.strictRateLimitMiddleware, async (c) => {
1056
- const config = deps.service.currentConfig;
1057
- const body = await c.req.json().catch(() => ({}));
1058
- const parsed = UserContextConfigSchema.safeParse({
1059
- ...config.userContext,
1060
- memory: {
1061
- ...config.userContext.memory,
1062
- mode: body.mode
1063
- },
1064
- privacy: {
1065
- ...config.userContext.privacy,
1066
- sensitiveWritePolicy: body.sensitiveWritePolicy
1067
- }
1068
- });
1069
- if (!parsed.success) return c.json({ error: parsed.error.issues[0]?.message ?? "Invalid personal context controls" }, 400);
1070
- const saved = await deps.service.saveConfig({
1071
- ...config,
1072
- userContext: parsed.data
1073
- });
1074
- if (!saved.saved) return c.json({ error: saved.error ?? "save failed" }, 500);
1075
- const updated = deps.service.currentConfig.userContext;
1076
- return c.json({ controls: {
1077
- mode: updated.memory.mode,
1078
- sensitiveWritePolicy: updated.privacy.sensitiveWritePolicy
1079
- } });
217
+ authenticated.patch("/api/you/rules/:id", write, async (c) => {
218
+ const id = c.req.param("id");
219
+ let rule = getCollaborationRule(id);
220
+ if (!rule) return c.json({ error: "Collaboration rule not found" }, 404);
221
+ const body = await readBody(c);
222
+ if (!body) return c.json({ error: "Invalid JSON" }, 400);
223
+ if (body.statement !== void 0) {
224
+ const statement = nonEmptyString(body.statement);
225
+ if (!statement) return c.json({ error: "statement must be 1-2000 characters" }, 400);
226
+ rule = reviseCollaborationRule(id, statement);
227
+ }
228
+ if (body.status !== void 0) {
229
+ if (!RULE_STATUSES.has(body.status)) return c.json({ error: "Invalid status" }, 400);
230
+ rule = setCollaborationRuleStatus(id, body.status);
231
+ }
232
+ return c.json({ rule });
233
+ });
234
+ authenticated.delete("/api/you/rules/:id", write, (c) => deleteCollaborationRule(c.req.param("id")) ? c.json({ ok: true }) : c.json({ error: "Collaboration rule not found" }, 404));
235
+ authenticated.get("/api/you/turns/:turnId/personalization", (c) => {
236
+ const personalization = getTurnPersonalization(c.req.param("turnId"));
237
+ return personalization ? c.json({ personalization }) : c.json({ error: "Personalization run not found" }, 404);
238
+ });
239
+ authenticated.post("/api/you/turns/:turnId/feedback", write, async (c) => {
240
+ const turnId = c.req.param("turnId");
241
+ const run = getTurnPersonalization(turnId);
242
+ if (!run) return c.json({ error: "Personalization run not found" }, 404);
243
+ const body = await readBody(c);
244
+ if (!body || !FEEDBACK_RATINGS.has(String(body.rating))) return c.json({ error: "Invalid feedback rating" }, 400);
245
+ const objectType = body.objectType;
246
+ const objectId = body.objectId;
247
+ if (objectType === void 0 !== (objectId === void 0) || objectType !== void 0 && ![
248
+ "profile",
249
+ "rule",
250
+ "understanding"
251
+ ].includes(String(objectType)) || objectId !== void 0 && typeof objectId !== "string") return c.json({ error: "objectType and objectId must be valid and provided together" }, 400);
252
+ if (objectType !== void 0 && !run.items.some((item) => item.objectType === objectType && item.objectId === objectId)) return c.json({ error: "The context object was not part of this turn" }, 400);
253
+ const rating = body.rating;
254
+ recordContextFeedback({
255
+ turnId,
256
+ runId: run.runId,
257
+ rating,
258
+ ...objectType ? {
259
+ objectType,
260
+ objectId
261
+ } : {},
262
+ ...typeof body.reason === "string" ? { reason: body.reason.slice(0, 500) } : {}
263
+ });
264
+ if (objectType === "understanding" && typeof objectId === "string") {
265
+ if (rating === "wrong") rejectUnderstanding(objectId, "Marked wrong from turn feedback");
266
+ if (rating === "stale") setUnderstandingStatus(objectId, "stale");
267
+ if (rating === "sensitive") setUnderstandingStatus(objectId, "needs_review");
268
+ }
269
+ return c.json({ ok: true });
1080
270
  });
1081
- authenticated.patch("/api/you/consents/:id", deps.strictRateLimitMiddleware, async (c) => {
1082
- const body = await c.req.json().catch(() => ({}));
1083
- const decision = typeof body.decision === "string" ? body.decision : "";
271
+ authenticated.patch("/api/you/consents/:id", write, async (c) => {
272
+ const decision = (await readBody(c))?.decision;
1084
273
  if (![
1085
274
  "once",
1086
275
  "session",
1087
276
  "always",
1088
277
  "deny"
1089
- ].includes(decision)) return c.json({ error: "Decision must be once, session, always, or deny" }, 400);
1090
- const consent = decideMemoryReferenceConsent(c.req.param("id"), decision);
1091
- if (!consent) return c.json({ error: "Pending consent not found" }, 404);
1092
- return c.json({
1093
- ok: true,
1094
- consent
1095
- });
1096
- });
1097
- authenticated.delete("/api/you/consents/:id", deps.strictRateLimitMiddleware, (c) => {
1098
- const consent = revokeMemoryReferenceConsent(c.req.param("id"));
1099
- if (!consent) return c.json({ error: "Active reference grant not found" }, 404);
1100
- return c.json({
1101
- ok: true,
1102
- consent
1103
- });
1104
- });
1105
- authenticated.delete("/api/you/sources/:instanceId", deps.strictRateLimitMiddleware, async (c) => {
1106
- const config = deps.service.currentConfig;
1107
- const instanceId = c.req.param("instanceId");
1108
- const installedInstances = listConnectorInstances(config);
1109
- const account = getConnectorAccount(instanceId);
1110
- const accountConnections = account ? listConnectorConnections({
1111
- principalId: account.principalId,
1112
- connectorId: account.connectorId
1113
- }).filter((connection) => connection.accountId === account.id) : [];
1114
- const instance = installedInstances.find((item) => item.instanceId === instanceId);
1115
- const connectorId = account?.connectorId ?? instance?.connectorId;
1116
- const definition = connectorId ? listConnectorCatalog().find((item) => item.id === connectorId) : void 0;
1117
- if (!instance && !account || !definition || !definition.capabilities.some((capability) => capability === "context" || capability === "memory_source")) return c.json({ error: "Personal context source not found" }, 404);
1118
- const body = await c.req.json().catch(() => ({}));
1119
- const understandingPolicy = body.understandingPolicy === "keep" || body.understandingPolicy === "delete" ? body.understandingPolicy : void 0;
1120
- if (!understandingPolicy) return c.json({ error: "understandingPolicy must be keep or delete" }, 400);
1121
- try {
1122
- if (account) for (const connection of accountConnections.filter((candidate) => candidate.status !== "revoked")) await revokeComposioConnection(connection.id);
1123
- else if (instance) {
1124
- uninstallConnector(config, instance.instanceId);
1125
- const saved = await deps.service.saveConfig(config);
1126
- if (!saved.saved) return c.json({ error: saved.error ?? "save failed" }, 500);
1127
- }
1128
- } catch (error) {
1129
- return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
1130
- }
1131
- let deletedUnderstandingCount = 0;
1132
- let deletedClaimCount = 0;
1133
- if (understandingPolicy === "delete") {
1134
- const sourceInstanceId = account ? `composio:${account.connectorId}:${account.id}` : instanceId;
1135
- const targets = recordsDerivedFromPersonalContextSource(listAllUserContextRecords(ALL_MEMORY_STATUSES), sourceInstanceId);
1136
- runSqliteWriteTransaction(() => {
1137
- const claimRemoval = removeUserClaimEvidenceForSource(sourceInstanceId);
1138
- deletedClaimCount = claimRemoval.deletedClaimCount;
1139
- const retainedMemoryIds = new Set(claimRemoval.retainedClaims.map((claim) => claim.memoryRecordId));
1140
- const deleteIds = new Set([...claimRemoval.deletedMemoryRecordIds, ...targets.filter((record) => !retainedMemoryIds.has(record.id)).map((record) => record.id)]);
1141
- for (const recordId of deleteIds) deleteMemoryRecord(recordId);
1142
- for (const retained of claimRemoval.retainedClaims) {
1143
- if (retained.state === "active") continue;
1144
- const record = getMemoryRecord(retained.memoryRecordId);
1145
- if (record) preserveRecord(record, { status: retained.state === "rejected" ? "rejected" : "stale" });
1146
- }
1147
- deletedUnderstandingCount = deleteIds.size;
1148
- });
1149
- }
1150
- return c.json({
1151
- ok: true,
1152
- deletedUnderstandingCount,
1153
- deletedClaimCount
1154
- });
1155
- });
1156
- authenticated.patch("/api/you/understanding/:id", deps.strictRateLimitMiddleware, async (c) => {
1157
- const existing = editableRecord(c.req.param("id"));
1158
- if (!existing) return c.json({ error: "Understanding not found" }, 404);
1159
- const body = await c.req.json().catch(() => ({}));
1160
- const action = typeof body.action === "string" ? body.action : "";
1161
- if (action === "confirm") return c.json({ understanding: projectUserContextRecord(preserveRecord(existing, {
1162
- status: "active",
1163
- reviewAfter: nextMemoryReviewAt(existing)
1164
- })) });
1165
- if (action === "reject") return c.json({ understanding: projectUserContextRecord(preserveRecord(existing, { status: "rejected" })) });
1166
- if (action === "update") {
1167
- const content = typeof body.content === "string" ? body.content.trim() : "";
1168
- if (!content) return c.json({ error: "Updated understanding cannot be empty" }, 400);
1169
- const replacement = upsertMemoryRecord({
1170
- providerId: "local",
1171
- kind: existing.kind,
1172
- sourceAgentId: existing.provenance.sourceAgentId,
1173
- workspaceId: existing.scope.workspaceId,
1174
- sessionKey: existing.scope.sessionKey,
1175
- projectId: existing.scope.projectId,
1176
- content,
1177
- source: { provider: "local" },
1178
- confidence: 1,
1179
- tags: [...new Set([
1180
- ...existing.tags ?? [],
1181
- "user-understanding",
1182
- "explicit-user-correction"
1183
- ])],
1184
- status: "active",
1185
- sensitivity: existing.sensitivity,
1186
- explicitness: "explicit",
1187
- durability: existing.durability,
1188
- importance: Math.max(existing.importance, .8),
1189
- disclosurePolicy: existing.disclosurePolicy,
1190
- evidence: existing.evidence,
1191
- reviewAfter: nextMemoryReviewAt({
1192
- durability: existing.durability,
1193
- explicitness: "explicit"
1194
- }),
1195
- supersedesRecordId: existing.id,
1196
- conflictGroupId: existing.conflictGroupId
1197
- });
1198
- preserveRecord(existing, {
1199
- status: "archived",
1200
- validTo: (/* @__PURE__ */ new Date()).toISOString()
1201
- });
1202
- return c.json({ understanding: projectUserContextRecord(replacement) });
1203
- }
1204
- return c.json({ error: "Action must be confirm, reject, or update" }, 400);
1205
- });
1206
- authenticated.delete("/api/you/understanding/:id", deps.strictRateLimitMiddleware, (c) => {
1207
- const existing = editableRecord(c.req.param("id"));
1208
- if (!existing) return c.json({ error: "Understanding not found" }, 404);
1209
- deleteMemoryRecord(existing.id);
1210
- return c.json({ ok: true });
278
+ ].includes(String(decision))) return c.json({ error: "Invalid consent decision" }, 400);
279
+ return decideContextConsent(c.req.param("id"), decision) ? c.json({ ok: true }) : c.json({ error: "Consent request not found" }, 404);
1211
280
  });
1212
281
  }
1213
282
  //#endregion
1214
- export { buildInsightSuggestions, buildPersonalPlaybooks, buildRoutineAutomationDraftHref, registerYouRoutes };
283
+ export { registerYouRoutes };