@xopcai/xopc 0.0.252 → 0.0.253

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 (168) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/src/inbound-processor.js +2 -2
  3. package/dist/extensions/telegram/src/plugin.js +3 -2
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store-w3eq3YpP.js → activity-store-CeS1bgXP.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-k039rbUz.js → agent-avatar-dicebear-BdF3HhCW.js} +1 -1
  7. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Bs34Kp0K.js +1 -0
  8. package/dist/gateway/static/root/assets/{agents-Bmth_bSQ.js → agents-DARlgjTm.js} +1 -1
  9. package/dist/gateway/static/root/assets/{api-2joIfbrH.js → api-zMPeC0yU.js} +1 -1
  10. package/dist/gateway/static/root/assets/{app-management-settings-panel-ByJ4kiD0.js → app-management-settings-panel-BaAFln8W.js} +1 -1
  11. package/dist/gateway/static/root/assets/{appearance-settings-BK2Jga-B.js → appearance-settings-CXvsoBlw.js} +1 -1
  12. package/dist/gateway/static/root/assets/{apps-page-B3ky7cWU.js → apps-page-BhgvfBJT.js} +1 -1
  13. package/dist/gateway/static/root/assets/{archive-plugin-DMDKtYpi.js → archive-plugin-C0o_mVQI.js} +1 -1
  14. package/dist/gateway/static/root/assets/{attachment-load-B764Ql3Z.js → attachment-load-B5Ry3tGL.js} +1 -1
  15. package/dist/gateway/static/root/assets/{automations-page-D-sO8CZe.js → automations-page-DY5QAEQd.js} +1 -1
  16. package/dist/gateway/static/root/assets/automations-workspace-BzX4lILP.js +6 -0
  17. package/dist/gateway/static/root/assets/{binary-plugins-fxtzYRpv.js → binary-plugins-BydpEgBA.js} +1 -1
  18. package/dist/gateway/static/root/assets/{block-editor-Bcjtvckh.js → block-editor-D0CpUOMo.js} +3 -3
  19. package/dist/gateway/static/root/assets/{browser-automation-inputs-BSmnusjD.js → browser-automation-inputs-DzbTsGI6.js} +1 -1
  20. package/dist/gateway/static/root/assets/{browser-automations-page-DC_OQIBk.js → browser-automations-page-D7fZYjni.js} +1 -1
  21. package/dist/gateway/static/root/assets/{browser-settings-page-C1FojyG6.js → browser-settings-page-BBdMqxl0.js} +1 -1
  22. package/dist/gateway/static/root/assets/capabilities-settings-panel-D_WfftDW.js +7 -0
  23. package/dist/gateway/static/root/assets/channels-settings-bdRLT9KA.js +1 -0
  24. package/dist/gateway/static/root/assets/{channels-status-swr-BuWjIG_a.js → channels-status-swr-BGGRTkn6.js} +1 -1
  25. package/dist/gateway/static/root/assets/{chat-terminal-dock-5SevEo_I.js → chat-terminal-dock-_CP4nvlg.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-CPDjU5wU.js +2 -0
  27. package/dist/gateway/static/root/assets/{cron-expression-DtsfalBM.js → cron-expression-g2U8Rllf.js} +1 -1
  28. package/dist/gateway/static/root/assets/{date-picker-tDEQV5TP.js → date-picker-SmVlhtj_.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-HhNwg0Y2.js → dependency-picker-D-0gcbbM.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-acU4Li-C.js → desktop-pet-Cl3JRIu6.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-R84AR0Pe.js → desktop-pet-settings-D7kvWQ9H.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-debug-page-CrLlRkSN.js → extension-debug-page-DtP2tJHY.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-page-BH5lmZXE.js → extension-page-CphZDdoT.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-settings-page-BscjNAd1.js → extension-settings-page-CsxVLV4-.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-config-swr-9HidFZUd.js → gateway-config-swr-BW3Bx-aV.js} +1 -1
  36. package/dist/gateway/static/root/assets/gateway-settings-DxBZ05dX.js +1 -0
  37. package/dist/gateway/static/root/assets/{gateway-startup-retry-DRCPXONr.js → gateway-startup-retry-DAq74TZe.js} +1 -1
  38. package/dist/gateway/static/root/assets/{heartbeat-settings-K5Zhl2rx.js → heartbeat-settings-DWcKsIoZ.js} +1 -1
  39. package/dist/gateway/static/root/assets/home-page-BdvLZKQZ.js +1 -0
  40. package/dist/gateway/static/root/assets/{image-generation-api-CR6Kle8H.js → image-generation-api-MPuaXDRs.js} +1 -1
  41. package/dist/gateway/static/root/assets/index-C7RDs6S-.js +74 -0
  42. package/dist/gateway/static/root/assets/index-Cu8xqZQ9.css +2 -0
  43. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B1QR49-7.js → keyboard-shortcuts-settings-CfhaTqgE.js} +1 -1
  44. package/dist/gateway/static/root/assets/{local-app-workbench-page-wicoV-ti.js → local-app-workbench-page-CR6asX7L.js} +1 -1
  45. package/dist/gateway/static/root/assets/{local-apps-page-C74It-T8.js → local-apps-page-g01W3kEK.js} +1 -1
  46. package/dist/gateway/static/root/assets/{locale-store-BfZGZKSs.js → locale-store-BkeaPZpn.js} +1 -1
  47. package/dist/gateway/static/root/assets/{logs-page-xX-7S49A.js → logs-page-ZP4QTWoC.js} +1 -1
  48. package/dist/gateway/static/root/assets/{management-settings-1kNnYL97.js → management-settings-DeGxJF_Z.js} +1 -1
  49. package/dist/gateway/static/root/assets/markdown-view-Ca7BRBLL.js +201 -0
  50. package/dist/gateway/static/root/assets/{media-plugins-B5c0AoS1.js → media-plugins-FmOhmzlD.js} +1 -1
  51. package/dist/gateway/static/root/assets/messages-C72stReU.js +3 -0
  52. package/dist/gateway/static/root/assets/{mobile-pairing-wizard-CsIZqK51.js → mobile-pairing-wizard-BXNbn05L.js} +1 -1
  53. package/dist/gateway/static/root/assets/note-detail-panel-EeVeF4II.js +5 -0
  54. package/dist/gateway/static/root/assets/notes-page-D7bMff96.js +8 -0
  55. package/dist/gateway/static/root/assets/{page-tabs-CqJN6Ljz.js → page-tabs-pyukZ1PJ.js} +1 -1
  56. package/dist/gateway/static/root/assets/{preview-open-alternatives-DqRIGxf4.js → preview-open-alternatives-slFHoMUe.js} +1 -1
  57. package/dist/gateway/static/root/assets/{product-open-page-DE2nPE_K.js → product-open-page-CXa3FNNk.js} +1 -1
  58. package/dist/gateway/static/root/assets/project-detail-page-BDF88VdN.js +1 -0
  59. package/dist/gateway/static/root/assets/projects-page-DeTD6pu1.js +1 -0
  60. package/dist/gateway/static/root/assets/{registry-api-Bpy8XX-5.js → registry-api-CviQoUBf.js} +1 -1
  61. package/dist/gateway/static/root/assets/remote-access-hub-CxKrdQ6a.js +1 -0
  62. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bb4b74-P.js → runtime-tools-settings-panel-O9D9o7-O.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schema-form-DoPU5j3J.js → schema-form-8FesicnL.js} +1 -1
  64. package/dist/gateway/static/root/assets/sessions-page-DUFJN-2t.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-advanced-gate-CcSYDjaH.js +1 -0
  66. package/dist/gateway/static/root/assets/{settings-form-section-Ci-9WajJ.js → settings-form-section-CBic9TFH.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-page-CL_2F95D.js → settings-page-Xz66_Mjg.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-C6DuwrP5.js +1 -0
  69. package/dist/gateway/static/root/assets/{share-preview-page-XUA3oKQX.js → share-preview-page--JpjwB58.js} +1 -1
  70. package/dist/gateway/static/root/assets/shares-settings-CovcdHSC.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-CrHagTsE.js +1 -0
  72. package/dist/gateway/static/root/assets/{skills-page-sXXAZDc9.js → skills-page-fVKExKv5.js} +1 -1
  73. package/dist/gateway/static/root/assets/{skills-page.utils-DD79Bl1I.js → skills-page.utils-Yv9u3uJp.js} +1 -1
  74. package/dist/gateway/static/root/assets/{system-settings-panel-BEH64qBV.js → system-settings-panel-CCWjVdc2.js} +1 -1
  75. package/dist/gateway/static/root/assets/task-detail-page-I8hueJnG.js +1 -0
  76. package/dist/gateway/static/root/assets/{theme-store-CISSxU1c.js → theme-store-BtkaVpMm.js} +1 -1
  77. package/dist/gateway/static/root/assets/{tunnel-api-DrKDhnJm.js → tunnel-api-C__W9BaN.js} +1 -1
  78. package/dist/gateway/static/root/assets/{use-autosave-CPYePL-Q.js → use-autosave-Dow9RRcq.js} +1 -1
  79. package/dist/gateway/static/root/assets/user-model-page-CU6nxmoM.js +2 -0
  80. package/dist/gateway/static/root/assets/{voice-api-key-field-DKqzrCXx.js → voice-api-key-field-CvF3lEyx.js} +1 -1
  81. package/dist/gateway/static/root/assets/{voice-config-api-e9xWjwBX.js → voice-config-api-BEUVAyM6.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-kTQug6bq.js → work-discovery-overlay-B9PDfReq.js} +1 -1
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-m9SKj_GT.js → workflow-run-setup-panel-kWGFkhjz.js} +2 -2
  84. package/dist/gateway/static/root/assets/workflows-page-B4Is5E42.js +5 -0
  85. package/dist/gateway/static/root/index.html +10 -10
  86. package/dist/package.js +1 -1
  87. package/dist/packages/realtime-protocol/src/voice.js +6 -1
  88. package/dist/src/agent/agent-manager.js +20 -3
  89. package/dist/src/agent/embedded/execution-context.d.ts +2 -1
  90. package/dist/src/agent/embedded/execution-context.js +10 -4
  91. package/dist/src/agent/embedded/index.d.ts +1 -1
  92. package/dist/src/agent/embedded/index.js +2 -2
  93. package/dist/src/agent/embedded/run-for-session.js +4 -3
  94. package/dist/src/agent/embedded/run-turn.js +22 -3
  95. package/dist/src/agent/embedded/types.d.ts +1 -1
  96. package/dist/src/agent/service/direct-turn-helpers.js +6 -3
  97. package/dist/src/agent/service/process-direct-streaming.js +6 -3
  98. package/dist/src/agent/service.d.ts +2 -0
  99. package/dist/src/agent/service.js +21 -7
  100. package/dist/src/agent/tools/clarify-tool.d.ts +17 -3
  101. package/dist/src/agent/tools/clarify-tool.js +27 -32
  102. package/dist/src/agent/tools/cli-clarify.js +23 -8
  103. package/dist/src/agent/tools/factory.js +14 -4
  104. package/dist/src/automations/domain/validation.d.ts +4 -4
  105. package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -1
  106. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  107. package/dist/src/gateway/chat-stream/mapper.js +5 -1
  108. package/dist/src/gateway/chat-stream/protocol.d.ts +5 -1
  109. package/dist/src/gateway/clarify-runtime.d.ts +7 -5
  110. package/dist/src/gateway/clarify-runtime.js +8 -11
  111. package/dist/src/gateway/ephemeral-clarification-waiter.d.ts +17 -0
  112. package/dist/src/gateway/ephemeral-clarification-waiter.js +46 -0
  113. package/dist/src/gateway/hono/routes/agent-stream.js +44 -18
  114. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +10 -2
  115. package/dist/src/gateway/hono/routes/side-chats.js +24 -4
  116. package/dist/src/gateway/security/gateway-scopes.js +1 -1
  117. package/dist/src/gateway/service/agent-runner.d.ts +25 -36
  118. package/dist/src/gateway/service/agent-runner.js +103 -32
  119. package/dist/src/gateway/service/run-gateway-agent.js +5 -2
  120. package/dist/src/gateway/service/session-input-coordinator.js +4 -1
  121. package/dist/src/gateway/service/sessions-api.js +1 -1
  122. package/dist/src/gateway/service.d.ts +4 -2
  123. package/dist/src/gateway/service.js +26 -10
  124. package/dist/src/gateway/side-chat/manager.d.ts +2 -1
  125. package/dist/src/gateway/side-chat/manager.js +5 -4
  126. package/dist/src/gateway/side-chat/run-service.d.ts +5 -1
  127. package/dist/src/gateway/side-chat/run-service.js +24 -23
  128. package/dist/src/gateway/side-chat/types.d.ts +3 -1
  129. package/dist/src/storage/sqlite/clarification-wait-repository.d.ts +41 -0
  130. package/dist/src/storage/sqlite/clarification-wait-repository.js +418 -0
  131. package/dist/src/storage/sqlite/index.d.ts +2 -1
  132. package/dist/src/storage/sqlite/index.js +2 -1
  133. package/dist/src/storage/sqlite/migrations/154_session_clarification_waits.sql +60 -0
  134. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  135. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  136. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  137. package/dist/src/storage/sqlite/schema.js +1 -1
  138. package/dist/src/storage/sqlite/session-input-repository.d.ts +11 -6
  139. package/dist/src/voice/realtime/agentEngine.js +7 -2
  140. package/dist/src/voice/realtime/runtime.types.d.ts +5 -0
  141. package/package.json +3 -3
  142. package/skills/creative/hatch-pet/SKILL.md +1 -1
  143. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-D4J4oq8p.js +0 -1
  144. package/dist/gateway/static/root/assets/automations-workspace-Ds5-_-9z.js +0 -6
  145. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bs59UCut.js +0 -7
  146. package/dist/gateway/static/root/assets/channels-settings-CM9vNmoo.js +0 -1
  147. package/dist/gateway/static/root/assets/connectors-page-BPZ44D-V.js +0 -2
  148. package/dist/gateway/static/root/assets/gateway-settings-BxLcW6ij.js +0 -1
  149. package/dist/gateway/static/root/assets/home-page-CZAg9RBv.js +0 -1
  150. package/dist/gateway/static/root/assets/index-D4Ykja-U.js +0 -72
  151. package/dist/gateway/static/root/assets/index-zIJ3AXgR.css +0 -2
  152. package/dist/gateway/static/root/assets/markdown-view-DjiwT28p.js +0 -201
  153. package/dist/gateway/static/root/assets/messages-DaIwVWar.js +0 -3
  154. package/dist/gateway/static/root/assets/note-detail-panel-CfWxopl4.js +0 -5
  155. package/dist/gateway/static/root/assets/notes-page-CYN-LCHJ.js +0 -8
  156. package/dist/gateway/static/root/assets/project-detail-page-B5G3LzDq.js +0 -1
  157. package/dist/gateway/static/root/assets/projects-page-CuVK2mKu.js +0 -1
  158. package/dist/gateway/static/root/assets/remote-access-hub-Dnd73xWt.js +0 -1
  159. package/dist/gateway/static/root/assets/sessions-page-XL4LyKZe.js +0 -1
  160. package/dist/gateway/static/root/assets/settings-advanced-gate-0ForzDSS.js +0 -1
  161. package/dist/gateway/static/root/assets/setup-status-panel-DVws6XZc.js +0 -1
  162. package/dist/gateway/static/root/assets/shares-settings-BwDvcacF.js +0 -1
  163. package/dist/gateway/static/root/assets/skill-reload-api-BJjrATqE.js +0 -1
  164. package/dist/gateway/static/root/assets/task-detail-page-0jxMi75O.js +0 -1
  165. package/dist/gateway/static/root/assets/user-model-page-B6zLDfDl.js +0 -2
  166. package/dist/gateway/static/root/assets/workflows-page-Bcd1XqP7.js +0 -5
  167. package/dist/src/gateway/clarify-bridge.d.ts +0 -46
  168. package/dist/src/gateway/clarify-bridge.js +0 -111
@@ -0,0 +1,418 @@
1
+ import { isXopcDatabaseOpen } from "./connection.js";
2
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
3
+ import { readCurrentSessionId } from "./session-instance-repository.js";
4
+ import { bumpSessionInputRevision, getSessionInputById, getSessionInputState, insertSessionInput } from "./session-input-repository.js";
5
+ import { TaskRunRepository } from "../../tasks/task-run-repository.js";
6
+ import { randomUUID } from "node:crypto";
7
+ //#region src/storage/sqlite/clarification-wait-repository.ts
8
+ const APPROVAL_TTL_MS = 10 * 6e4;
9
+ const STALE_CONTEXT_MS = 1440 * 6e4;
10
+ function rowToWait(row) {
11
+ return JSON.parse(row.data_json);
12
+ }
13
+ function getRow(id) {
14
+ return getSqliteDatabase().prepare(`SELECT id, session_key, session_id, status, version, data_json
15
+ FROM session_clarification_waits WHERE id = ?`).get(id);
16
+ }
17
+ function writeWait(wait, expectedVersion) {
18
+ const next = {
19
+ ...wait,
20
+ version: expectedVersion + 1,
21
+ updatedAt: wait.updatedAt || Date.now()
22
+ };
23
+ return getSqliteDatabase().prepare(`UPDATE session_clarification_waits
24
+ SET status = ?, version = ?, data_json = ?
25
+ WHERE id = ? AND version = ?`).run(next.status, next.version, JSON.stringify(next), next.id, expectedVersion).changes ? next : void 0;
26
+ }
27
+ function taskWaitsForClarification(taskId, clarificationId) {
28
+ return new TaskRunRepository().listActiveWaits(taskId).filter((wait) => wait.condition.clarificationId === clarificationId);
29
+ }
30
+ function resolveTaskWait(wait, resolution) {
31
+ if (!wait.taskRunId) return;
32
+ const runs = new TaskRunRepository();
33
+ const run = runs.get(wait.taskRunId);
34
+ if (!run) return;
35
+ for (const taskWait of taskWaitsForClarification(run.taskId, wait.id)) runs.resolveWait({
36
+ waitId: taskWait.id,
37
+ actor: {
38
+ kind: "user",
39
+ id: wait.principalId
40
+ },
41
+ resolution
42
+ });
43
+ }
44
+ function cancelTaskRun(wait, reason, now) {
45
+ if (!wait.taskRunId) return;
46
+ const runs = new TaskRunRepository();
47
+ const run = runs.get(wait.taskRunId);
48
+ if (!run || ![
49
+ "queued",
50
+ "running",
51
+ "waiting",
52
+ "verifying"
53
+ ].includes(run.status)) return;
54
+ runs.finalize({
55
+ runId: run.id,
56
+ expectedVersion: run.version,
57
+ actor: {
58
+ kind: "user",
59
+ id: wait.principalId
60
+ },
61
+ terminalCode: "clarification_cancelled",
62
+ terminalMessage: reason,
63
+ now,
64
+ receipt: {
65
+ status: "cancelled",
66
+ summary: reason,
67
+ changes: [],
68
+ evidence: [],
69
+ verification: {
70
+ status: "unverified",
71
+ checks: []
72
+ },
73
+ remainingWork: [wait.checkpoint.objectiveSummary],
74
+ needsUser: false,
75
+ completionVerdict: "not_achieved"
76
+ }
77
+ });
78
+ }
79
+ function markTaskWaiting(wait) {
80
+ if (!wait.taskRunId) return;
81
+ const runs = new TaskRunRepository();
82
+ const run = runs.get(wait.taskRunId);
83
+ if (!run || run.status !== "running") return;
84
+ runs.createWait({
85
+ taskId: run.taskId,
86
+ taskRunId: run.id,
87
+ kind: wait.kind === "approval" ? "approval" : "user_input",
88
+ reason: wait.question,
89
+ condition: {
90
+ type: "clarification",
91
+ clarificationId: wait.id
92
+ }
93
+ });
94
+ runs.setStatus({
95
+ runId: run.id,
96
+ expectedVersion: run.version,
97
+ from: ["running"],
98
+ to: "waiting",
99
+ actor: { kind: "system" }
100
+ });
101
+ }
102
+ function getClarification(id) {
103
+ if (!isXopcDatabaseOpen()) return void 0;
104
+ const row = getRow(id);
105
+ return row ? rowToWait(row) : void 0;
106
+ }
107
+ function getActiveClarification(sessionKey) {
108
+ if (!isXopcDatabaseOpen()) return void 0;
109
+ const sessionId = readCurrentSessionId(getSqliteDatabase(), sessionKey);
110
+ if (!sessionId) return void 0;
111
+ const row = getSqliteDatabase().prepare(`SELECT id, session_key, session_id, status, version, data_json
112
+ FROM session_clarification_waits
113
+ WHERE session_key = ? AND session_id = ? AND status IN ('open', 'queued')
114
+ ORDER BY version DESC LIMIT 1`).get(sessionKey, sessionId);
115
+ return row ? rowToWait(row) : void 0;
116
+ }
117
+ function getClarificationSnapshot(sessionKey) {
118
+ if (!isXopcDatabaseOpen()) return void 0;
119
+ const sessionId = readCurrentSessionId(getSqliteDatabase(), sessionKey);
120
+ if (!sessionId) return void 0;
121
+ const state = getSessionInputState(sessionKey);
122
+ const now = Date.now();
123
+ const active = getActiveClarification(sessionKey);
124
+ const clarification = active?.kind === "approval" && active.expiresAt !== void 0 && active.expiresAt <= now ? expireApproval(active, now) : active;
125
+ return {
126
+ sessionId,
127
+ revision: state.revision,
128
+ serverTime: now,
129
+ clarification: clarification?.status === "open" || clarification?.status === "queued" ? clarification : null
130
+ };
131
+ }
132
+ function createClarificationWait(input) {
133
+ return runSqliteWriteTransaction((db) => {
134
+ const sessionId = readCurrentSessionId(db, input.sessionKey);
135
+ if (!sessionId) throw new Error("Clarification requires a persisted session.");
136
+ const duplicate = db.prepare(`SELECT id, session_key, session_id, status, version, data_json
137
+ FROM session_clarification_waits
138
+ WHERE session_id = ? AND origin_run_id = ? AND origin_tool_call_id = ?`).get(sessionId, input.runId, input.toolCallId);
139
+ if (duplicate) return rowToWait(duplicate);
140
+ const now = input.now ?? Date.now();
141
+ const runtime = getSessionInputState(input.sessionKey);
142
+ const origin = runtime.activeInputId ? getSessionInputById(input.sessionKey, runtime.activeInputId) : void 0;
143
+ const active = getActiveClarification(input.sessionKey);
144
+ if (active) {
145
+ writeWait({
146
+ ...active,
147
+ status: "superseded",
148
+ resolution: "cancelled",
149
+ resolvedAt: now,
150
+ updatedAt: now
151
+ }, active.version);
152
+ resolveTaskWait(active, { superseded: true });
153
+ cancelTaskRun(active, "Task superseded by a newer clarification request.", now);
154
+ }
155
+ const lastEntry = db.prepare("SELECT entry_id FROM transcript_entries WHERE session_id = ? ORDER BY seq DESC LIMIT 1").get(sessionId);
156
+ const wait = {
157
+ id: randomUUID(),
158
+ principalId: "local-owner",
159
+ sessionKey: input.sessionKey,
160
+ sessionId,
161
+ objectiveId: origin?.id ?? input.runId,
162
+ objectiveRevision: (active?.objectiveRevision ?? 0) + 1,
163
+ originRunId: input.runId,
164
+ originInputId: origin?.id ?? input.runId,
165
+ originToolCallId: input.toolCallId,
166
+ taskRunId: origin?.taskRunId,
167
+ kind: input.kind,
168
+ status: "open",
169
+ question: input.question.trim(),
170
+ choices: input.choices,
171
+ suggestedAnswer: input.suggestedAnswer,
172
+ checkpoint: {
173
+ transcriptEntryId: lastEntry?.entry_id,
174
+ objectiveSummary: origin?.content ?? input.question.trim(),
175
+ completedSteps: [],
176
+ pendingSteps: [input.question.trim()],
177
+ originalRequestAt: origin?.createdAtMs ?? now
178
+ },
179
+ expiresAt: input.kind === "approval" ? now + APPROVAL_TTL_MS : void 0,
180
+ approvalKey: input.approvalKey,
181
+ version: 1,
182
+ createdAt: now,
183
+ updatedAt: now
184
+ };
185
+ db.prepare(`INSERT INTO session_clarification_waits (
186
+ id, principal_id, session_key, session_id, status, version, data_json,
187
+ origin_run_id, origin_tool_call_id
188
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(wait.id, wait.principalId, wait.sessionKey, wait.sessionId, wait.status, wait.version, JSON.stringify(wait), wait.originRunId, wait.originToolCallId);
189
+ markTaskWaiting(wait);
190
+ bumpSessionInputRevision(db, input.sessionKey);
191
+ return wait;
192
+ });
193
+ }
194
+ function isClarificationSuspended(sessionKey, runId) {
195
+ const wait = getActiveClarification(sessionKey);
196
+ return Boolean(wait?.status === "open" && wait.originRunId === runId);
197
+ }
198
+ function expireApproval(wait, now) {
199
+ const expired = {
200
+ ...wait,
201
+ status: "expired",
202
+ resolution: "cancelled",
203
+ resolvedAt: now,
204
+ updatedAt: now
205
+ };
206
+ const updated = writeWait(expired, wait.version) ?? getClarification(wait.id) ?? expired;
207
+ resolveTaskWait(updated, { expired: true });
208
+ cancelTaskRun(updated, "Approval expired before the task could continue.", now);
209
+ bumpSessionInputRevision(getSqliteDatabase(), wait.sessionKey);
210
+ return updated;
211
+ }
212
+ function resolveClarification(input) {
213
+ return runSqliteWriteTransaction((db) => {
214
+ const wait = getClarification(input.id);
215
+ if (!wait || readCurrentSessionId(db, wait.sessionKey) !== wait.sessionId) return {
216
+ ok: false,
217
+ code: "NOT_FOUND"
218
+ };
219
+ const now = input.now ?? Date.now();
220
+ if (wait.kind === "approval" && wait.expiresAt !== void 0 && wait.expiresAt <= now) return {
221
+ ok: false,
222
+ code: "EXPIRED",
223
+ clarification: expireApproval(wait, now)
224
+ };
225
+ if (db.prepare("SELECT id FROM session_inputs WHERE session_key = ? AND client_message_id = ?").get(wait.sessionKey, input.idempotencyKey)) return {
226
+ ok: true,
227
+ clarification: wait,
228
+ idempotent: true,
229
+ queued: wait.status === "queued"
230
+ };
231
+ if (wait.responseIdempotencyKey === input.idempotencyKey) return {
232
+ ok: true,
233
+ clarification: wait,
234
+ idempotent: true,
235
+ queued: wait.status === "queued"
236
+ };
237
+ if (wait.version !== input.expectedVersion || wait.status !== "open") return {
238
+ ok: false,
239
+ code: "CONFLICT",
240
+ clarification: wait
241
+ };
242
+ const trimmed = input.answer?.trim() ?? "";
243
+ if (input.action === "answer" && !trimmed) return {
244
+ ok: false,
245
+ code: "INVALID"
246
+ };
247
+ if (input.action === "agent_decide" && wait.kind === "approval") return {
248
+ ok: false,
249
+ code: "INVALID"
250
+ };
251
+ const resolution = input.action === "answer" ? "answered" : input.action === "agent_decide" ? "agent_decide" : "cancelled";
252
+ if (input.action === "cancel") {
253
+ const cancelled = writeWait({
254
+ ...wait,
255
+ status: "cancelled",
256
+ resolution,
257
+ responseIdempotencyKey: input.idempotencyKey,
258
+ resolvedAt: now,
259
+ updatedAt: now
260
+ }, wait.version);
261
+ if (!cancelled) return {
262
+ ok: false,
263
+ code: "CONFLICT",
264
+ clarification: getClarification(wait.id)
265
+ };
266
+ resolveTaskWait(cancelled, { cancelled: true });
267
+ cancelTaskRun(cancelled, "Task cancelled while waiting for clarification.", now);
268
+ bumpSessionInputRevision(db, wait.sessionKey);
269
+ return {
270
+ ok: true,
271
+ clarification: cancelled,
272
+ idempotent: false,
273
+ queued: false
274
+ };
275
+ }
276
+ const answer = input.action === "agent_decide" ? "Use your best judgment and continue without additional user input." : trimmed;
277
+ const queued = writeWait({
278
+ ...wait,
279
+ status: "queued",
280
+ answer,
281
+ resolution,
282
+ responseIdempotencyKey: input.idempotencyKey,
283
+ updatedAt: now
284
+ }, wait.version);
285
+ if (!queued) return {
286
+ ok: false,
287
+ code: "CONFLICT",
288
+ clarification: getClarification(wait.id)
289
+ };
290
+ const stale = now - wait.checkpoint.originalRequestAt >= STALE_CONTEXT_MS;
291
+ const content = [
292
+ "Resume the objective that was waiting for clarification.",
293
+ `Original objective: ${wait.checkpoint.objectiveSummary}`,
294
+ `Clarification question: ${wait.question}`,
295
+ `User response: ${answer}`,
296
+ stale ? "The request is over 24 hours old. Re-check mutable state before acting." : "",
297
+ "Do not repeat completed side effects. Continue from the stored transcript and current state."
298
+ ].filter(Boolean).join("\n");
299
+ const origin = getSessionInputById(wait.sessionKey, wait.originInputId);
300
+ insertSessionInput({
301
+ id: randomUUID(),
302
+ sessionKey: wait.sessionKey,
303
+ expectedSessionId: wait.sessionId,
304
+ clientMessageId: input.idempotencyKey,
305
+ requestedDelivery: "next",
306
+ effectiveDelivery: "next",
307
+ status: "queued",
308
+ content,
309
+ kind: "clarification_resume",
310
+ payload: {
311
+ waitId: wait.id,
312
+ objectiveRevision: wait.objectiveRevision,
313
+ resolution
314
+ },
315
+ taskRunId: wait.taskRunId,
316
+ contextRefs: origin?.contextRefs,
317
+ contextSnapshots: origin?.contextSnapshots,
318
+ thinking: origin?.thinking,
319
+ origin: {
320
+ type: "system",
321
+ source: "internal"
322
+ }
323
+ });
324
+ return {
325
+ ok: true,
326
+ clarification: queued,
327
+ idempotent: false,
328
+ queued: true
329
+ };
330
+ });
331
+ }
332
+ function getClarificationResumeInput(sessionKey, runId) {
333
+ if (!isXopcDatabaseOpen()) return void 0;
334
+ const state = getSessionInputState(sessionKey);
335
+ if (state.activeRunId !== runId || !state.activeInputId) return void 0;
336
+ const input = getSessionInputById(sessionKey, state.activeInputId);
337
+ return input?.kind === "clarification_resume" ? input : void 0;
338
+ }
339
+ function consumeClarificationResume(input) {
340
+ if (input.kind !== "clarification_resume") return true;
341
+ return runSqliteWriteTransaction((db) => {
342
+ const wait = input.payload ? getClarification(input.payload.waitId) : void 0;
343
+ if (!wait || wait.status !== "queued" || wait.objectiveRevision !== input.payload?.objectiveRevision) return false;
344
+ if (readCurrentSessionId(db, input.sessionKey) !== wait.sessionId) return false;
345
+ if (wait.taskRunId) {
346
+ const runs = new TaskRunRepository();
347
+ const run = runs.get(wait.taskRunId);
348
+ if (!run || run.status !== "waiting") return false;
349
+ if (runs.listActiveWaits(run.taskId).filter((item) => item.taskRunId === run.id).some((item) => item.condition.clarificationId !== wait.id)) return false;
350
+ resolveTaskWait(wait, {
351
+ clarificationId: wait.id,
352
+ resolution: wait.resolution
353
+ });
354
+ runs.setStatus({
355
+ runId: run.id,
356
+ expectedVersion: run.version,
357
+ from: ["waiting"],
358
+ to: "running",
359
+ actor: { kind: "system" }
360
+ });
361
+ } else resolveTaskWait(wait, {
362
+ clarificationId: wait.id,
363
+ resolution: wait.resolution
364
+ });
365
+ if (!writeWait({
366
+ ...wait,
367
+ status: "resolved",
368
+ resolvedAt: Date.now(),
369
+ updatedAt: Date.now()
370
+ }, wait.version)) return false;
371
+ bumpSessionInputRevision(db, wait.sessionKey);
372
+ return true;
373
+ });
374
+ }
375
+ function consumeClarificationApproval(sessionKey, approvalKey) {
376
+ return runSqliteWriteTransaction(() => {
377
+ const state = getSessionInputState(sessionKey);
378
+ if (!state.activeInputId) return void 0;
379
+ const input = getSessionInputById(sessionKey, state.activeInputId);
380
+ if (input?.kind !== "clarification_resume" || !input.payload) return void 0;
381
+ const wait = getClarification(input.payload.waitId);
382
+ if (!wait || wait.kind !== "approval" || wait.approvalKey !== approvalKey || wait.approvalConsumedAt) return;
383
+ const approved = wait.answer === "Allow once";
384
+ writeWait({
385
+ ...wait,
386
+ approvalConsumedAt: Date.now(),
387
+ updatedAt: Date.now()
388
+ }, wait.version);
389
+ return approved ? "approved" : "denied";
390
+ });
391
+ }
392
+ function supersedeActiveClarification(sessionKey, now = Date.now()) {
393
+ return runSqliteWriteTransaction((db) => {
394
+ const wait = getActiveClarification(sessionKey);
395
+ if (!wait) return void 0;
396
+ if (wait.status === "queued") {
397
+ const queued = db.prepare(`SELECT id FROM session_inputs
398
+ WHERE session_key = ? AND kind = 'clarification_resume'
399
+ AND status = 'queued' AND json_extract(payload_json, '$.waitId') = ?`).get(sessionKey, wait.id);
400
+ if (queued) db.prepare(`UPDATE session_inputs SET status = 'cancelled', version = version + 1, updated_at_ms = ?
401
+ WHERE id = ? AND status = 'queued'`).run(now, queued.id);
402
+ }
403
+ const updated = writeWait({
404
+ ...wait,
405
+ status: "superseded",
406
+ resolution: "cancelled",
407
+ resolvedAt: now,
408
+ updatedAt: now
409
+ }, wait.version);
410
+ if (!updated) return void 0;
411
+ resolveTaskWait(updated, { superseded: true });
412
+ cancelTaskRun(updated, "Task superseded by a newer instruction.", now);
413
+ bumpSessionInputRevision(db, sessionKey);
414
+ return updated;
415
+ });
416
+ }
417
+ //#endregion
418
+ export { consumeClarificationApproval, consumeClarificationResume, createClarificationWait, getActiveClarification, getClarification, getClarificationResumeInput, getClarificationSnapshot, isClarificationSuspended, resolveClarification, supersedeActiveClarification };
@@ -14,7 +14,8 @@ export { closeTemporalAssertions, createTemporalAssertion, linkContextObjects, l
14
14
  export { createCollaborationRule, getCollaborationRule, listCollaborationRules, setCollaborationRuleStatus, type CollaborationRule, } from './collaboration-rule-repository.js';
15
15
  export { createContextEvidence, type ContextEvidence } from './context-evidence-repository.js';
16
16
  export { getUserPerson, getUserPeopleIndexState, listUserPeople, mergeUserPeople, replaceUserPeopleIndex, summarizeUserPeople, updateUserPerson, } from './user-people-repository.js';
17
- export { cancelQueuedSessionInput, claimNextSessionInput, findSessionInput, finishSessionInputRun, getSessionInputState, getSessionInputById, insertSessionInput, listActiveSessionInputRuns, mutateQueuedSessionInput, recoverSessionInputState, setSessionInputStatus, type SessionInput, type SessionInputDelivery, type SessionInputState, type SessionInputStatus, } from './session-input-repository.js';
17
+ export { cancelQueuedSessionInput, claimNextSessionInput, findSessionInput, finishSessionInputRun, getSessionInputState, getSessionInputById, insertSessionInput, listActiveSessionInputRuns, mutateQueuedSessionInput, recoverSessionInputState, setSessionInputStatus, type SessionInput, type SessionInputDelivery, type SessionInputPayload, type SessionInputState, type SessionInputStatus, } from './session-input-repository.js';
18
+ export { consumeClarificationApproval, consumeClarificationResume, createClarificationWait, getActiveClarification, getClarification, getClarificationResumeInput, getClarificationSnapshot, isClarificationSuspended, resolveClarification, supersedeActiveClarification, type CreateClarificationInput, type ResolveClarificationInput, type ResolveClarificationResult, } from './clarification-wait-repository.js';
18
19
  export { replaceLatestSessionTurnAndQueueInput, validateLatestSessionTurnTarget, type ReplaceLatestSessionTurnInput, type ReplaceLatestSessionTurnResult, } from './session-turn-replace-repository.js';
19
20
  export { acknowledgeHomeAttention, isHomeAttentionAcknowledged, type HomeAttentionSubjectKind, } from './home-attention-repository.js';
20
21
  export { claimNextConnectorLearningJob, enqueueConnectorLearningJob, listConnectorLearningJobs, recoverStaleConnectorLearningJobs, setConnectorLearningPaused, updateConnectorLearningJob, type ConnectorLearningJob, type ConnectorLearningMode, type ConnectorLearningPhase, type ConnectorLearningStatus, } from './connector-learning-repository.js';
@@ -16,6 +16,7 @@ import { createCollaborationRule, getCollaborationRule, listCollaborationRules,
16
16
  import { createContextEvidence } from "./context-evidence-repository.js";
17
17
  import { getUserPeopleIndexState, getUserPerson, listUserPeople, mergeUserPeople, replaceUserPeopleIndex, summarizeUserPeople, updateUserPerson } from "./user-people-repository.js";
18
18
  import { cancelQueuedSessionInput, claimNextSessionInput, findSessionInput, finishSessionInputRun, getSessionInputById, getSessionInputState, insertSessionInput, listActiveSessionInputRuns, mutateQueuedSessionInput, recoverSessionInputState, setSessionInputStatus } from "./session-input-repository.js";
19
+ import { consumeClarificationApproval, consumeClarificationResume, createClarificationWait, getActiveClarification, getClarification, getClarificationResumeInput, getClarificationSnapshot, isClarificationSuspended, resolveClarification, supersedeActiveClarification } from "./clarification-wait-repository.js";
19
20
  import { buildDefaultSessionMetadata } from "./session-metadata.js";
20
21
  import { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow } from "./row-mappers.js";
21
22
  import { replaceLatestSessionTurnAndQueueInput, validateLatestSessionTurnTarget } from "./session-turn-replace-repository.js";
@@ -38,4 +39,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
38
39
  import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
39
40
  import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
40
41
  import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
41
- export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeConnectorApproval, consumeDevicePairingToken, countKnowledgeSourceItems, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActivityEventRecord, getCachedConnectorCatalogEntry, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
42
+ export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, consumeDevicePairingToken, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
@@ -0,0 +1,60 @@
1
+ CREATE TABLE session_clarification_waits (
2
+ id TEXT PRIMARY KEY,
3
+ principal_id TEXT NOT NULL,
4
+ session_key TEXT NOT NULL,
5
+ session_id TEXT NOT NULL,
6
+ origin_run_id TEXT NOT NULL,
7
+ origin_tool_call_id TEXT NOT NULL,
8
+ status TEXT NOT NULL CHECK (status IN (
9
+ 'open', 'queued', 'resolved', 'expired', 'cancelled', 'superseded'
10
+ )),
11
+ version INTEGER NOT NULL,
12
+ data_json TEXT NOT NULL,
13
+ UNIQUE(session_id, origin_run_id, origin_tool_call_id)
14
+ );
15
+
16
+ CREATE UNIQUE INDEX idx_clarification_wait_active
17
+ ON session_clarification_waits(principal_id, session_id)
18
+ WHERE status IN ('open', 'queued');
19
+
20
+ CREATE INDEX idx_clarification_wait_session
21
+ ON session_clarification_waits(session_key, session_id, status);
22
+
23
+ CREATE TABLE session_inputs_v154 (
24
+ id TEXT PRIMARY KEY,
25
+ session_key TEXT NOT NULL,
26
+ client_message_id TEXT NOT NULL,
27
+ requested_delivery TEXT NOT NULL CHECK (requested_delivery IN ('next', 'steer')),
28
+ effective_delivery TEXT NOT NULL CHECK (effective_delivery IN ('next', 'steer')),
29
+ status TEXT NOT NULL CHECK (status IN (
30
+ 'queued', 'running', 'injecting',
31
+ 'completed', 'cancelled', 'failed', 'interrupted', 'suspended'
32
+ )),
33
+ content TEXT NOT NULL,
34
+ attachments_json TEXT,
35
+ thinking TEXT,
36
+ origin_json TEXT NOT NULL,
37
+ position INTEGER NOT NULL,
38
+ target_run_id TEXT,
39
+ run_id TEXT,
40
+ version INTEGER NOT NULL DEFAULT 1,
41
+ error TEXT,
42
+ created_at_ms INTEGER NOT NULL,
43
+ updated_at_ms INTEGER NOT NULL,
44
+ expected_session_id TEXT,
45
+ context_refs_json TEXT,
46
+ context_snapshots_json TEXT,
47
+ kind TEXT NOT NULL DEFAULT 'message' CHECK (
48
+ kind IN ('message', 'connection_resume', 'clarification_resume')
49
+ ),
50
+ payload_json TEXT,
51
+ task_run_id TEXT,
52
+ UNIQUE(session_key, client_message_id)
53
+ );
54
+
55
+ INSERT INTO session_inputs_v154
56
+ SELECT * FROM session_inputs;
57
+ DROP TABLE session_inputs;
58
+ ALTER TABLE session_inputs_v154 RENAME TO session_inputs;
59
+ CREATE INDEX idx_session_inputs_pending
60
+ ON session_inputs(session_key,status,position,created_at_ms);
@@ -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 = 153;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 154;
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 = 153;
15
+ const XOPC_DB_SCHEMA_VERSION = 154;
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 ?? 153;
60
+ const targetVersion = options.targetVersion ?? 154;
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 ?? 153;
97
+ const appVersion = options.targetVersion ?? 154;
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 = 153;
22
+ export const XOPC_DB_SCHEMA_VERSION = 154;
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: 153,
35
+ targetVersion: 154,
36
36
  databasePath: options.databasePath
37
37
  });
38
38
  }
@@ -3,6 +3,15 @@ import { type TurnOrigin } from '@xopcai/endpoint-tools-protocol';
3
3
  import type { AgentSourceContext, SourceContextRefSummary } from '../../agent/source-context/types.js';
4
4
  export type SessionInputDelivery = 'next' | 'steer';
5
5
  export type SessionInputStatus = 'queued' | 'running' | 'injecting' | 'completed' | 'cancelled' | 'failed' | 'interrupted' | 'suspended';
6
+ export type SessionInputPayload = {
7
+ waitId: string;
8
+ objectiveRevision: number;
9
+ resolution: 'continued' | 'skipped';
10
+ } | {
11
+ waitId: string;
12
+ objectiveRevision: number;
13
+ resolution: 'answered' | 'agent_decide' | 'cancelled';
14
+ };
6
15
  export type SessionInput = {
7
16
  id: string;
8
17
  sessionKey: string;
@@ -13,12 +22,8 @@ export type SessionInput = {
13
22
  status: SessionInputStatus;
14
23
  content: string;
15
24
  taskRunId?: string;
16
- kind: 'message' | 'connection_resume';
17
- payload?: {
18
- waitId: string;
19
- objectiveRevision: number;
20
- resolution: 'continued' | 'skipped';
21
- };
25
+ kind: 'message' | 'connection_resume' | 'clarification_resume';
26
+ payload?: SessionInputPayload;
22
27
  attachments?: unknown[];
23
28
  contextRefs?: SourceContextRefSummary[];
24
29
  contextSnapshots?: AgentSourceContext[];
@@ -167,7 +167,7 @@ function createAgentVoiceEngine(options) {
167
167
  if (response.abortController.signal.aborted || closed) return;
168
168
  for await (const event of options.runtime.runAgent(text, claim.request.sessionKey, response.abortController.signal)) {
169
169
  if (activeResponse !== response || response.abortController.signal.aborted) return;
170
- if (event.type === "assistant_delta" || event.type === "tool_end") response.awaitingClarification = false;
170
+ if (event.type === "assistant_delta" || event.type === "tool_end" && event.payload?.toolName !== "clarify") response.awaitingClarification = false;
171
171
  if (event.type === "assistant_delta" && typeof event.payload?.delta === "string") {
172
172
  if (response.text.length + event.payload.delta.length > 32e3) throw new Error("Voice response text limit reached");
173
173
  if (!response.firstTextSeen) {
@@ -196,8 +196,13 @@ function createAgentVoiceEngine(options) {
196
196
  send("response.clarification", {
197
197
  responseId: response.id,
198
198
  requestId: event.payload.requestId.slice(0, 160),
199
+ kind: event.payload.kind === "approval" ? "approval" : "input",
199
200
  question: event.payload.question.slice(0, 8e3),
200
- ...Array.isArray(event.payload.choices) ? { choices: event.payload.choices.filter((choice) => typeof choice === "string").slice(0, 20).map((choice) => choice.slice(0, 1e3)) } : {}
201
+ ...Array.isArray(event.payload.choices) ? { choices: event.payload.choices.filter((choice) => typeof choice === "string").slice(0, 20).map((choice) => choice.slice(0, 1e3)) } : {},
202
+ ...typeof event.payload.suggestedAnswer === "string" ? { suggestedAnswer: event.payload.suggestedAnswer.slice(0, 1e3) } : {},
203
+ version: typeof event.payload.version === "number" ? event.payload.version : 1,
204
+ createdAt: typeof event.payload.createdAt === "number" ? event.payload.createdAt : Date.now(),
205
+ ...typeof event.payload.expiresAt === "number" ? { expiresAt: event.payload.expiresAt } : {}
201
206
  });
202
207
  }
203
208
  if (event.type === "error") throw new Error(typeof event.payload?.message === "string" ? event.payload.message : "Agent response failed");
@@ -46,8 +46,13 @@ interface VoiceAgentEvent {
46
46
  toolCallId?: unknown;
47
47
  toolName?: unknown;
48
48
  requestId?: unknown;
49
+ kind?: unknown;
49
50
  question?: unknown;
50
51
  choices?: unknown;
52
+ suggestedAnswer?: unknown;
53
+ version?: unknown;
54
+ createdAt?: unknown;
55
+ expiresAt?: unknown;
51
56
  };
52
57
  }
53
58
  export interface VoiceRealtimeRuntimeOptions {