@xopcai/xopc 0.0.246 → 0.0.248

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 (199) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/src/update-offset-store.js +17 -54
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/extensions/weixin/src/auth/accounts.js +3 -5
  5. package/dist/extensions/weixin/src/monitor/monitor.js +3 -5
  6. package/dist/extensions/weixin/src/storage/sync-buf.d.ts +3 -6
  7. package/dist/extensions/weixin/src/storage/sync-buf.js +9 -22
  8. package/dist/gateway/static/root/assets/{activity-store-BlxqErph.js → activity-store-etpmyV7S.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CJJzpYYS.js → agent-avatar-dicebear-BmKxSM1k.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CUXApfcE.js +1 -0
  11. package/dist/gateway/static/root/assets/{agents-je3sRGmk.js → agents-DNq_GKuc.js} +1 -1
  12. package/dist/gateway/static/root/assets/{api-BbXzyQMj.js → api-B0-hLuZ1.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-Cnn3i00c.js → app-management-settings-panel-qfwAgyhQ.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-BToQaw_v.js → appearance-settings-DqQVUpCC.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-dwIqYmXk.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-DD2SweEH.js → archive-plugin-BnMSgZvR.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-BFtcib5t.js → attachment-load-CejsQMev.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-XS8wIl5o.js → automations-page-RC8EyoAf.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-SkdcSZ0i.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-Xs7pLHxR.js → binary-plugins-DGjppLSG.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-BPdSzceB.js → block-editor-CWdP4bUc.js} +44 -44
  22. package/dist/gateway/static/root/assets/browser-settings-page-CKCa6TvG.js +8 -0
  23. package/dist/gateway/static/root/assets/{browser-workflow-inputs-BAAc151l.js → browser-workflow-inputs-BQ1Ilw_o.js} +1 -1
  24. package/dist/gateway/static/root/assets/{browser-workflows-page-DUPPvE30.js → browser-workflows-page-CJh4NyxT.js} +2 -2
  25. package/dist/gateway/static/root/assets/{capabilities-settings-panel-cl9kYilL.js → capabilities-settings-panel-DSp--zIZ.js} +5 -5
  26. package/dist/gateway/static/root/assets/channels-settings-CMd2dDrI.js +1 -0
  27. package/dist/gateway/static/root/assets/{channels-status-swr-CCBCtLDg.js → channels-status-swr-Ohhee4vm.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-DKW1M6aJ.js → chat-terminal-dock-BOtoKTK3.js} +2 -2
  29. package/dist/gateway/static/root/assets/connectors-page-udWs5Kdm.js +2 -0
  30. package/dist/gateway/static/root/assets/{cron-expression-Bijb0ZQu.js → cron-expression-DTj1V3Sw.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-BZuHw-SY.js → date-picker-Yr6OCvGL.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-BsBD2JFY.js → dependency-picker-DpN3XZg9.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-Ceuw3QKb.js → desktop-pet-DbGzggPF.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-DctOXexM.js → desktop-pet-settings-DinCToZh.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-debug-page-BNlMPATK.js → extension-debug-page-DgTtk4KC.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-CK4Uvzge.js → extension-page-DtQeiP6f.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-CpnXXemw.js → extension-settings-page-DcguCgsH.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-C_mlpe-r.js → gateway-config-api-Br7lSf6H.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-826dipyU.js → gateway-config-swr-DXuXtU1w.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-settings-DSSW17ed.js → gateway-settings-CdPoDMuj.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-DyvcAIMm.js → gateway-startup-retry-CzBzglzQ.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-hbmIZTpg.js → heartbeat-settings-DHk1hawP.js} +1 -1
  43. package/dist/gateway/static/root/assets/home-page-YGipe_W6.js +1 -0
  44. package/dist/gateway/static/root/assets/{image-generation-api-D7cyfks6.js → image-generation-api-TIgsn04n.js} +1 -1
  45. package/dist/gateway/static/root/assets/{index-eZjksPvq.js → index-D5TQQpeb.js} +44 -44
  46. package/dist/gateway/static/root/assets/index-DReBaaTX.css +2 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQrDwwgi.js → keyboard-shortcuts-settings-wsWuoa8p.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-CpyvYyrb.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-D-YWD6LS.js → local-apps-page-CXrbrGo8.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-context-graph-BjUf7fQ9.js +1 -0
  51. package/dist/gateway/static/root/assets/{locale-store-CBoCuIMx.js → locale-store-BJFLQY8O.js} +1 -1
  52. package/dist/gateway/static/root/assets/{logs-page-DvLc9l59.js → logs-page-CXKy6E_l.js} +2 -2
  53. package/dist/gateway/static/root/assets/{management-settings-DsULLUUv.js → management-settings-BdJZFR7U.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-split-CjqlP6IB.js → markdown-split-NK3ACVG2.js} +1 -1
  55. package/dist/gateway/static/root/assets/{markdown-view-BXsHghJd.js → markdown-view-DTF9v1gg.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-DQL029DU.js → media-plugins-F0jcUxyl.js} +1 -1
  57. package/dist/gateway/static/root/assets/messages-CHNYp8EQ.js +3 -0
  58. package/dist/gateway/static/root/assets/{mobile-pairing-wizard-gauprAae.js → mobile-pairing-wizard-3NKCniSp.js} +1 -1
  59. package/dist/gateway/static/root/assets/models-hub-cache-nCfkBN8M.js +1 -0
  60. package/dist/gateway/static/root/assets/{notes-page-AsEfLZt9.js → notes-page-DuqLahi6.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-C7j9EdQk.js +5 -0
  62. package/dist/gateway/static/root/assets/{oauth-api-BjSUDIgq.js → oauth-api-8lP_qJpq.js} +1 -1
  63. package/dist/gateway/static/root/assets/{product-open-page-CAJeUXeU.js → product-open-page-CxGGlWA8.js} +1 -1
  64. package/dist/gateway/static/root/assets/project-detail-page-CfebYVX0.js +1 -0
  65. package/dist/gateway/static/root/assets/projects-page-48GvzSVa.js +1 -0
  66. package/dist/gateway/static/root/assets/{registry-api-BhGKnvLP.js → registry-api-CIsNlSBi.js} +1 -1
  67. package/dist/gateway/static/root/assets/remote-access-hub-64xj_s2m.js +1 -0
  68. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DH6EilMV.js → runtime-tools-settings-panel-YkjhiQfA.js} +2 -2
  69. package/dist/gateway/static/root/assets/{schema-form-DYHmEZeZ.js → schema-form-oFGf3G3s.js} +1 -1
  70. package/dist/gateway/static/root/assets/sessions-page-CcwcdRN8.js +1 -0
  71. package/dist/gateway/static/root/assets/settings-advanced-gate-BaN84CyW.js +1 -0
  72. package/dist/gateway/static/root/assets/{settings-page-BHwPd_M3.js → settings-page-C7VWs0IT.js} +1 -1
  73. package/dist/gateway/static/root/assets/setup-status-panel-DVVOCNbr.js +1 -0
  74. package/dist/gateway/static/root/assets/{share-preview-page-BjwrS03F.js → share-preview-page-t5oz18rh.js} +1 -1
  75. package/dist/gateway/static/root/assets/shares-settings-DUYbYLi7.js +1 -0
  76. package/dist/gateway/static/root/assets/skill-reload-api-BGyD0gB9.js +1 -0
  77. package/dist/gateway/static/root/assets/{skills-page-OHyK25op.js → skills-page-CjF8DTsN.js} +1 -1
  78. package/dist/gateway/static/root/assets/{skills-page.utils-DQx9ulmg.js → skills-page.utils-DEDTYs2W.js} +1 -1
  79. package/dist/gateway/static/root/assets/{system-settings-panel-wO7DWv4C.js → system-settings-panel-BSYuRgFI.js} +1 -1
  80. package/dist/gateway/static/root/assets/task-detail-page-YZYSTJH7.js +1 -0
  81. package/dist/gateway/static/root/assets/{theme-store-hybK3oC9.js → theme-store-O597U8q_.js} +1 -1
  82. package/dist/gateway/static/root/assets/{tunnel-api-CVC8BHZu.js → tunnel-api-FKUi9wDL.js} +1 -1
  83. package/dist/gateway/static/root/assets/{use-autosave-DMvRu2XZ.js → use-autosave-B5eUJ6Zq.js} +1 -1
  84. package/dist/gateway/static/root/assets/user-context-page-BCyiduKd.js +2 -0
  85. package/dist/gateway/static/root/assets/{voice-api-key-field-DuBK2NDG.js → voice-api-key-field-CMKSwz4C.js} +1 -1
  86. package/dist/gateway/static/root/assets/{voice-config-api-CBbiF1T3.js → voice-config-api-q7B6fOFB.js} +1 -1
  87. package/dist/gateway/static/root/assets/{work-discovery-overlay-B7VXWpDr.js → work-discovery-overlay-jhT2EzeH.js} +1 -1
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BokVAsWN.js → workflow-run-setup-panel-DZmvLZjb.js} +2 -2
  89. package/dist/gateway/static/root/assets/workflows-page-DQC0TpMa.js +5 -0
  90. package/dist/gateway/static/root/index.html +12 -12
  91. package/dist/package.js +1 -1
  92. package/dist/src/agent/commands/command-registry.d.ts +1 -0
  93. package/dist/src/agent/commands/command-registry.js +12 -22
  94. package/dist/src/agent/ipc/inbox.d.ts +8 -31
  95. package/dist/src/agent/ipc/inbox.js +64 -133
  96. package/dist/src/agent/service/process-direct-one-shot.js +15 -10
  97. package/dist/src/agent/workflow/catalog.d.ts +1 -8
  98. package/dist/src/agent/workflow/catalog.js +44 -102
  99. package/dist/src/agent/workflow/index.d.ts +1 -1
  100. package/dist/src/agent/workflow/index.js +2 -2
  101. package/dist/src/automations/domain/types.d.ts +1 -0
  102. package/dist/src/automations/service/action-executor.js +2 -2
  103. package/dist/src/automations/service/automation-service.js +2 -2
  104. package/dist/src/channels/manager.d.ts +1 -1
  105. package/dist/src/channels/manager.js +2 -2
  106. package/dist/src/channels/outbound/persist-store.d.ts +2 -8
  107. package/dist/src/channels/outbound/persist-store.js +11 -38
  108. package/dist/src/channels/outbound-sender.d.ts +1 -1
  109. package/dist/src/channels/outbound-sender.js +2 -2
  110. package/dist/src/cli/commands/connectors.js +1 -1
  111. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  112. package/dist/src/config/schema.js +2 -2
  113. package/dist/src/connectors/auth-provider-registry.js +1 -1
  114. package/dist/src/connectors/composio-triggers.d.ts +2 -2
  115. package/dist/src/connectors/composio-triggers.js +8 -15
  116. package/dist/src/connectors/connected-source-ingestion.js +1 -1
  117. package/dist/src/connectors/health.js +1 -1
  118. package/dist/src/gateway/automation-agent-session.js +3 -0
  119. package/dist/src/gateway/heartbeat/service.js +1 -1
  120. package/dist/src/gateway/hono/lib/extension-store.js +8 -25
  121. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  122. package/dist/src/gateway/hono/routes/connectors.js +3 -3
  123. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  124. package/dist/src/gateway/hono/routes/projects.js +1 -1
  125. package/dist/src/gateway/hono/routes/you.js +20 -4
  126. package/dist/src/gateway/service.js +4 -5
  127. package/dist/src/heartbeat/index.js +1 -1
  128. package/dist/src/notes/index.d.ts +1 -1
  129. package/dist/src/notes/index.js +2 -2
  130. package/dist/src/notes/paths.d.ts +0 -3
  131. package/dist/src/notes/paths.js +1 -10
  132. package/dist/src/notes/service.d.ts +0 -1
  133. package/dist/src/notes/service.js +0 -3
  134. package/dist/src/notes/store.d.ts +0 -2
  135. package/dist/src/notes/store.js +33 -80
  136. package/dist/src/share/hosted-session-share.d.ts +1 -4
  137. package/dist/src/share/hosted-session-share.js +14 -47
  138. package/dist/src/share/share-auto.d.ts +1 -1
  139. package/dist/src/share/share-auto.js +2 -2
  140. package/dist/src/share/share-store.d.ts +2 -7
  141. package/dist/src/share/share-store.js +153 -195
  142. package/dist/src/share/share-types.d.ts +0 -4
  143. package/dist/src/share/site-share-store.d.ts +3 -8
  144. package/dist/src/share/site-share-store.js +94 -153
  145. package/dist/src/share/site-share-types.d.ts +0 -4
  146. package/dist/src/storage/sqlite/connection.d.ts +1 -2
  147. package/dist/src/storage/sqlite/connection.js +50 -47
  148. package/dist/src/storage/sqlite/durable-queue.d.ts +16 -0
  149. package/dist/src/storage/sqlite/durable-queue.js +52 -0
  150. package/dist/src/storage/sqlite/durable-state.d.ts +16 -0
  151. package/dist/src/storage/sqlite/durable-state.js +43 -0
  152. package/dist/src/storage/sqlite/migrations/146_understanding_focus_exclusions.sql +9 -0
  153. package/dist/src/storage/sqlite/migrations/147_durable_application_state.sql +39 -0
  154. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  155. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  156. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  157. package/dist/src/storage/sqlite/schema.js +1 -1
  158. package/dist/src/storage/sqlite/understanding-focus-exclusions.d.ts +2 -0
  159. package/dist/src/storage/sqlite/understanding-focus-exclusions.js +24 -0
  160. package/dist/src/tui/tui-scoped-models.js +9 -6
  161. package/dist/src/tui/tui-startup-resources.js +1 -1
  162. package/dist/src/voice/dashscope/streaming-tts-stream.js +49 -0
  163. package/dist/src/voice/realtime/agentEngine.js +63 -18
  164. package/dist/src/voice/realtime/conversationTurn.d.ts +20 -0
  165. package/dist/src/voice/realtime/conversationTurn.js +83 -0
  166. package/dist/src/voice/realtime/omniEngine.js +72 -18
  167. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +1 -5
  168. package/dist/src/workflows/authoring/workflow-draft-store.js +23 -43
  169. package/dist/src/workflows/index.js +2 -2
  170. package/dist/src/workflows/store/event-store.d.ts +1 -2
  171. package/dist/src/workflows/store/event-store.js +19 -64
  172. package/dist/src/workflows/store/paths.d.ts +0 -2
  173. package/dist/src/workflows/store/paths.js +1 -7
  174. package/dist/src/workflows/store/run-store.d.ts +0 -1
  175. package/dist/src/workflows/store/run-store.js +1 -24
  176. package/package.json +3 -3
  177. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-0dRjnL2s.js +0 -1
  178. package/dist/gateway/static/root/assets/apps-page-EpUZsl4h.js +0 -1
  179. package/dist/gateway/static/root/assets/automations-workspace-BGQdHrip.js +0 -6
  180. package/dist/gateway/static/root/assets/browser-settings-page-DJGcm7rH.js +0 -8
  181. package/dist/gateway/static/root/assets/channels-settings-BcIr-_GM.js +0 -1
  182. package/dist/gateway/static/root/assets/connectors-page-DNHqaZfX.js +0 -2
  183. package/dist/gateway/static/root/assets/home-page-CaVvW77l.js +0 -1
  184. package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +0 -2
  185. package/dist/gateway/static/root/assets/local-app-workbench-page-D3K1XmOM.js +0 -2
  186. package/dist/gateway/static/root/assets/messages-BbdwoxVo.js +0 -3
  187. package/dist/gateway/static/root/assets/models-hub-cache-88f4fzYS.js +0 -1
  188. package/dist/gateway/static/root/assets/notes-workbench-CI30cDh3.js +0 -4
  189. package/dist/gateway/static/root/assets/project-detail-page-jO_4I5zN.js +0 -1
  190. package/dist/gateway/static/root/assets/projects-page-BrTGFME0.js +0 -1
  191. package/dist/gateway/static/root/assets/remote-access-hub-CH70D5SH.js +0 -1
  192. package/dist/gateway/static/root/assets/sessions-page-hbfUNtNs.js +0 -1
  193. package/dist/gateway/static/root/assets/settings-advanced-gate-Vg3_jua6.js +0 -1
  194. package/dist/gateway/static/root/assets/setup-status-panel-DkcpWSss.js +0 -1
  195. package/dist/gateway/static/root/assets/shares-settings-BL4DEt6p.js +0 -1
  196. package/dist/gateway/static/root/assets/skill-reload-api-CafhNktn.js +0 -1
  197. package/dist/gateway/static/root/assets/task-detail-page-anyomXsu.js +0 -1
  198. package/dist/gateway/static/root/assets/user-context-page-BBk9YdBn.js +0 -1
  199. package/dist/gateway/static/root/assets/workflows-page-RUTv0yvR.js +0 -5
@@ -1,36 +1,19 @@
1
- import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
1
+ import { requireXopcDatabase } from "../../storage/sqlite/connection.js";
2
+ import { runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
3
+ import { DurableState } from "../../storage/sqlite/durable-state.js";
2
4
  import { buildWorkflowDefinition } from "../../workflows/domain/definition-utils.js";
3
5
  import { validateWorkflowGraph } from "../../workflows/domain/validation.js";
4
6
  import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
5
- import { join } from "node:path";
6
- import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
7
- import { randomUUID } from "node:crypto";
8
7
  //#region src/agent/workflow/catalog.ts
9
- init_paths_state();
10
8
  const NAME_RE = /^[a-z][a-z0-9_-]*$/;
11
- function createWorkflowCatalog(opts = {}) {
12
- const userDir = opts.userDir ?? defaultUserDir();
13
- const loadUser = (name) => {
14
- const path = join(userDir, `${name}.json`);
15
- if (!existsSync(path)) return null;
16
- const parsed = JSON.parse(readFileSync(path, "utf-8"));
17
- assertStoredDefinition(parsed, name, path);
18
- return parsed;
19
- };
9
+ function createWorkflowCatalog() {
10
+ const definitions = new DurableState("workflow-definitions");
11
+ const revisions = (name) => new DurableState("workflow-revisions", name);
12
+ const loadUser = (name) => definitions.get(name) ?? null;
20
13
  const list = () => {
21
- const definitions = /* @__PURE__ */ new Map();
22
- for (const definition of BUILTIN_WORKFLOWS) definitions.set(definition.name, {
23
- definition,
24
- path: null
25
- });
26
- for (const name of listUserNames(userDir)) try {
27
- const definition = loadUser(name);
28
- if (definition) definitions.set(name, {
29
- definition,
30
- path: join(userDir, `${name}.json`)
31
- });
32
- } catch {}
33
- return [...definitions.values()].map(({ definition, path }) => toCatalogEntry(definition, path)).sort((left, right) => left.name.localeCompare(right.name));
14
+ const items = new Map(BUILTIN_WORKFLOWS.map((definition) => [definition.name, definition]));
15
+ for (const definition of definitions.values()) items.set(definition.name, definition);
16
+ return [...items.values()].map(toCatalogEntry).sort((a, b) => a.name.localeCompare(b.name));
34
17
  };
35
18
  const load = (name) => {
36
19
  requireValidName(name);
@@ -45,56 +28,40 @@ function createWorkflowCatalog(opts = {}) {
45
28
  requireValidName(name);
46
29
  const validation = validateWorkflowGraph(input.graph);
47
30
  if (!validation.valid) throw new Error(validation.errors.map((issue) => issue.message).join(" "));
48
- const existing = loadUser(name);
49
- const builtin = BUILTIN_WORKFLOWS.find((definition) => definition.name === name);
50
- if (input.intent === "create" && (existing || builtin)) throw new WorkflowNameConflictError(name, existing?.revision ?? builtin?.revision ?? 0);
51
- if (input.expectedRevision !== void 0 && input.expectedRevision !== (existing?.revision ?? 0)) throw new WorkflowRevisionConflictError(existing?.revision ?? 0);
52
- const definition = buildWorkflowDefinition({
53
- name,
54
- source: "user",
55
- graph: input.graph,
56
- manifest: input.manifest,
57
- revision: (existing?.revision ?? 0) + 1,
58
- createdAtMs: existing?.metadata.createdAtMs
31
+ requireXopcDatabase();
32
+ return runSqliteWriteTransaction(() => {
33
+ const existing = loadUser(name);
34
+ const builtin = BUILTIN_WORKFLOWS.find((definition) => definition.name === name);
35
+ if (input.intent === "create" && (existing || builtin)) throw new WorkflowNameConflictError(name, existing?.revision ?? builtin?.revision ?? 0);
36
+ if (input.expectedRevision !== void 0 && input.expectedRevision !== (existing?.revision ?? 0)) throw new WorkflowRevisionConflictError(existing?.revision ?? 0);
37
+ const definition = buildWorkflowDefinition({
38
+ name,
39
+ source: "user",
40
+ graph: input.graph,
41
+ manifest: input.manifest,
42
+ revision: (existing?.revision ?? 0) + 1,
43
+ createdAtMs: existing?.metadata.createdAtMs
44
+ });
45
+ revisions(name).set(String(definition.revision), definition);
46
+ definitions.set(name, definition);
47
+ return { definition };
59
48
  });
60
- if (!existsSync(userDir)) mkdirSync(userDir, { recursive: true });
61
- const path = join(userDir, `${name}.json`);
62
- const revisionsDir = join(userDir, ".revisions", name);
63
- mkdirSync(revisionsDir, { recursive: true });
64
- writeJsonAtomic(join(revisionsDir, `${definition.revision}.json`), definition);
65
- writeJsonAtomic(path, definition);
66
- return {
67
- path,
68
- definition
69
- };
70
49
  };
71
50
  const listRevisions = (name) => {
72
51
  requireValidName(name);
73
- const dir = join(userDir, ".revisions", name);
74
- if (!existsSync(dir)) return [];
75
- return readdirSync(dir).filter((file) => /^\d+\.json$/.test(file)).map((file) => {
76
- try {
77
- const definition = JSON.parse(readFileSync(join(dir, file), "utf-8"));
78
- assertStoredDefinition(definition, name, join(dir, file));
79
- return {
80
- revision: definition.revision,
81
- title: definition.title,
82
- contentHash: definition.contentHash,
83
- createdAtMs: definition.metadata.updatedAtMs
84
- };
85
- } catch {
86
- return null;
87
- }
88
- }).filter((item) => item !== null).sort((left, right) => right.revision - left.revision);
52
+ return revisions(name).values().map((definition) => ({
53
+ revision: definition.revision,
54
+ title: definition.title,
55
+ contentHash: definition.contentHash,
56
+ createdAtMs: definition.metadata.updatedAtMs
57
+ })).sort((a, b) => b.revision - a.revision);
89
58
  };
90
59
  const loadRevision = (name, revision) => {
91
60
  requireValidName(name);
92
61
  if (!Number.isSafeInteger(revision) || revision < 1) throw new Error("invalid workflow revision");
93
- const path = join(userDir, ".revisions", name, `${revision}.json`);
94
- if (!existsSync(path)) throw new Error(`workflow revision not found: ${name}@${revision}`);
95
- const definition = JSON.parse(readFileSync(path, "utf-8"));
96
- assertStoredDefinition(definition, name, path);
97
- return structuredClone(definition);
62
+ const definition = revisions(name).get(String(revision));
63
+ if (!definition) throw new Error(`workflow revision not found: ${name}@${revision}`);
64
+ return definition;
98
65
  };
99
66
  const restore = (name, revision, expectedRevision) => {
100
67
  const selected = loadRevision(name, revision);
@@ -107,15 +74,12 @@ function createWorkflowCatalog(opts = {}) {
107
74
  };
108
75
  const remove = (name) => {
109
76
  requireValidName(name);
110
- const path = join(userDir, `${name}.json`);
111
- if (!existsSync(path)) return false;
112
- unlinkSync(path);
113
- const revisionsDir = join(userDir, ".revisions", name);
114
- if (existsSync(revisionsDir)) rmSync(revisionsDir, {
115
- recursive: true,
116
- force: true
77
+ requireXopcDatabase();
78
+ return runSqliteWriteTransaction(() => {
79
+ const deleted = definitions.delete(name);
80
+ for (const [key] of revisions(name).entries()) revisions(name).delete(key);
81
+ return deleted;
117
82
  });
118
- return true;
119
83
  };
120
84
  return {
121
85
  list,
@@ -124,8 +88,7 @@ function createWorkflowCatalog(opts = {}) {
124
88
  listRevisions,
125
89
  loadRevision,
126
90
  restore,
127
- remove,
128
- userDir
91
+ remove
129
92
  };
130
93
  }
131
94
  var WorkflowRevisionConflictError = class extends Error {
@@ -143,26 +106,10 @@ var WorkflowNameConflictError = class extends Error {
143
106
  this.name = "WorkflowNameConflictError";
144
107
  }
145
108
  };
146
- function defaultUserDir() {
147
- return join(resolveStateDir(), "workflows");
148
- }
149
- function listUserNames(dir) {
150
- try {
151
- if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
152
- return readdirSync(dir).filter((file) => file.endsWith(".json")).map((file) => file.slice(0, -5)).filter((name) => NAME_RE.test(name));
153
- } catch {
154
- return [];
155
- }
156
- }
157
- function assertStoredDefinition(value, name, path) {
158
- if (!value || typeof value !== "object" || value.name !== name || value.metadata?.source !== "user") throw new Error(`invalid workflow definition: ${path}`);
159
- if (!validateWorkflowGraph(value.graph).valid) throw new Error(`invalid workflow graph: ${path}`);
160
- }
161
- function toCatalogEntry(definition, path) {
109
+ function toCatalogEntry(definition) {
162
110
  return {
163
111
  name: definition.name,
164
112
  source: definition.metadata.source,
165
- path,
166
113
  description: definition.description,
167
114
  title: definition.title,
168
115
  version: definition.version,
@@ -175,11 +122,6 @@ function toCatalogEntry(definition, path) {
175
122
  function requireValidName(name) {
176
123
  if (!NAME_RE.test(name)) throw new Error(`invalid workflow name "${name}"; use lowercase letters, numbers, underscores, or hyphens`);
177
124
  }
178
- function writeJsonAtomic(path, value) {
179
- const temporaryPath = `${path}.${randomUUID()}.tmp`;
180
- writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
181
- renameSync(temporaryPath, path);
182
- }
183
125
  function definitionToManifest(definition) {
184
126
  return {
185
127
  title: definition.title,
@@ -199,4 +141,4 @@ function definitionToManifest(definition) {
199
141
  };
200
142
  }
201
143
  //#endregion
202
- export { WorkflowNameConflictError, WorkflowRevisionConflictError, createWorkflowCatalog, defaultUserDir };
144
+ export { WorkflowNameConflictError, WorkflowRevisionConflictError, createWorkflowCatalog };
@@ -1,6 +1,6 @@
1
1
  export { applySubagentProgress } from './agent-progress.js';
2
2
  export { BUILTIN_WORKFLOWS } from './builtins/index.js';
3
- export { createWorkflowCatalog, defaultUserDir, type CatalogEntry, type SaveWorkflowInput, type WorkflowCatalog, type WorkflowSource, } from './catalog.js';
3
+ export { createWorkflowCatalog, type CatalogEntry, type SaveWorkflowInput, type WorkflowCatalog, type WorkflowSource, } from './catalog.js';
4
4
  export type { ChannelProgressCapability, WorkflowProgressMode, WorkflowProgressPostInput, WorkflowProgressPostResult, } from './channel-capability.js';
5
5
  export { WorkflowProgressBroker, getWorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, type BrokerListenerHandle, type SessionBusLike, } from './progress-broker.js';
6
6
  export { emptySnapshotFor } from './snapshot-empty.js';
@@ -1,9 +1,9 @@
1
1
  import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
2
- import { createWorkflowCatalog, defaultUserDir } from "./catalog.js";
2
+ import { createWorkflowCatalog } from "./catalog.js";
3
3
  import { applySubagentProgress } from "./agent-progress.js";
4
4
  import { emptySnapshotFor } from "./snapshot-empty.js";
5
5
  import { createWorkflowSnapshot, previewValue, recomputeCounts, renderWorkflowText } from "./snapshot.js";
6
6
  import { WorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, getWorkflowProgressBroker } from "./progress-broker.js";
7
7
  import { STRUCTURED_OUTPUT_TOOL_NAME, createStructuredOutputTool } from "./structured-output-tool.js";
8
8
  import { DelegateSubagentRunner } from "./subagent-runner.js";
9
- export { BUILTIN_WORKFLOWS, DelegateSubagentRunner, STRUCTURED_OUTPUT_TOOL_NAME, WorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, applySubagentProgress, createStructuredOutputTool, createWorkflowCatalog, createWorkflowSnapshot, defaultUserDir, emptySnapshotFor, getWorkflowProgressBroker, previewValue, recomputeCounts, renderWorkflowText };
9
+ export { BUILTIN_WORKFLOWS, DelegateSubagentRunner, STRUCTURED_OUTPUT_TOOL_NAME, WorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, applySubagentProgress, createStructuredOutputTool, createWorkflowCatalog, createWorkflowSnapshot, emptySnapshotFor, getWorkflowProgressBroker, previewValue, recomputeCounts, renderWorkflowText };
@@ -163,6 +163,7 @@ export interface AutomationMetrics {
163
163
  };
164
164
  }
165
165
  export interface PrepareAutomationAgentSessionInput {
166
+ automationName?: string;
166
167
  sessionKey: string;
167
168
  projectId?: string;
168
169
  agentId: string;
@@ -3,7 +3,6 @@ import { init_logger } from "../../utils/logger.js";
3
3
  import { init_agent_scope, normalizeAgentId } from "../../agent/agent-scope.js";
4
4
  import { buildSessionKey, init_session_key } from "../../routing/session-key.js";
5
5
  import { resolveAutomationTimeoutSeconds } from "../domain/defaults.js";
6
- import crypto from "node:crypto";
7
6
  //#region src/automations/service/action-executor.ts
8
7
  init_agent_scope();
9
8
  init_session_key();
@@ -158,7 +157,7 @@ var AutomationActionExecutor = class {
158
157
  error: "Agent service is not available"
159
158
  };
160
159
  const agentId = normalizeAgentId(action.agentId || this.deps.getDefaultAgentId?.() || "main");
161
- const peerId = automation.conversationMode === "continuous" ? automation.id : `${automation.id}-${crypto.randomUUID().slice(0, 8)}`;
160
+ const peerId = automation.conversationMode === "continuous" ? automation.id : `${automation.id}-${run.id}`;
162
161
  const sessionKey = buildSessionKey({
163
162
  agentId,
164
163
  source: "automation",
@@ -171,6 +170,7 @@ var AutomationActionExecutor = class {
171
170
  currentPhase: "action"
172
171
  });
173
172
  await this.deps.prepareAgentSession?.({
173
+ automationName: automation.name,
174
174
  sessionKey,
175
175
  projectId: automation.projectId,
176
176
  agentId,
@@ -365,7 +365,7 @@ var AutomationService = class {
365
365
  this.appendRunEvent(run, status === "succeeded" ? "action.completed" : "action.failed", status === "succeeded" ? `${automation.action.kind} action completed` : `${automation.action.kind} action ${status}`, {
366
366
  summary: task.summary,
367
367
  error: task.error,
368
- sessionKey: task.sessionKey,
368
+ sessionKey: task.sessionKey ?? run.sessionKey,
369
369
  workflowRunId: task.workflowRunId,
370
370
  model: task.model
371
371
  });
@@ -374,7 +374,7 @@ var AutomationService = class {
374
374
  status,
375
375
  summary: task.summary,
376
376
  error,
377
- sessionKey: task.sessionKey,
377
+ sessionKey: task.sessionKey ?? run.sessionKey,
378
378
  workflowRunId: task.workflowRunId,
379
379
  model: task.model,
380
380
  deadlineAtMs: task.deadlineAtMs ?? run.deadlineAtMs,
@@ -32,7 +32,7 @@ export declare class ChannelManager {
32
32
  setOutboundHooks(hooks: OutboundChannelHooks): void;
33
33
  /** Call before `initialize()` so plugins can persist per-session model overrides. */
34
34
  setSessionModelHooks(hooks: ChannelPluginSessionModelHooks | undefined): void;
35
- enableOutboundPersistence(agentDir: string): void;
35
+ enableOutboundPersistence(agentId: string): void;
36
36
  registerPlugin(plugin: ChannelPlugin): void;
37
37
  getPlugin(id: string): ChannelPlugin | undefined;
38
38
  getAllPlugins(): ChannelPlugin[];
@@ -45,8 +45,8 @@ var ChannelManager = class {
45
45
  setSessionModelHooks(hooks) {
46
46
  this.sessionModelHooks = hooks;
47
47
  }
48
- enableOutboundPersistence(agentDir) {
49
- this.outbound.enablePersistence(agentDir);
48
+ enableOutboundPersistence(agentId) {
49
+ this.outbound.enablePersistence(agentId);
50
50
  }
51
51
  registerPlugin(plugin) {
52
52
  this.registry.register(plugin);
@@ -1,6 +1,3 @@
1
- /**
2
- * Durable outbound queue (crash recovery): JSON file under agent internal dir.
3
- */
4
1
  import type { OutboundMessage } from '../transport-types.js';
5
2
  export interface PendingOutbound {
6
3
  id: string;
@@ -8,11 +5,8 @@ export interface PendingOutbound {
8
5
  message: OutboundMessage;
9
6
  }
10
7
  export declare class OutboundPersistStore {
11
- private readonly filePath;
12
- private pending;
13
- constructor(agentDir: string);
14
- private load;
15
- private flush;
8
+ private readonly queue;
9
+ constructor(scope: string);
16
10
  enqueue(message: OutboundMessage): string;
17
11
  ack(id: string): void;
18
12
  peek(): readonly PendingOutbound[];
@@ -1,52 +1,25 @@
1
- import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
- import { join } from "path";
3
- import { existsSync, mkdirSync, readFileSync } from "fs";
1
+ import { DurableQueue } from "../../storage/sqlite/durable-queue.js";
4
2
  import { randomUUID } from "node:crypto";
5
3
  //#region src/channels/outbound/persist-store.ts
6
- /**
7
- * Durable outbound queue (crash recovery): JSON file under agent internal dir.
8
- */
9
- init_write_file_atomic();
10
4
  var OutboundPersistStore = class {
11
- filePath;
12
- pending = [];
13
- constructor(agentDir) {
14
- mkdirSync(agentDir, { recursive: true });
15
- this.filePath = join(agentDir, "outbound-pending.json");
16
- this.load();
17
- }
18
- load() {
19
- if (!existsSync(this.filePath)) return;
20
- try {
21
- const raw = readFileSync(this.filePath, "utf-8");
22
- const data = JSON.parse(raw);
23
- if (Array.isArray(data)) this.pending = data;
24
- } catch {
25
- this.pending = [];
26
- }
27
- }
28
- flush() {
29
- writeTextAtomicSync(this.filePath, JSON.stringify(this.pending));
5
+ queue;
6
+ constructor(scope) {
7
+ this.queue = new DurableQueue("outbound", scope);
30
8
  }
31
9
  enqueue(message) {
32
- const id = randomUUID();
33
- this.pending.push({
34
- id,
10
+ const entry = {
11
+ id: randomUUID(),
35
12
  enqueuedAt: Date.now(),
36
13
  message
37
- });
38
- this.flush();
39
- return id;
14
+ };
15
+ this.queue.enqueue(entry.id, entry, entry.enqueuedAt);
16
+ return entry.id;
40
17
  }
41
18
  ack(id) {
42
- const i = this.pending.findIndex((p) => p.id === id);
43
- if (i >= 0) {
44
- this.pending.splice(i, 1);
45
- this.flush();
46
- }
19
+ this.queue.delete(id);
47
20
  }
48
21
  peek() {
49
- return this.pending;
22
+ return this.queue.pending();
50
23
  }
51
24
  };
52
25
  //#endregion
@@ -37,7 +37,7 @@ export declare class ChannelOutboundSender {
37
37
  private persistStore?;
38
38
  constructor(opts: ChannelOutboundSenderOptions);
39
39
  setHooks(hooks: OutboundChannelHooks): void;
40
- enablePersistence(agentDir: string): void;
40
+ enablePersistence(agentId: string): void;
41
41
  /**
42
42
  * Redeliver every queued outbound item (called after channels are started).
43
43
  * Best-effort — may duplicate if the prior send succeeded but ack did not
@@ -18,8 +18,8 @@ var ChannelOutboundSender = class {
18
18
  setHooks(hooks) {
19
19
  this.hooks = hooks;
20
20
  }
21
- enablePersistence(agentDir) {
22
- this.persistStore = new OutboundPersistStore(agentDir);
21
+ enablePersistence(agentId) {
22
+ this.persistStore = new OutboundPersistStore(agentId);
23
23
  }
24
24
  /**
25
25
  * Redeliver every queued outbound item (called after channels are started).
@@ -1,6 +1,6 @@
1
1
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
2
- import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
3
2
  import { register } from "../registry.js";
3
+ import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
4
4
  import { confirm } from "@inquirer/prompts";
5
5
  import { Command } from "commander";
6
6
  //#region src/cli/commands/connectors.ts
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v145).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v147).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -804,7 +804,7 @@ activityDetailDefault: z.enum([
804
804
  realtime: z.object({
805
805
  enabled: z.boolean().default(false),
806
806
  defaultEngine: z.enum(["agent", "omni"]).default("agent"),
807
- silenceDurationMs: z.number().int().min(300).max(2e3).default(700),
807
+ silenceDurationMs: z.number().int().min(300).max(2e3).default(1200),
808
808
  idleTimeoutMs: z.number().int().min(1e4).max(3e5).default(6e4),
809
809
  maxDictationMs: z.number().int().min(1e4).max(36e5).default(6e5),
810
810
  maxConversationMs: z.number().int().min(1e4).max(72e5).default(36e5),
@@ -825,7 +825,7 @@ activityDetailDefault: z.enum([
825
825
  }).strict().default({
826
826
  enabled: false,
827
827
  defaultEngine: "agent",
828
- silenceDurationMs: 700,
828
+ silenceDurationMs: 1200,
829
829
  idleTimeoutMs: 6e4,
830
830
  maxDictationMs: 6e5,
831
831
  maxConversationMs: 36e5,
@@ -1,7 +1,7 @@
1
1
  import { startComposioAuthorize } from "./composio.js";
2
+ import { getMcpOAuthManager } from "../agent/mcp/oauth/mcp-oauth-manager.js";
2
3
  import { isManagedConnectorServer } from "./materialize.js";
3
4
  import { getConnectorInstance } from "./instances.js";
4
- import { getMcpOAuthManager } from "../agent/mcp/oauth/mcp-oauth-manager.js";
5
5
  //#region src/connectors/auth-provider-registry.ts
6
6
  async function startConnectorAuthorization(definition, config, instanceId) {
7
7
  if (definition.auth.mode !== "oauth") throw new Error(`Connector "${definition.id}" does not use OAuth.`);
@@ -23,5 +23,5 @@ export declare function normalizeComposioTriggerPayload(payload: unknown, webhoo
23
23
  data: Record<string, unknown>;
24
24
  };
25
25
  export declare function applyComposioConnectionLifecycleEvent(payload: unknown): string | undefined;
26
- export declare function appendComposioTriggerEvent(config: Config, payload: unknown): Promise<ComposioTriggerArchiveEntry>;
27
- export declare function listComposioTriggerEvents(config: Config, limit?: number): Promise<ComposioTriggerArchiveEntry[]>;
26
+ export declare function appendComposioTriggerEvent(_config: Config, payload: unknown): Promise<ComposioTriggerArchiveEntry>;
27
+ export declare function listComposioTriggerEvents(_config: Config, limit?: number): Promise<ComposioTriggerArchiveEntry[]>;
@@ -1,12 +1,7 @@
1
1
  import { listConnectorConnections, upsertConnectorConnection } from "../storage/sqlite/connector-repository.js";
2
- import { getWorkspacePath } from "../config/workspace-path-helpers.js";
3
- import { dirname, join } from "node:path";
2
+ import { DurableState } from "../storage/sqlite/durable-state.js";
4
3
  import crypto, { createHmac, timingSafeEqual } from "node:crypto";
5
- import { appendFile, mkdir, readFile } from "node:fs/promises";
6
4
  //#region src/connectors/composio-triggers.ts
7
- function archivePath(config) {
8
- return join(getWorkspacePath(config) || "./workspace", "state", "connectors", "composio-triggers.jsonl");
9
- }
10
5
  function readString(value) {
11
6
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
12
7
  }
@@ -50,7 +45,7 @@ function applyComposioConnectionLifecycleEvent(payload) {
50
45
  });
51
46
  return connection.id;
52
47
  }
53
- async function appendComposioTriggerEvent(config, payload) {
48
+ async function appendComposioTriggerEvent(_config, payload) {
54
49
  const record = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
55
50
  const normalized = normalizeComposioTriggerPayload(payload);
56
51
  const entry = {
@@ -60,15 +55,13 @@ async function appendComposioTriggerEvent(config, payload) {
60
55
  trigger: normalized.trigger ?? normalized.type,
61
56
  payload
62
57
  };
63
- const path = archivePath(config);
64
- await mkdir(dirname(path), { recursive: true });
65
- const existing = (await listComposioTriggerEvents(config, 500)).find((candidate) => candidate.id === entry.id);
66
- if (existing) return existing;
67
- await appendFile(path, `${JSON.stringify(entry)}\n`, "utf8");
68
- return entry;
58
+ return new DurableState("composio-events").update(entry.id, (existing) => ({
59
+ value: existing ?? entry,
60
+ result: existing ?? entry
61
+ }));
69
62
  }
70
- async function listComposioTriggerEvents(config, limit = 50) {
71
- return (await readFile(archivePath(config), "utf8").catch(() => "")).split("\n").filter(Boolean).slice(-Math.max(1, Math.min(limit, 500))).map((line) => JSON.parse(line)).reverse();
63
+ async function listComposioTriggerEvents(_config, limit = 50) {
64
+ return new DurableState("composio-events").values(Math.max(1, Math.min(Math.floor(limit) || 50, 500)), true);
72
65
  }
73
66
  //#endregion
74
67
  export { appendComposioTriggerEvent, applyComposioConnectionLifecycleEvent, listComposioTriggerEvents, normalizeComposioTriggerPayload, verifyComposioWebhook };
@@ -6,8 +6,8 @@ import { ComposioSessionsAdapter } from "./composio-sessions.js";
6
6
  import { decodeConnectedSourceCursor, encodeConnectedSourceCursor } from "./connected-source-cursor.js";
7
7
  import { scopeForComposioAction } from "./composio.js";
8
8
  import { getConnectorDefinition } from "./catalog.js";
9
- import { getConnectorInstance } from "./instances.js";
10
9
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
10
+ import { getConnectorInstance } from "./instances.js";
11
11
  import { KnowledgeIngestionService } from "../knowledge/ingestion-service.js";
12
12
  import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
13
13
  import { LocalFolderKnowledgeSourceAdapter } from "../knowledge/local-folder-adapter.js";
@@ -1,6 +1,6 @@
1
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
1
2
  import { materializeConnectorMcpServer } from "./materialize.js";
2
3
  import { getConnectorInstance } from "./instances.js";
3
- import { getWorkspacePath } from "../config/workspace-path-helpers.js";
4
4
  import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-gateway.js";
5
5
  //#region src/connectors/health.ts
6
6
  function classifyConnectorHealthError(error) {
@@ -1,6 +1,9 @@
1
1
  //#region src/gateway/automation-agent-session.ts
2
2
  async function prepareAutomationAgentSession(store, projects, input) {
3
3
  await store.resolveTranscriptPath(input.sessionKey, { metadata: {
4
+ hiddenFromSessionList: true,
5
+ name: input.automationName,
6
+ customData: { titleSource: "provisional" },
4
7
  projectId: input.projectId,
5
8
  sourceChannel: "automation",
6
9
  sourceChatId: `default:dm:${input.peerId}`,
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
4
- import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
5
4
  import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
6
5
  import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
6
+ import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
7
7
  import { createHeartbeatWake } from "../../heartbeat/wake.js";
8
8
  import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
9
9
  import { readFile } from "fs/promises";
@@ -1,33 +1,16 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
- import { readFile } from "node:fs/promises";
1
+ import { DurableState } from "../../../storage/sqlite/durable-state.js";
5
2
  //#region src/gateway/hono/lib/extension-store.ts
6
- init_write_file_atomic();
7
- /** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */
8
- const extensionStoreCache = /* @__PURE__ */ new Map();
9
- function getExtensionStorePath(namespace) {
10
- const safeNamespace = namespace.replace(/[^a-zA-Z0-9_-]/g, "_");
11
- return join(homedir(), ".xopc", "extensions", safeNamespace, "storage.json");
3
+ const state = new DurableState("extension-ui");
4
+ function validateNamespace(namespace) {
5
+ if (!namespace.trim()) throw new Error("Extension namespace is required");
12
6
  }
13
7
  async function loadExtensionStore(namespace) {
14
- const cached = extensionStoreCache.get(namespace);
15
- if (cached) return cached;
16
- const filePath = getExtensionStorePath(namespace);
17
- try {
18
- const raw = await readFile(filePath, "utf-8");
19
- const data = JSON.parse(raw);
20
- extensionStoreCache.set(namespace, data);
21
- return data;
22
- } catch {
23
- const empty = {};
24
- extensionStoreCache.set(namespace, empty);
25
- return empty;
26
- }
8
+ validateNamespace(namespace);
9
+ return state.get(namespace) ?? {};
27
10
  }
28
11
  async function saveExtensionStore(namespace, data) {
29
- await writeTextAtomic(getExtensionStorePath(namespace), JSON.stringify(data, null, 2));
30
- extensionStoreCache.set(namespace, data);
12
+ validateNamespace(namespace);
13
+ state.set(namespace, data);
31
14
  }
32
15
  //#endregion
33
16
  export { loadExtensionStore, saveExtensionStore };
@@ -1,5 +1,5 @@
1
- import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../../capabilities/store-connector.js";
2
1
  import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
2
+ import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../../capabilities/store-connector.js";
3
3
  //#region src/gateway/hono/routes/capabilities.ts
4
4
  function errorMessage(error) {
5
5
  return error instanceof Error ? error.message : String(error);
@@ -12,17 +12,17 @@ import { configureComposioApiKey, executeComposioTool, getComposioInstallationPo
12
12
  import { listConnectorProviders } from "../../../connectors/providers.js";
13
13
  import { getConnectorDefinition, listConnectorCatalog } from "../../../connectors/catalog.js";
14
14
  import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
15
- import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
16
- import { getConnectorInstance, getInstalledConnectorDefinition, listConnectorInstances } from "../../../connectors/instances.js";
17
- import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
18
15
  import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
19
16
  import { getMcpOAuthManager } from "../../../agent/mcp/oauth/mcp-oauth-manager.js";
17
+ import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
18
+ import { getConnectorInstance, getInstalledConnectorDefinition, listConnectorInstances } from "../../../connectors/instances.js";
20
19
  import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
21
20
  import { composioLogoResponse } from "../../../connectors/composio-logo.js";
22
21
  import { inspectManagedComposioStatus } from "../../../connectors/composio-managed-client.js";
23
22
  import { appendComposioTriggerEvent, listComposioTriggerEvents } from "../../../connectors/composio-triggers.js";
24
23
  import { ingestLocalFolderSource } from "../../../connectors/connected-source-ingestion.js";
25
24
  import { previewConnectorDefinition, testConnectorInstance } from "../../../connectors/health.js";
25
+ import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
26
26
  import { setConnectorEnabled } from "../../../connectors/lifecycle.js";
27
27
  import { projectComposioConnectionStatus } from "../../../connectors/runtime-status.js";
28
28
  import { applySourceRevocationChoices, sourceRevocationImpact } from "./understanding-sources.js";