@xopcai/xopc 0.0.247 → 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 (197) 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-DmaFeojS.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-CZwf1mgZ.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-BODskFTb.js → app-management-settings-panel-qfwAgyhQ.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-DeaVvaYZ.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-BG82bNBQ.js → attachment-load-CejsQMev.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-CqBZ89He.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-B6LKm5Zv.js → binary-plugins-DGjppLSG.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-BJKvGVXd.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-DoE4Uuns.js → browser-workflows-page-CJh4NyxT.js} +2 -2
  25. package/dist/gateway/static/root/assets/{capabilities-settings-panel-Cg7zCxEH.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-BsRWnz7M.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-DdCgsH2c.js → cron-expression-DTj1V3Sw.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-dt37Lt8e.js → date-picker-Yr6OCvGL.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-oi7cdv2C.js → dependency-picker-DpN3XZg9.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-Nw_Pgkk3.js → desktop-pet-DbGzggPF.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-D9OO-exo.js → desktop-pet-settings-DinCToZh.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-debug-page-BHSst0WN.js → extension-debug-page-DgTtk4KC.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-DXbL4cQZ.js → extension-page-DtQeiP6f.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-FTD7nE8v.js → extension-settings-page-DcguCgsH.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-c-8ENciH.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-BxvyTRl0.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-C1S2Ccui.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-Cif1_3Jx.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-EY4cu-6W.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-Dh7OxX0S.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-DUsxXdDp.js → logs-page-CXKy6E_l.js} +2 -2
  53. package/dist/gateway/static/root/assets/{management-settings-ZjiL3A-S.js → management-settings-BdJZFR7U.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-split-B4BxkTpU.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-D15XBiEo.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-Dv87XewB.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-DOe0lOcQ.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-BhKcyEId.js → runtime-tools-settings-panel-YkjhiQfA.js} +2 -2
  69. package/dist/gateway/static/root/assets/{schema-form-L0s7RWCi.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-CTKoztlF.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-CiiLLz5A.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-cBT9jCof.js → skills-page-CjF8DTsN.js} +1 -1
  78. package/dist/gateway/static/root/assets/{skills-page.utils-CwRekJSJ.js → skills-page.utils-DEDTYs2W.js} +1 -1
  79. package/dist/gateway/static/root/assets/{system-settings-panel-Byrk4DQy.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-jKzujxFU.js → tunnel-api-FKUi9wDL.js} +1 -1
  83. package/dist/gateway/static/root/assets/{use-autosave-DX5YZ3Nn.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-ocnZbAyi.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-DE4_YpDn.js → work-discovery-overlay-jhT2EzeH.js} +1 -1
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DaErGvxO.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/hono/lib/extension-store.js +8 -25
  120. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  121. package/dist/src/gateway/hono/routes/connectors.js +3 -3
  122. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  123. package/dist/src/gateway/hono/routes/projects.js +1 -1
  124. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  125. package/dist/src/gateway/hono/routes/you.js +16 -2
  126. package/dist/src/gateway/service.js +4 -5
  127. package/dist/src/notes/index.d.ts +1 -1
  128. package/dist/src/notes/index.js +2 -2
  129. package/dist/src/notes/paths.d.ts +0 -3
  130. package/dist/src/notes/paths.js +1 -10
  131. package/dist/src/notes/service.d.ts +0 -1
  132. package/dist/src/notes/service.js +0 -3
  133. package/dist/src/notes/store.d.ts +0 -2
  134. package/dist/src/notes/store.js +33 -80
  135. package/dist/src/share/hosted-session-share.d.ts +1 -4
  136. package/dist/src/share/hosted-session-share.js +14 -47
  137. package/dist/src/share/share-auto.d.ts +1 -1
  138. package/dist/src/share/share-auto.js +2 -2
  139. package/dist/src/share/share-store.d.ts +2 -7
  140. package/dist/src/share/share-store.js +153 -195
  141. package/dist/src/share/share-types.d.ts +0 -4
  142. package/dist/src/share/site-share-store.d.ts +3 -8
  143. package/dist/src/share/site-share-store.js +94 -153
  144. package/dist/src/share/site-share-types.d.ts +0 -4
  145. package/dist/src/storage/sqlite/connection.d.ts +1 -2
  146. package/dist/src/storage/sqlite/connection.js +50 -47
  147. package/dist/src/storage/sqlite/durable-queue.d.ts +16 -0
  148. package/dist/src/storage/sqlite/durable-queue.js +52 -0
  149. package/dist/src/storage/sqlite/durable-state.d.ts +16 -0
  150. package/dist/src/storage/sqlite/durable-state.js +43 -0
  151. package/dist/src/storage/sqlite/migrations/146_understanding_focus_exclusions.sql +9 -0
  152. package/dist/src/storage/sqlite/migrations/147_durable_application_state.sql +39 -0
  153. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  154. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  155. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  156. package/dist/src/storage/sqlite/schema.js +1 -1
  157. package/dist/src/storage/sqlite/understanding-focus-exclusions.d.ts +2 -0
  158. package/dist/src/storage/sqlite/understanding-focus-exclusions.js +24 -0
  159. package/dist/src/tui/tui-scoped-models.js +9 -6
  160. package/dist/src/tui/tui-startup-resources.js +1 -1
  161. package/dist/src/voice/realtime/agentEngine.js +63 -18
  162. package/dist/src/voice/realtime/conversationTurn.d.ts +20 -0
  163. package/dist/src/voice/realtime/conversationTurn.js +83 -0
  164. package/dist/src/voice/realtime/omniEngine.js +72 -18
  165. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +1 -5
  166. package/dist/src/workflows/authoring/workflow-draft-store.js +23 -43
  167. package/dist/src/workflows/index.js +2 -2
  168. package/dist/src/workflows/store/event-store.d.ts +1 -2
  169. package/dist/src/workflows/store/event-store.js +19 -64
  170. package/dist/src/workflows/store/paths.d.ts +0 -2
  171. package/dist/src/workflows/store/paths.js +1 -7
  172. package/dist/src/workflows/store/run-store.d.ts +0 -1
  173. package/dist/src/workflows/store/run-store.js +1 -24
  174. package/package.json +3 -3
  175. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-eG49pM-z.js +0 -1
  176. package/dist/gateway/static/root/assets/apps-page-BZG3BK7f.js +0 -1
  177. package/dist/gateway/static/root/assets/automations-workspace-CB7Yl2_B.js +0 -6
  178. package/dist/gateway/static/root/assets/browser-settings-page-Bu42Ljfw.js +0 -8
  179. package/dist/gateway/static/root/assets/channels-settings-EDTZ8P3y.js +0 -1
  180. package/dist/gateway/static/root/assets/connectors-page-kh7PEkSS.js +0 -2
  181. package/dist/gateway/static/root/assets/home-page-Bqx-SMWV.js +0 -1
  182. package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +0 -2
  183. package/dist/gateway/static/root/assets/local-app-workbench-page-sDdw7Y3Q.js +0 -2
  184. package/dist/gateway/static/root/assets/messages-BbdwoxVo.js +0 -3
  185. package/dist/gateway/static/root/assets/models-hub-cache-88f4fzYS.js +0 -1
  186. package/dist/gateway/static/root/assets/notes-workbench-Cy0oYbWP.js +0 -4
  187. package/dist/gateway/static/root/assets/project-detail-page-fgD1xc4O.js +0 -1
  188. package/dist/gateway/static/root/assets/projects-page-CiTiEcOc.js +0 -1
  189. package/dist/gateway/static/root/assets/remote-access-hub-Dc0GrNSp.js +0 -1
  190. package/dist/gateway/static/root/assets/sessions-page-BPOW3yaM.js +0 -1
  191. package/dist/gateway/static/root/assets/settings-advanced-gate-Bz4s9BBY.js +0 -1
  192. package/dist/gateway/static/root/assets/setup-status-panel-rllj-j7k.js +0 -1
  193. package/dist/gateway/static/root/assets/shares-settings-DMj7onCX.js +0 -1
  194. package/dist/gateway/static/root/assets/skill-reload-api-DRB366nS.js +0 -1
  195. package/dist/gateway/static/root/assets/task-detail-page-CheX3zmK.js +0 -1
  196. package/dist/gateway/static/root/assets/user-context-page-CWy3Pqtk.js +0 -1
  197. package/dist/gateway/static/root/assets/workflows-page-y4O9-BTf.js +0 -5
@@ -0,0 +1,39 @@
1
+ CREATE TABLE durable_state (
2
+ namespace TEXT NOT NULL,
3
+ scope TEXT NOT NULL,
4
+ key TEXT NOT NULL,
5
+ payload TEXT NOT NULL CHECK(json_valid(payload)),
6
+ UNIQUE(namespace, scope, key)
7
+ );
8
+ CREATE TABLE workflow_events (
9
+ agent_id TEXT NOT NULL,
10
+ run_id TEXT NOT NULL,
11
+ sequence INTEGER NOT NULL CHECK(sequence > 0),
12
+ id TEXT NOT NULL UNIQUE,
13
+ payload TEXT NOT NULL CHECK(json_valid(payload)),
14
+ PRIMARY KEY(agent_id, run_id, sequence)
15
+ );
16
+ CREATE TABLE note_snapshots (
17
+ note_id TEXT NOT NULL REFERENCES notes(note_id) ON DELETE CASCADE,
18
+ timestamp INTEGER NOT NULL,
19
+ payload TEXT NOT NULL CHECK(json_valid(payload)),
20
+ PRIMARY KEY(note_id, timestamp)
21
+ );
22
+ CREATE TABLE durable_messages (
23
+ sequence INTEGER PRIMARY KEY AUTOINCREMENT,
24
+ queue TEXT NOT NULL,
25
+ scope TEXT NOT NULL,
26
+ id TEXT NOT NULL,
27
+ payload TEXT NOT NULL CHECK(json_valid(payload)),
28
+ enqueued_at INTEGER NOT NULL,
29
+ processed_at INTEGER,
30
+ lease_token TEXT,
31
+ lease_until INTEGER,
32
+ UNIQUE(queue, scope, id)
33
+ );
34
+ CREATE INDEX durable_messages_pending ON durable_messages(queue, scope, processed_at, sequence);
35
+
36
+ CREATE UNIQUE INDEX durable_share_token ON durable_state(namespace, json_extract(payload, '$.token'))
37
+ WHERE namespace IN ('shares', 'site-shares');
38
+ CREATE UNIQUE INDEX durable_site_subdomain ON durable_state(json_extract(payload, '$.subdomain'))
39
+ WHERE namespace = 'site-shares' AND json_extract(payload, '$.subdomain') IS NOT NULL;
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 145;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 147;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
12
12
  /** Baseline schema version applied from schema.sql on first open. */
13
13
  const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
14
14
  /** Latest schema version this release supports (increment when adding migrations). */
15
- const XOPC_DB_SCHEMA_VERSION = 145;
15
+ const XOPC_DB_SCHEMA_VERSION = 147;
16
16
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
17
17
  function backupBeforeTaskCutover(db, databasePath) {
18
18
  db.exec("PRAGMA wal_checkpoint(FULL)");
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
57
57
  * Each step runs in its own transaction and updates schema_meta on success.
58
58
  */
59
59
  function applyPendingMigrations(db, options = {}) {
60
- const targetVersion = options.targetVersion ?? 145;
60
+ const targetVersion = options.targetVersion ?? 147;
61
61
  let currentVersion = readSchemaVersion(db);
62
62
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
63
63
  if (currentVersion >= targetVersion) return currentVersion;
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
94
94
  }
95
95
  /** Inspect schema version without mutating the database. */
96
96
  function inspectSchemaMigrationStatus(db, options = {}) {
97
- const appVersion = options.targetVersion ?? 145;
97
+ const appVersion = options.targetVersion ?? 147;
98
98
  const dbVersion = readSchemaVersion(db);
99
99
  if (dbVersion > appVersion) return {
100
100
  dbVersion,
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
19
19
  export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
20
20
 
21
21
  /** Latest schema version this release supports (increment when adding migrations). */
22
- export const XOPC_DB_SCHEMA_VERSION = 145;
22
+ export const XOPC_DB_SCHEMA_VERSION = 147;
23
23
 
24
24
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
25
25
 
@@ -32,7 +32,7 @@ function ensureXopcDatabaseSchema(db, options = {}) {
32
32
  currentVersion = 11;
33
33
  }
34
34
  applyPendingMigrations(db, {
35
- targetVersion: 145,
35
+ targetVersion: 147,
36
36
  databasePath: options.databasePath
37
37
  });
38
38
  }
@@ -0,0 +1,2 @@
1
+ export declare function listUnderstandingFocusExclusions(): Map<string, string[]>;
2
+ export declare function setUnderstandingFocusExclusion(understandingId: string, focusId: string, excluded: boolean): void;
@@ -0,0 +1,24 @@
1
+ import { getSqliteDatabase } from "./transaction.js";
2
+ import { notifyUserContextChange } from "../../user-context/changes.js";
3
+ //#region src/storage/sqlite/understanding-focus-exclusions.ts
4
+ function listUnderstandingFocusExclusions() {
5
+ const rows = getSqliteDatabase().prepare("SELECT understanding_id, focus_id FROM understanding_focus_exclusions").all();
6
+ const result = /* @__PURE__ */ new Map();
7
+ for (const row of rows) {
8
+ const ids = result.get(row.understanding_id) ?? [];
9
+ ids.push(row.focus_id);
10
+ result.set(row.understanding_id, ids);
11
+ }
12
+ return result;
13
+ }
14
+ function setUnderstandingFocusExclusion(understandingId, focusId, excluded) {
15
+ const db = getSqliteDatabase();
16
+ if (excluded) db.prepare("INSERT OR IGNORE INTO understanding_focus_exclusions (understanding_id, focus_id, created_at) VALUES (?, ?, ?)").run(understandingId, focusId, Date.now());
17
+ else db.prepare("DELETE FROM understanding_focus_exclusions WHERE understanding_id = ? AND focus_id = ?").run(understandingId, focusId);
18
+ notifyUserContextChange({
19
+ kind: "understanding",
20
+ id: understandingId
21
+ });
22
+ }
23
+ //#endregion
24
+ export { listUnderstandingFocusExclusions, setUnderstandingFocusExclusion };
@@ -1,15 +1,18 @@
1
- import { homedir } from "node:os";
1
+ import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
2
2
  import { join } from "node:path";
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
4
  //#region src/tui/tui-scoped-models.ts
5
- const STORE_PATH = join(homedir(), ".xopc", "tui-scoped-models.json");
5
+ init_paths_state();
6
+ function storePath() {
7
+ return join(resolveStateDir(), "tui-scoped-models.json");
8
+ }
6
9
  function normalizeWorkspaceKey(cwd) {
7
10
  return cwd.replace(/\\/g, "/").replace(/\/+$/, "") || "/";
8
11
  }
9
12
  function readStore() {
10
13
  try {
11
- if (!existsSync(STORE_PATH)) return {};
12
- const raw = readFileSync(STORE_PATH, "utf8");
14
+ if (!existsSync(storePath())) return {};
15
+ const raw = readFileSync(storePath(), "utf8");
13
16
  const parsed = JSON.parse(raw);
14
17
  return parsed && typeof parsed === "object" ? parsed : {};
15
18
  } catch {
@@ -17,9 +20,9 @@ function readStore() {
17
20
  }
18
21
  }
19
22
  function writeStore(data) {
20
- const dir = join(homedir(), ".xopc");
23
+ const dir = resolveStateDir();
21
24
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
22
- writeFileSync(STORE_PATH, `${JSON.stringify(data, null, 2)}\n`, "utf8");
25
+ writeFileSync(storePath(), `${JSON.stringify(data, null, 2)}\n`, "utf8");
23
26
  }
24
27
  /** Load scoped model refs for Ctrl+P cycling (`null` = all models). */
25
28
  function loadScopedModelRefs(cwd = process.cwd()) {
@@ -5,9 +5,9 @@ import { resolveBootstrapFilesSync } from "../agent/bootstrap/bootstrap-files.js
5
5
  import { createSkillConfigManager, isSkillEnabled } from "../agent/skills/config.js";
6
6
  import { loadSkills } from "../agent/skills/index.js";
7
7
  import { createWorkflowCatalog } from "../agent/workflow/catalog.js";
8
- import { listConnectorInstances } from "../connectors/instances.js";
9
8
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
10
9
  import "../config/index.js";
10
+ import { listConnectorInstances } from "../connectors/instances.js";
11
11
  import { basename } from "node:path";
12
12
  //#region src/tui/tui-startup-resources.ts
13
13
  init_paths();
@@ -2,6 +2,7 @@ import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { speakStream } from "../tts/speak-core.js";
4
4
  import { AudioPlaybackWindow } from "./audio-playback-window.js";
5
+ import { ConversationTurn } from "./conversationTurn.js";
5
6
  import { SpeakableSegmenter } from "./speakable-segmenter.js";
6
7
  import crypto from "node:crypto";
7
8
  //#region src/voice/realtime/agentEngine.ts
@@ -29,6 +30,32 @@ function createAgentVoiceEngine(options) {
29
30
  let finalCount = 0;
30
31
  let committing = false;
31
32
  const finalizedUtterances = /* @__PURE__ */ new Set();
33
+ let pendingTurn;
34
+ const turn = new ConversationTurn(claim.silenceDurationMs, (text) => {
35
+ if (closed || muted) return;
36
+ if (queuedTurns >= 8) {
37
+ send("session.error", {
38
+ code: "INPUT_BACKPRESSURE",
39
+ message: "Too many queued voice turns",
40
+ recoverable: false
41
+ });
42
+ options.onClose("input_backpressure", true);
43
+ return;
44
+ }
45
+ queuedTurns += 1;
46
+ const generation = inputGeneration;
47
+ const pending = {
48
+ text,
49
+ cancelled: false
50
+ };
51
+ pendingTurn = pending;
52
+ conversationTail = conversationTail.then(() => {
53
+ if (pendingTurn === pending) pendingTurn = void 0;
54
+ if (generation === inputGeneration && !pending.cancelled) return runConversationTurn(text);
55
+ }).finally(() => {
56
+ if (generation === inputGeneration) queuedTurns -= 1;
57
+ });
58
+ });
32
59
  function cancelActiveResponse(reason) {
33
60
  const response = activeResponse;
34
61
  if (!response) return false;
@@ -238,10 +265,23 @@ function createAgentVoiceEngine(options) {
238
265
  }
239
266
  });
240
267
  }
268
+ function bufferFinal(utteranceId, text) {
269
+ try {
270
+ turn.final(utteranceId, text);
271
+ } catch {
272
+ send("session.error", {
273
+ code: "INPUT_BACKPRESSURE",
274
+ message: "Voice turn input limit reached",
275
+ recoverable: false
276
+ });
277
+ options.onClose("input_backpressure", true);
278
+ }
279
+ }
241
280
  function onSttEvent(event) {
242
281
  if (closed) return;
243
282
  if (event.type === "ready" || event.type === "usage") return;
244
283
  if (event.type === "error") {
284
+ turn.reset();
245
285
  log.warn({
246
286
  err: event.error,
247
287
  sessionId: claim.sessionId,
@@ -257,10 +297,21 @@ function createAgentVoiceEngine(options) {
257
297
  }
258
298
  if (muted || finalizedUtterances.has(event.utteranceId)) return;
259
299
  if (event.type === "speech_started") {
300
+ if (claim.request.purpose === "conversation") {
301
+ if (pendingTurn) {
302
+ pendingTurn.cancelled = true;
303
+ turn.restore(pendingTurn.text);
304
+ pendingTurn = void 0;
305
+ }
306
+ turn.start(event.utteranceId);
307
+ }
260
308
  if (claim.request.purpose === "conversation" && claim.config.voice?.realtime?.bargeIn && !activeResponse?.awaitingClarification) cancelActiveResponse("barge_in");
261
309
  send("input.speech_started", { utteranceId: event.utteranceId });
262
310
  }
263
- if (event.type === "speech_stopped") send("input.speech_stopped", { utteranceId: event.utteranceId });
311
+ if (event.type === "speech_stopped") {
312
+ if (claim.request.purpose === "conversation") turn.stop(event.utteranceId);
313
+ send("input.speech_stopped", { utteranceId: event.utteranceId });
314
+ }
264
315
  if (event.type === "transcript_delta") send("input.transcript.delta", {
265
316
  utteranceId: event.utteranceId,
266
317
  revision: event.revision,
@@ -268,7 +319,10 @@ function createAgentVoiceEngine(options) {
268
319
  });
269
320
  if (event.type === "transcript_final") {
270
321
  const text = event.text.trim();
271
- if (!text) return;
322
+ if (!text) {
323
+ if (claim.request.purpose === "conversation") bufferFinal(event.utteranceId, "");
324
+ return;
325
+ }
272
326
  if (finalizedUtterances.size >= 1e4) {
273
327
  options.onClose("utterance_limit", true);
274
328
  return;
@@ -282,28 +336,18 @@ function createAgentVoiceEngine(options) {
282
336
  ...event.language === "zh" || event.language === "en" ? { language: event.language } : {}
283
337
  });
284
338
  if (claim.request.purpose === "conversation") {
285
- if (activeResponse?.awaitingClarification) return;
286
- if (claim.config.voice?.realtime?.bargeIn) cancelActiveResponse("barge_in");
287
- if (queuedTurns >= 8) {
288
- send("session.error", {
289
- code: "INPUT_BACKPRESSURE",
290
- message: "Too many queued voice turns",
291
- recoverable: false
292
- });
293
- options.onClose("input_backpressure", true);
339
+ if (activeResponse?.awaitingClarification) {
340
+ turn.reset();
294
341
  return;
295
342
  }
296
- queuedTurns += 1;
297
- const generation = inputGeneration;
298
- conversationTail = conversationTail.then(() => {
299
- if (generation === inputGeneration) return runConversationTurn(text);
300
- }).finally(() => {
301
- if (generation === inputGeneration) queuedTurns -= 1;
302
- });
343
+ if (claim.config.voice?.realtime?.bargeIn) cancelActiveResponse("barge_in");
344
+ bufferFinal(event.utteranceId, text);
303
345
  }
304
346
  }
305
347
  }
306
348
  function discardInput() {
349
+ turn.reset();
350
+ pendingTurn = void 0;
307
351
  inputGeneration += 1;
308
352
  queuedTurns = 0;
309
353
  bufferedAudio = [];
@@ -387,6 +431,7 @@ function createAgentVoiceEngine(options) {
387
431
  close() {
388
432
  if (closing) return closing;
389
433
  closed = true;
434
+ turn.reset();
390
435
  cancelActiveResponse("session_closed");
391
436
  sttAbort.abort("session_closed");
392
437
  sttSession?.abort("session_closed");
@@ -0,0 +1,20 @@
1
+ /** Conservative continuation hints, not a semantic model or punctuation-based endpoint detector. */
2
+ export declare function needsContinuation(text: string): boolean;
3
+ /** Joins provider utterances until both transcription and the continuation window have settled. */
4
+ export declare class ConversationTurn {
5
+ private readonly silenceDurationMs;
6
+ private readonly onTurn;
7
+ private readonly parts;
8
+ private timer;
9
+ private stoppedAt;
10
+ constructor(silenceDurationMs: number, onTurn: (text: string) => void);
11
+ start(id: string): void;
12
+ stop(id: string): void;
13
+ final(id: string, text: string): void;
14
+ reset(): void;
15
+ /** Restore a settled turn if generation was still queued when the user resumed. */
16
+ restore(text: string): void;
17
+ private text;
18
+ private clearTimer;
19
+ private schedule;
20
+ }
@@ -0,0 +1,83 @@
1
+ //#region src/voice/realtime/conversationTurn.ts
2
+ const MIN_TURN_SILENCE_MS = 1200;
3
+ const FINAL_SETTLE_MS = 350;
4
+ const INCOMPLETE_HOLD_MS = 1800;
5
+ /** Conservative continuation hints, not a semantic model or punctuation-based endpoint detector. */
6
+ function needsContinuation(text) {
7
+ const tail = text.trim().replace(/[\s,。!?、;:,.!?;:]+$/u, "");
8
+ return /(?:…|\.\.\.)[\s,。!?,.!?]*$/u.test(text) || /(?:因为|但是|然后|而且|如果|所以|比如|或者|还有|我想|我要|我觉得|帮我|帮我查一下|帮我查查|请帮我|就是说|那个|这个|呃|嗯)$/u.test(tail) || /\b(?:because|but|and|or|if|so|then|um|uh|i want to|i would like to|can you|could you|let me)\s*$/iu.test(tail);
9
+ }
10
+ /** Joins provider utterances until both transcription and the continuation window have settled. */
11
+ var ConversationTurn = class {
12
+ parts = /* @__PURE__ */ new Map();
13
+ timer;
14
+ stoppedAt = 0;
15
+ constructor(silenceDurationMs, onTurn) {
16
+ this.silenceDurationMs = silenceDurationMs;
17
+ this.onTurn = onTurn;
18
+ }
19
+ start(id) {
20
+ if (this.parts.has(id)) return;
21
+ this.clearTimer();
22
+ this.parts.set(id, { stopped: false });
23
+ }
24
+ stop(id) {
25
+ const part = this.parts.get(id);
26
+ if (part?.stopped) return;
27
+ this.parts.set(id, {
28
+ ...part,
29
+ stopped: true
30
+ });
31
+ this.stoppedAt = Date.now();
32
+ this.schedule();
33
+ }
34
+ final(id, text) {
35
+ const part = this.parts.get(id);
36
+ if (part?.text !== void 0) return;
37
+ if (!part?.stopped) this.stoppedAt = Date.now();
38
+ this.parts.set(id, {
39
+ text: text.trim(),
40
+ stopped: true
41
+ });
42
+ if (this.parts.size > 256 || this.text().length > 32e3) {
43
+ this.reset();
44
+ throw new Error("Voice turn input limit reached");
45
+ }
46
+ this.schedule();
47
+ }
48
+ reset() {
49
+ this.clearTimer();
50
+ this.parts.clear();
51
+ }
52
+ /** Restore a settled turn if generation was still queued when the user resumed. */
53
+ restore(text) {
54
+ this.parts.set("queued-turn", {
55
+ text,
56
+ stopped: true
57
+ });
58
+ this.clearTimer();
59
+ }
60
+ text() {
61
+ return [...this.parts.values()].map((part) => part.text ?? "").filter(Boolean).join(" ");
62
+ }
63
+ clearTimer() {
64
+ clearTimeout(this.timer);
65
+ this.timer = void 0;
66
+ }
67
+ schedule() {
68
+ this.clearTimer();
69
+ if ([...this.parts.values()].some((part) => !part.stopped || part.text === void 0)) return;
70
+ const text = this.text();
71
+ if (!text) {
72
+ this.reset();
73
+ return;
74
+ }
75
+ const holdMs = Math.max(FINAL_SETTLE_MS, MIN_TURN_SILENCE_MS - this.silenceDurationMs, needsContinuation(text) ? INCOMPLETE_HOLD_MS : 0);
76
+ this.timer = setTimeout(() => {
77
+ this.reset();
78
+ this.onTurn(text);
79
+ }, Math.max(FINAL_SETTLE_MS, this.stoppedAt + holdMs - Date.now()));
80
+ }
81
+ };
82
+ //#endregion
83
+ export { ConversationTurn, needsContinuation };
@@ -1,6 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { AudioPlaybackWindow } from "./audio-playback-window.js";
4
+ import { ConversationTurn } from "./conversationTurn.js";
4
5
  import crypto from "node:crypto";
5
6
  import WebSocket from "ws";
6
7
  //#region src/voice/realtime/omniEngine.ts
@@ -47,6 +48,23 @@ function createOmniVoiceEngine(options) {
47
48
  let queuedInputBytes = 0;
48
49
  let uploadingBytes = 0;
49
50
  let uploadTimer;
51
+ let turnSettled = false;
52
+ const speaking = /* @__PURE__ */ new Set();
53
+ const turn = new ConversationTurn(options.silenceDurationMs, () => {
54
+ if (closed || failed || muted || inputBlocked) return;
55
+ turnSettled = true;
56
+ if (active) publish(active);
57
+ });
58
+ function publish(response) {
59
+ if (response.published || active !== response) return;
60
+ response.published = true;
61
+ options.send("response.created", { responseId: response.id });
62
+ if (response.text) options.send("response.text.delta", {
63
+ responseId: response.id,
64
+ delta: response.text
65
+ });
66
+ response.release();
67
+ }
50
68
  const send = (type, fields = {}) => {
51
69
  if (closed || socket?.readyState !== WebSocket.OPEN) throw new Error("Omni connection is closed");
52
70
  socket.send(JSON.stringify({
@@ -103,23 +121,29 @@ function createOmniVoiceEngine(options) {
103
121
  if (!response) return false;
104
122
  active = void 0;
105
123
  response.abort.abort(reason);
106
- save({
107
- itemId: response.id,
108
- role: "assistant",
109
- text: response.text,
110
- interrupted: true
111
- });
112
- options.send("response.cancelled", {
113
- responseId: response.id,
114
- reason
115
- });
116
- if (reason === "client_cancelled" && response.generating && socket?.readyState === WebSocket.OPEN) {
124
+ response.release();
125
+ if (response.published) {
126
+ save({
127
+ itemId: response.id,
128
+ role: "assistant",
129
+ text: response.text,
130
+ interrupted: true
131
+ });
132
+ options.send("response.cancelled", {
133
+ responseId: response.id,
134
+ reason
135
+ });
136
+ }
137
+ if ((reason === "client_cancelled" || reason === "barge_in" && !options.bargeIn) && response.generating && socket?.readyState === WebSocket.OPEN) {
117
138
  cancellationPending = true;
118
139
  send("response.cancel");
119
140
  }
120
141
  return true;
121
142
  };
122
143
  const finish = async (response) => {
144
+ await response.settled;
145
+ if (active !== response || closed) return;
146
+ options.send("response.text.done", { responseId: response.id });
123
147
  await response.tail;
124
148
  if (active !== response || closed) return;
125
149
  await response.playback.drain(response.abort.signal);
@@ -157,6 +181,7 @@ function createOmniVoiceEngine(options) {
157
181
  function fail(code, details = {}) {
158
182
  if (closed || failed) return;
159
183
  failed = true;
184
+ turn.reset();
160
185
  log.warn({
161
186
  sessionId: options.callId,
162
187
  platformRequestId,
@@ -179,6 +204,10 @@ function createOmniVoiceEngine(options) {
179
204
  options.onClose("omni_error", true);
180
205
  }
181
206
  function discardInput() {
207
+ turn.reset();
208
+ speaking.clear();
209
+ turnSettled = false;
210
+ if (active && !active.published) cancel("client_cancelled");
182
211
  inputQueue = [];
183
212
  queuedInputBytes = 0;
184
213
  inputBlocked = true;
@@ -266,12 +295,18 @@ function createOmniVoiceEngine(options) {
266
295
  discardedInputs.add(String(event.item_id));
267
296
  return;
268
297
  }
298
+ if (recorded.has(String(event.item_id)) || pendingInputs.has(String(event.item_id))) return;
269
299
  inputBlocked = false;
270
300
  pendingInputs.add(String(event.item_id));
271
- if (options.bargeIn) cancel("barge_in");
301
+ turnSettled = false;
302
+ speaking.add(String(event.item_id));
303
+ turn.start(String(event.item_id));
304
+ if (options.bargeIn || active && !active.published) cancel("barge_in");
272
305
  options.send("input.speech_started", { utteranceId: String(event.item_id) });
273
306
  } else if (event.type === "input_audio_buffer.speech_stopped") {
274
- if (muted || inputBlocked || discardedInputs.has(String(event.item_id))) return;
307
+ if (muted || inputBlocked || discardedInputs.has(String(event.item_id)) || recorded.has(String(event.item_id))) return;
308
+ speaking.delete(String(event.item_id));
309
+ turn.stop(String(event.item_id));
275
310
  options.send("input.speech_stopped", { utteranceId: String(event.item_id) });
276
311
  } else if (event.type === "conversation.item.input_audio_transcription.completed") {
277
312
  if (typeof event.transcript !== "string" || event.transcript.length > 32e3 || typeof event.item_id !== "string") {
@@ -280,6 +315,8 @@ function createOmniVoiceEngine(options) {
280
315
  }
281
316
  if (muted || inputBlocked || discardedInputs.has(event.item_id) || recorded.has(event.item_id)) return;
282
317
  pendingInputs.delete(event.item_id);
318
+ speaking.delete(event.item_id);
319
+ turn.final(event.item_id, event.transcript);
283
320
  save({
284
321
  itemId: event.item_id,
285
322
  role: "user",
@@ -291,8 +328,16 @@ function createOmniVoiceEngine(options) {
291
328
  revision: 1,
292
329
  text: event.transcript
293
330
  });
331
+ } else if (event.type === "conversation.item.input_audio_transcription.failed") {
332
+ if (muted || inputBlocked || discardedInputs.has(String(event.item_id))) return;
333
+ discardInput();
334
+ options.send("session.error", {
335
+ code: "INPUT_DROPPED",
336
+ message: "Could not transcribe this voice turn. Please repeat it.",
337
+ recoverable: true
338
+ });
294
339
  } else if (event.type === "response.created") {
295
- if (muted || inputBlocked) {
340
+ if (muted || inputBlocked || speaking.size > 0) {
296
341
  cancellationPending = true;
297
342
  send("response.cancel");
298
343
  return;
@@ -301,6 +346,10 @@ function createOmniVoiceEngine(options) {
301
346
  if (active) cancel("barge_in");
302
347
  const id = event.response?.id;
303
348
  if (typeof id !== "string" || !id.length || id.length > 160) throw new Error("Invalid response ID");
349
+ let release;
350
+ const settled = new Promise((resolve) => {
351
+ release = resolve;
352
+ });
304
353
  active = {
305
354
  id,
306
355
  text: "",
@@ -309,16 +358,19 @@ function createOmniVoiceEngine(options) {
309
358
  queuedBytes: 0,
310
359
  abort: new AbortController(),
311
360
  playback: new AudioPlaybackWindow(),
312
- tail: Promise.resolve()
361
+ tail: Promise.resolve(),
362
+ published: false,
363
+ settled,
364
+ release
313
365
  };
314
- options.send("response.created", { responseId: id });
366
+ if (turnSettled) publish(active);
315
367
  } else if (active && event.response_id === active.id && event.type === "response.audio_transcript.delta") {
316
368
  if (typeof event.delta !== "string" || active.text.length + event.delta.length > 32e3) {
317
369
  fail("OMNI_TRANSCRIPT_LIMIT");
318
370
  return;
319
371
  }
320
372
  active.text += event.delta;
321
- options.send("response.text.delta", {
373
+ if (active.published) options.send("response.text.delta", {
322
374
  responseId: active.id,
323
375
  delta: event.delta
324
376
  });
@@ -339,6 +391,7 @@ function createOmniVoiceEngine(options) {
339
391
  }
340
392
  response.queuedBytes += audio.length;
341
393
  response.tail = response.tail.then(async () => {
394
+ await response.settled;
342
395
  for (let offset = 0; offset < audio.length; offset += 24e3) {
343
396
  if (closed || active !== response) return;
344
397
  const chunk = audio.subarray(offset, offset + 24e3);
@@ -368,7 +421,6 @@ function createOmniVoiceEngine(options) {
368
421
  else if (event.response.status !== "completed") fail("OMNI_RESPONSE_FAILED");
369
422
  else {
370
423
  const response = active;
371
- options.send("response.text.done", { responseId: response.id });
372
424
  finish(response).catch(() => {
373
425
  if (!response.abort.signal.aborted) stopReply(response, "OMNI_PLAYBACK_FAILED");
374
426
  });
@@ -429,6 +481,8 @@ function createOmniVoiceEngine(options) {
429
481
  clearTimeout(timer);
430
482
  clearTimeout(clearTimer);
431
483
  clearTimeout(uploadTimer);
484
+ turn.reset();
485
+ speaking.clear();
432
486
  inputQueue = [];
433
487
  queuedInputBytes = 0;
434
488
  rejectStart?.(/* @__PURE__ */ new Error("Omni connection closed"));
@@ -17,15 +17,11 @@ export interface SaveWorkflowAuthoringDraftInput {
17
17
  expectedUpdatedAtMs?: number;
18
18
  }
19
19
  export declare class WorkflowDraftStore {
20
- private readonly draftsDir;
21
- constructor(options?: {
22
- userDir?: string;
23
- });
20
+ private readonly state;
24
21
  list(workflowName?: string): WorkflowAuthoringDraft[];
25
22
  get(id: string): WorkflowAuthoringDraft | null;
26
23
  save(input: SaveWorkflowAuthoringDraftInput): WorkflowAuthoringDraft;
27
24
  remove(id: string): boolean;
28
- private readFile;
29
25
  }
30
26
  export declare class WorkflowDraftConflictError extends Error {
31
27
  readonly currentUpdatedAtMs?: number;