@xopcai/xopc 0.0.207 → 0.0.210

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 (204) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-BmpM0zwM.js → activity-store-JLmEb1p0.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DhK5wi6_.js → agent-avatar-dicebear-CI1zQfzY.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DqGMj3QJ.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-CzaAcDOn.js → api-C6MmWfcb.js} +1 -1
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-Cd02GGpV.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-Db-h2I3G.js +1 -0
  9. package/dist/gateway/static/root/assets/apps-page-BT7F4WBI.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-CgnzBplN.js → archive-plugin-CMHzJT2a.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Cuybcmhn.js → attachment-load-BzhI2LoH.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-CwOXGV9z.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-D6BBx6Ps.js → binary-plugins-DsUeHvZO.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-Dk1c3Spa.js → block-editor-CFfsIeZ4.js} +46 -46
  15. package/dist/gateway/static/root/assets/browser-settings-page-CyRLhCod.js +8 -0
  16. package/dist/gateway/static/root/assets/{browser-workflow-inputs-DvfIzCgV.js → browser-workflow-inputs-BiWghvJ0.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-workflows-page-DZScuPlF.js → browser-workflows-page-DPLdT6Zn.js} +2 -2
  18. package/dist/gateway/static/root/assets/capabilities-settings-panel-jRKcS7lZ.js +7 -0
  19. package/dist/gateway/static/root/assets/{capability-presets-api-hoA8R_J1.js → capability-presets-api-CTxGFvsS.js} +1 -1
  20. package/dist/gateway/static/root/assets/capability-presets-settings-panel-B3bKdtwU.js +3 -0
  21. package/dist/gateway/static/root/assets/{channel-recipient-api-BS8I65NT.js → channel-recipient-api-BklVUOxC.js} +1 -1
  22. package/dist/gateway/static/root/assets/channels-settings-yZBWH02s.js +1 -0
  23. package/dist/gateway/static/root/assets/channels-status-swr-C3zlimZd.js +1 -0
  24. package/dist/gateway/static/root/assets/chat-terminal-dock-0F4Jmma2.js +36 -0
  25. package/dist/gateway/static/root/assets/{connectors-api-B_78jmvM.js → connectors-api-BvIZ51ty.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-OX4KvUkA.js +2 -0
  27. package/dist/gateway/static/root/assets/{cron-expression-BBheaBIr.js → cron-expression-BHmwaMbO.js} +1 -1
  28. package/dist/gateway/static/root/assets/{date-picker-CDwj7UrT.js → date-picker-fj_pPCv5.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-Dnrc2qZe.js → dependency-picker-DsWvwOv-.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-Bj_vUjXp.js → desktop-pet-mjkF0Xxh.js} +1 -1
  31. package/dist/gateway/static/root/assets/desktop-pet-settings-ClwUpRYu.js +1 -0
  32. package/dist/gateway/static/root/assets/directory-picker-path-field-OkqRFyRL.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-_GZ4y2da.js → extension-debug-page-DC69wplH.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-scR96Edg.js → extension-page-DCtk6zdJ.js} +1 -1
  35. package/dist/gateway/static/root/assets/extension-settings-page-Bkm4zzv-.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-config-api-984O_4wM.js → gateway-config-api-Dr_NQt7v.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-swr-D4hvsdJA.js → gateway-config-swr-CEfv8N1J.js} +1 -1
  38. package/dist/gateway/static/root/assets/gateway-settings-V1XVxjHa.js +1 -0
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-Deo5-O87.js → gateway-startup-retry-B8hebJ7s.js} +1 -1
  40. package/dist/gateway/static/root/assets/heartbeat-settings-CWUBAQrE.js +1 -0
  41. package/dist/gateway/static/root/assets/home-page-D57cYRd3.js +1 -0
  42. package/dist/gateway/static/root/assets/index-DJ7HSgKs.js +85 -0
  43. package/dist/gateway/static/root/assets/index-PNBFdxHb.css +2 -0
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DGmOlNcB.js → keyboard-shortcuts-settings-DCQvf05d.js} +1 -1
  45. package/dist/gateway/static/root/assets/local-app-workbench-page-BbAiMZE1.js +2 -0
  46. package/dist/gateway/static/root/assets/{local-apps-page-CzS2sCxg.js → local-apps-page-B3Ugd0my.js} +1 -1
  47. package/dist/gateway/static/root/assets/{locale-store-C7xtkP3D.js → locale-store-hDBVeG3G.js} +1 -1
  48. package/dist/gateway/static/root/assets/logs-page-nXdF3wOT.js +2 -0
  49. package/dist/gateway/static/root/assets/{management-settings-Cpxs43JB.js → management-settings-C-S5Llq3.js} +1 -1
  50. package/dist/gateway/static/root/assets/{markdown-split-CQvFHxUa.js → markdown-split-DuVq37Uh.js} +1 -1
  51. package/dist/gateway/static/root/assets/{markdown-view-BRwrSbwM.js → markdown-view-D8eO_6h3.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-Bs9MsiaM.js → media-plugins-C1V6pkX3.js} +1 -1
  53. package/dist/gateway/static/root/assets/messages-1qg_hOOd.js +3 -0
  54. package/dist/gateway/static/root/assets/{notes-page-Dux_g6aZ.js → notes-page-Dn71ZV8c.js} +1 -1
  55. package/dist/gateway/static/root/assets/notes-workbench-BYPoZeRw.js +4 -0
  56. package/dist/gateway/static/root/assets/page-tabs-B5a5aSoS.js +1 -0
  57. package/dist/gateway/static/root/assets/preview-open-alternatives-5041AIBX.js +1 -0
  58. package/dist/gateway/static/root/assets/{product-open-page-f_jbg-9N.js → product-open-page-7UkouFQU.js} +1 -1
  59. package/dist/gateway/static/root/assets/project-detail-page-D27nOKbo.js +1 -0
  60. package/dist/gateway/static/root/assets/projects-page-CdB5cJJ-.js +1 -0
  61. package/dist/gateway/static/root/assets/remote-access-hub-DFoZ3UNS.js +1 -0
  62. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-zapSiJrv.js → runtime-tools-settings-panel-DvaXzHYS.js} +2 -2
  63. package/dist/gateway/static/root/assets/{schema-form-CFyz8y5v.js → schema-form-Dlxl_5X0.js} +1 -1
  64. package/dist/gateway/static/root/assets/sessions-page-C1cbIcJ7.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-advanced-gate-DnXRlQXS.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-form-section-CSaiuuer.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DFUJEv4G.js → settings-loading-skeleton-H3mJwt3r.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-page-Cnp9Bdd0.js → settings-page-Cs7zA4BS.js} +1 -1
  69. package/dist/gateway/static/root/assets/setup-status-panel-CwgMODfJ.js +1 -0
  70. package/dist/gateway/static/root/assets/{share-preview-page-DA8nA4cz.js → share-preview-page-Bdpw5m7M.js} +1 -1
  71. package/dist/gateway/static/root/assets/shares-settings-hlUgIkrp.js +1 -0
  72. package/dist/gateway/static/root/assets/skill-reload-api-DR31B_Gz.js +1 -0
  73. package/dist/gateway/static/root/assets/skills-page-Bup3Lg1Z.js +2 -0
  74. package/dist/gateway/static/root/assets/{skills-page.utils--1-vOg3V.js → skills-page.utils-D22ORR21.js} +1 -1
  75. package/dist/gateway/static/root/assets/system-settings-panel-GmtWsfjB.js +1 -0
  76. package/dist/gateway/static/root/assets/task-detail-page-CTKDpxhf.js +1 -0
  77. package/dist/gateway/static/root/assets/{theme-store-DoyRfkoi.js → theme-store-CtY8RwMX.js} +1 -1
  78. package/dist/gateway/static/root/assets/typed-models-lib-C2aOdlEA.js +1 -0
  79. package/dist/gateway/static/root/assets/{use-autosave-DzIR5Lxf.js → use-autosave-DOj5i8d_.js} +1 -1
  80. package/dist/gateway/static/root/assets/user-context-page-keJJYpix.js +1 -0
  81. package/dist/gateway/static/root/assets/{voice-api-key-field-B7MZS8tS.js → voice-api-key-field-5WfurWYa.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-zyX6yxxF.js → work-discovery-overlay-D5_MH3n3.js} +1 -1
  83. package/dist/gateway/static/root/assets/work-discovery-page-BcvBiebt.js +1 -0
  84. package/dist/gateway/static/root/assets/workflow-run-setup-panel-bBA8LinI.js +3 -0
  85. package/dist/gateway/static/root/assets/workflows-page-Cz2VpWdj.js +5 -0
  86. package/dist/gateway/static/root/index.html +11 -15
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/agent-manager.js +2 -2
  89. package/dist/src/agent/background-review/coordinator.d.ts +1 -1
  90. package/dist/src/agent/background-review/coordinator.js +4 -5
  91. package/dist/src/agent/background-review/run-background-review.js +0 -1
  92. package/dist/src/agent/background-review/settings.d.ts +1 -2
  93. package/dist/src/agent/background-review/settings.js +3 -4
  94. package/dist/src/agent/external-tools/composio-provider.js +8 -4
  95. package/dist/src/agent/memory/builtin-provider.js +1 -1
  96. package/dist/src/agent/memory/create-memory-manager.js +1 -1
  97. package/dist/src/agent/memory/manager.js +2 -0
  98. package/dist/src/agent/memory/sensitivity.js +1 -1
  99. package/dist/src/agent/memory/understanding/service.js +43 -19
  100. package/dist/src/agent/memory/user-context-coordinator.js +1 -1
  101. package/dist/src/agent-runtime/index.js +1 -1
  102. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  103. package/dist/src/automations/domain/validation.d.ts +7 -7
  104. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  105. package/dist/src/connectors/auth-provider-registry.d.ts +2 -1
  106. package/dist/src/connectors/auth-provider-registry.js +5 -2
  107. package/dist/src/connectors/composio-sessions.d.ts +38 -0
  108. package/dist/src/connectors/composio-sessions.js +64 -6
  109. package/dist/src/connectors/composio.d.ts +4 -1
  110. package/dist/src/connectors/composio.js +26 -4
  111. package/dist/src/connectors/runtime-adapter-registry.js +14 -1
  112. package/dist/src/gateway/hono/routes/agent-stream.js +4 -1
  113. package/dist/src/gateway/hono/routes/connectors.js +15 -2
  114. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +60 -0
  115. package/dist/src/gateway/hono/routes/session-input-handler.js +75 -1
  116. package/dist/src/gateway/service/agent-runner.d.ts +9 -1
  117. package/dist/src/gateway/service/agent-runner.js +9 -0
  118. package/dist/src/gateway/service/session-input-coordinator.d.ts +12 -0
  119. package/dist/src/gateway/service/session-input-coordinator.js +64 -6
  120. package/dist/src/gateway/service.d.ts +8 -0
  121. package/dist/src/gateway/service.js +8 -5
  122. package/dist/src/retrieval/audit.d.ts +1 -0
  123. package/dist/src/retrieval/audit.js +8 -0
  124. package/dist/src/retrieval/candidateFusion.d.ts +5 -0
  125. package/dist/src/retrieval/candidateFusion.js +20 -0
  126. package/dist/src/retrieval/queryProfile.d.ts +16 -0
  127. package/dist/src/retrieval/queryProfile.js +66 -0
  128. package/dist/src/retrieval/textFeatures.d.ts +5 -0
  129. package/dist/src/retrieval/textFeatures.js +71 -0
  130. package/dist/src/session/client-history.d.ts +1 -0
  131. package/dist/src/session/client-history.js +4 -0
  132. package/dist/src/session/index.js +1 -1
  133. package/dist/src/session/store.js +1 -1
  134. package/dist/src/storage/sqlite/fts.d.ts +0 -4
  135. package/dist/src/storage/sqlite/fts.js +2 -49
  136. package/dist/src/storage/sqlite/index.d.ts +3 -2
  137. package/dist/src/storage/sqlite/index.js +6 -5
  138. package/dist/src/storage/sqlite/memory-records-repository.js +60 -38
  139. package/dist/src/storage/sqlite/row-mappers.js +2 -2
  140. package/dist/src/storage/sqlite/session-repository.js +2 -2
  141. package/dist/src/storage/sqlite/session-turn-replace-repository.d.ts +34 -0
  142. package/dist/src/storage/sqlite/session-turn-replace-repository.js +110 -0
  143. package/dist/src/storage/sqlite/transcript-repository.js +1 -1
  144. package/dist/src/storage/sqlite/user-context-quality-repository.d.ts +7 -0
  145. package/dist/src/storage/sqlite/user-context-quality-repository.js +25 -1
  146. package/dist/src/storage/sqlite/user-context-repository.d.ts +4 -0
  147. package/dist/src/storage/sqlite/user-context-repository.js +29 -3
  148. package/dist/src/tasks/home-query-service.d.ts +3 -1
  149. package/dist/src/tasks/home-query-service.js +73 -70
  150. package/dist/src/tui/backends/embedded-backend.js +1 -1
  151. package/dist/src/user-context/planner.d.ts +1 -0
  152. package/dist/src/user-context/planner.js +16 -29
  153. package/dist/src/user-context/retriever.d.ts +15 -0
  154. package/dist/src/user-context/retriever.js +65 -0
  155. package/dist/src/user-context/scope.d.ts +7 -0
  156. package/dist/src/user-context/scope.js +9 -0
  157. package/package.json +3 -3
  158. package/dist/gateway/static/root/assets/agents-Bc3Lc-n2.js +0 -68
  159. package/dist/gateway/static/root/assets/app-management-settings-panel-Dqj5G_cd.js +0 -1
  160. package/dist/gateway/static/root/assets/appearance-settings-Bm1uLGMi.js +0 -1
  161. package/dist/gateway/static/root/assets/apps-page-BKtwU47-.js +0 -1
  162. package/dist/gateway/static/root/assets/automations-page-ilGeRLDN.js +0 -6
  163. package/dist/gateway/static/root/assets/browser-settings-page-BCu8AZbs.js +0 -8
  164. package/dist/gateway/static/root/assets/capabilities-settings-panel-BbWQBtTe.js +0 -7
  165. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BTVU46Yn.js +0 -3
  166. package/dist/gateway/static/root/assets/channels-settings-BEQsC9a9.js +0 -1
  167. package/dist/gateway/static/root/assets/channels-status-swr-DRwbgtOT.js +0 -1
  168. package/dist/gateway/static/root/assets/chat-terminal-dock-BIPhWBDI.js +0 -36
  169. package/dist/gateway/static/root/assets/connectors-page-w_3kpqbc.js +0 -2
  170. package/dist/gateway/static/root/assets/desktop-pet-settings-uiCwJJk4.js +0 -1
  171. package/dist/gateway/static/root/assets/directory-picker-path-field-D0zUQ-TO.js +0 -1
  172. package/dist/gateway/static/root/assets/extension-settings-page-CILsAwxx.js +0 -1
  173. package/dist/gateway/static/root/assets/form-field-width-DJw_jULe.js +0 -1
  174. package/dist/gateway/static/root/assets/gateway-settings-aF4eQHo3.js +0 -1
  175. package/dist/gateway/static/root/assets/heartbeat-settings-D5DrFWH6.js +0 -1
  176. package/dist/gateway/static/root/assets/home-page-DiMWxngC.js +0 -3
  177. package/dist/gateway/static/root/assets/index-DzKLVgY-.js +0 -85
  178. package/dist/gateway/static/root/assets/index-wR5jX-lw.css +0 -2
  179. package/dist/gateway/static/root/assets/interaction-BmQogeqz.js +0 -1
  180. package/dist/gateway/static/root/assets/local-app-workbench-page-De8vuwu1.js +0 -2
  181. package/dist/gateway/static/root/assets/logs-page-BI9stsVO.js +0 -2
  182. package/dist/gateway/static/root/assets/messages-Dxk5Rzj_.js +0 -3
  183. package/dist/gateway/static/root/assets/notes-workbench-CGafcgJ8.js +0 -4
  184. package/dist/gateway/static/root/assets/page-tabs-BaEQMYm_.js +0 -1
  185. package/dist/gateway/static/root/assets/preview-open-alternatives-fvhtN4Y2.js +0 -1
  186. package/dist/gateway/static/root/assets/project-detail-page-C6mNsjYr.js +0 -1
  187. package/dist/gateway/static/root/assets/projects-page-D1G6VIxR.js +0 -1
  188. package/dist/gateway/static/root/assets/remote-access-hub-CIez6X0x.js +0 -1
  189. package/dist/gateway/static/root/assets/sessions-page-6irxQjHb.js +0 -1
  190. package/dist/gateway/static/root/assets/settings-advanced-gate-CRb0QTG2.js +0 -1
  191. package/dist/gateway/static/root/assets/settings-form-draft-Dy10ldo8.js +0 -1
  192. package/dist/gateway/static/root/assets/settings-form-section-DCiK4TIq.js +0 -1
  193. package/dist/gateway/static/root/assets/setup-status-panel-BFMGTGBO.js +0 -1
  194. package/dist/gateway/static/root/assets/shares-settings-CaKfvJzQ.js +0 -1
  195. package/dist/gateway/static/root/assets/skill-reload-api-BOBUcYr5.js +0 -1
  196. package/dist/gateway/static/root/assets/skills-page-BJJACxzz.js +0 -2
  197. package/dist/gateway/static/root/assets/system-settings-panel-DY0lIaXY.js +0 -1
  198. package/dist/gateway/static/root/assets/task-detail-page-Ciuwe7AG.js +0 -1
  199. package/dist/gateway/static/root/assets/typed-models-lib-q5-Vfqd8.js +0 -1
  200. package/dist/gateway/static/root/assets/user-context-page-yf18T_BZ.js +0 -1
  201. package/dist/gateway/static/root/assets/work-discovery-page-2e5J0sIp.js +0 -1
  202. package/dist/gateway/static/root/assets/workflow-run-setup-panel-Cj1vPWRM.js +0 -3
  203. package/dist/gateway/static/root/assets/workflows-page-D37zWlWY.js +0 -5
  204. package/dist/gateway/static/root/assets/working-directory-picker-modal-Bm7cox3y.js +0 -1
@@ -8,7 +8,7 @@ import { resolveComposioApiKey } from "../../../connectors/composio-sessions.js"
8
8
  import { getConnectorLearningPlan } from "../../../connectors/learning-recipes.js";
9
9
  import { listComposioConnectorCatalog } from "../../../connectors/composio-catalog.js";
10
10
  import { createConnectorSetupSecretRequest, submitConnectorSetupSecret } from "../../../connectors/setup-secrets.js";
11
- import { configureComposioApiKey, executeComposioTool, getComposioInstallationPolicy, getComposioToolkitScope, inspectComposioConnectorHealth, listComposioConnections, listComposioTools, refreshComposioConnection, revokeComposioConnection, setComposioToolkitScope, updateComposioConnection, updateComposioInstallationPolicy } from "../../../connectors/composio.js";
11
+ import { configureComposioApiKey, executeComposioTool, getComposioInstallationPolicy, getComposioToolkitAuthState, getComposioToolkitScope, inspectComposioConnectorHealth, listComposioConnections, listComposioTools, refreshComposioConnection, revokeComposioConnection, setComposioToolkitScope, updateComposioConnection, updateComposioInstallationPolicy } from "../../../connectors/composio.js";
12
12
  import { listConnectorProviders } from "../../../connectors/providers.js";
13
13
  import { getConnectorDefinition, listConnectorCatalog } from "../../../connectors/catalog.js";
14
14
  import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
@@ -314,6 +314,19 @@ function registerConnectorRoutes(authenticated, deps) {
314
314
  }, 400);
315
315
  }
316
316
  });
317
+ authenticated.get("/api/connectors/composio/:toolkit/auth-configs", async (c) => {
318
+ try {
319
+ return c.json({
320
+ ok: true,
321
+ payload: { auth: await getComposioToolkitAuthState(c.req.param("toolkit")) }
322
+ });
323
+ } catch (error) {
324
+ return c.json({
325
+ ok: false,
326
+ error: errorMessage(error)
327
+ }, 400);
328
+ }
329
+ });
317
330
  authenticated.get("/api/connectors/composio/:toolkit/scope", async (c) => {
318
331
  const toolkit = c.req.param("toolkit");
319
332
  return c.json({
@@ -566,7 +579,7 @@ function registerConnectorRoutes(authenticated, deps) {
566
579
  error: `Unknown connector: ${connectorId}`
567
580
  }, 404);
568
581
  try {
569
- const authorization = await startConnectorAuthorization(connector);
582
+ const authorization = await startConnectorAuthorization(connector, service.currentConfig);
570
583
  return c.json({
571
584
  ok: true,
572
585
  payload: { authorization }
@@ -60,3 +60,63 @@ export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteD
60
60
  };
61
61
  };
62
62
  }, 202, "json">)>;
63
+ export declare function replaceLatestSessionTurn(c: Context, deps: AuthenticatedRouteDeps, sessionKey: string, targetTurnId: string): Promise<(Response & import("hono").TypedResponse<{
64
+ ok: false;
65
+ error: {
66
+ code: string;
67
+ message: string;
68
+ };
69
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
70
+ ok: false;
71
+ error: {
72
+ code: string;
73
+ message: string;
74
+ };
75
+ }, 401, "json">) | (Response & import("hono").TypedResponse<{
76
+ ok: false;
77
+ error: {
78
+ code: "TARGET_NOT_FOUND" | "NOT_LATEST" | "SESSION_BUSY" | "BAD_REQUEST";
79
+ message: string;
80
+ };
81
+ }, 400 | 404 | 409, "json">) | (Response & import("hono").TypedResponse<{
82
+ ok: true;
83
+ payload: {
84
+ sessionKey: string;
85
+ ok: true;
86
+ effectiveDelivery: "next";
87
+ state: {
88
+ sessionKey: string;
89
+ revision: number;
90
+ activeRunId?: string;
91
+ activeInputId?: string;
92
+ inputs: {
93
+ id: string;
94
+ sessionKey: string;
95
+ clientMessageId: string;
96
+ requestedDelivery: import("../../../storage/sqlite/session-input-repository.js").SessionInputDelivery;
97
+ effectiveDelivery: import("../../../storage/sqlite/session-input-repository.js").SessionInputDelivery;
98
+ status: import("../../../storage/sqlite/session-input-repository.js").SessionInputStatus;
99
+ content: string;
100
+ attachments?: import("hono/dist/types/utils/types.js").JSONValue[];
101
+ thinking?: string;
102
+ origin: {
103
+ type: "endpoint";
104
+ endpointId: string;
105
+ } | {
106
+ type: "channel";
107
+ channel: string;
108
+ } | {
109
+ type: "system";
110
+ source: "cli" | "workflow" | "automation" | "heartbeat" | "internal";
111
+ };
112
+ position: number;
113
+ targetRunId?: string;
114
+ runId?: string;
115
+ version: number;
116
+ error?: string;
117
+ createdAtMs: number;
118
+ updatedAtMs: number;
119
+ }[];
120
+ };
121
+ };
122
+ }, 202, "json">)>;
@@ -78,5 +78,79 @@ async function submitSessionInput(c, deps, sessionKey) {
78
78
  }
79
79
  }, 202);
80
80
  }
81
+ async function replaceLatestSessionTurn(c, deps, sessionKey, targetTurnId) {
82
+ const body = await c.req.json().catch(() => null);
83
+ if (!body || !sessionKey || !targetTurnId) return c.json({
84
+ ok: false,
85
+ error: {
86
+ code: "BAD_REQUEST",
87
+ message: "Invalid request"
88
+ }
89
+ }, 400);
90
+ const attachments = Array.isArray(body.attachments) ? body.attachments : void 0;
91
+ const content = typeof body.content === "string" ? body.content : "";
92
+ const contentError = validateWebchatContent(content);
93
+ if (contentError) return c.json({
94
+ ok: false,
95
+ error: {
96
+ code: "BAD_REQUEST",
97
+ message: contentError
98
+ }
99
+ }, 400);
100
+ const attachmentError = validateWebchatAttachments(attachments);
101
+ if (attachmentError) return c.json({
102
+ ok: false,
103
+ error: {
104
+ code: "BAD_REQUEST",
105
+ message: attachmentError
106
+ }
107
+ }, 400);
108
+ const origin = endpointTurnClaimSchema.safeParse(body.origin);
109
+ if (!origin.success) return c.json({
110
+ ok: false,
111
+ error: {
112
+ code: "BAD_REQUEST",
113
+ message: "Invalid endpoint origin"
114
+ }
115
+ }, 400);
116
+ if (!deps.service.endpointTools.registry.verifyTurnClaim(origin.data.endpointId, origin.data.token)) return c.json({
117
+ ok: false,
118
+ error: {
119
+ code: "INVALID_ENDPOINT",
120
+ message: "Endpoint connection is not active"
121
+ }
122
+ }, 401);
123
+ const result = await deps.service.replaceLatestSessionTurn({
124
+ sessionKey,
125
+ targetTurnId,
126
+ clientMessageId: typeof body.clientMessageId === "string" ? body.clientMessageId : "",
127
+ delivery: "next",
128
+ content,
129
+ attachments,
130
+ thinking: typeof body.thinking === "string" ? body.thinking : void 0,
131
+ origin: {
132
+ type: "endpoint",
133
+ endpointId: origin.data.endpointId
134
+ }
135
+ });
136
+ if (result.ok === false) {
137
+ const status = result.code === "TARGET_NOT_FOUND" ? 404 : result.code === "BAD_REQUEST" ? 400 : 409;
138
+ const message = result.code === "NOT_LATEST" ? "Only the latest user turn can be replaced" : result.code === "SESSION_BUSY" ? "Session has pending input" : result.code === "TARGET_NOT_FOUND" ? "User turn was not found" : "Replacement input was not accepted";
139
+ return c.json({
140
+ ok: false,
141
+ error: {
142
+ code: result.code,
143
+ message
144
+ }
145
+ }, status);
146
+ }
147
+ return c.json({
148
+ ok: true,
149
+ payload: {
150
+ ...result,
151
+ sessionKey
152
+ }
153
+ }, 202);
154
+ }
81
155
  //#endregion
82
- export { submitSessionInput };
156
+ export { replaceLatestSessionTurn, submitSessionInput };
@@ -27,7 +27,7 @@ import type { SessionIndex } from '../../session/index.js';
27
27
  import type { ClarifyStreamEvent } from '../clarify-bridge.js';
28
28
  import { ClarifyBridge, type ClarifyBridgeRequest } from '../clarify-bridge.js';
29
29
  import type { UserTurnAttachment, UserTurnInput } from '../user-turn-input.js';
30
- import { SessionInputCoordinator, type SubmitSessionInput } from './session-input-coordinator.js';
30
+ import { SessionInputCoordinator, type ReplaceLatestTurnInput, type SubmitSessionInput } from './session-input-coordinator.js';
31
31
  export interface GatewayAgentRunnerOptions {
32
32
  bus: MessageBus;
33
33
  sessionIndex: SessionIndex;
@@ -79,6 +79,14 @@ export declare class GatewayAgentRunner {
79
79
  ok: false;
80
80
  code: "BAD_REQUEST" | "QUEUE_FULL";
81
81
  }>;
82
+ replaceLatestSessionTurn(input: ReplaceLatestTurnInput): Promise<{
83
+ ok: true;
84
+ effectiveDelivery: "next";
85
+ state: import("../../storage/sqlite/session-input-repository.js").SessionInputState;
86
+ } | {
87
+ ok: false;
88
+ code: "BAD_REQUEST" | "TARGET_NOT_FOUND" | "NOT_LATEST" | "SESSION_BUSY";
89
+ }>;
82
90
  getSessionInputState(sessionKey: string): import("../../storage/sqlite/session-input-repository.js").SessionInputState;
83
91
  updateSessionInput(sessionKey: string, id: string, body: {
84
92
  version: number;
@@ -115,6 +115,15 @@ var GatewayAgentRunner = class {
115
115
  submitSessionInput(input) {
116
116
  return this.inputs.submit(input);
117
117
  }
118
+ replaceLatestSessionTurn(input) {
119
+ return this.inputs.replaceLatestTurn(input, async () => {
120
+ const activeRunId = this.activeWebchatRunBySession.get(input.sessionKey) ?? this.inputs.snapshot(input.sessionKey).activeRunId;
121
+ if (activeRunId) await this.abortAgentRun(activeRunId);
122
+ const { evictEmbeddedSessionRunner } = await import("../../agent/embedded/session-runner.js");
123
+ evictEmbeddedSessionRunner(input.sessionKey, "gateway_user_turn_replaced");
124
+ this.opts.getAgentService().evictSessionAgent(input.sessionKey);
125
+ });
126
+ }
118
127
  getSessionInputState(sessionKey) {
119
128
  return this.inputs.snapshot(sessionKey);
120
129
  }
@@ -10,6 +10,9 @@ export type SubmitSessionInput = {
10
10
  thinking?: string;
11
11
  origin: TurnOrigin;
12
12
  };
13
+ export type ReplaceLatestTurnInput = SubmitSessionInput & {
14
+ targetTurnId: string;
15
+ };
13
16
  export declare class SessionInputCoordinator {
14
17
  private readonly deps;
15
18
  private readonly draining;
@@ -33,6 +36,7 @@ export declare class SessionInputCoordinator {
33
36
  });
34
37
  snapshot(sessionKey: string): SessionInputState;
35
38
  private publish;
39
+ private runSubmissionExclusive;
36
40
  submit(input: SubmitSessionInput): Promise<{
37
41
  ok: true;
38
42
  effectiveDelivery: SessionInputDelivery;
@@ -41,6 +45,14 @@ export declare class SessionInputCoordinator {
41
45
  ok: false;
42
46
  code: 'BAD_REQUEST' | 'QUEUE_FULL';
43
47
  }>;
48
+ replaceLatestTurn(input: ReplaceLatestTurnInput, beforeReplace: () => Promise<void>): Promise<{
49
+ ok: true;
50
+ effectiveDelivery: 'next';
51
+ state: SessionInputState;
52
+ } | {
53
+ ok: false;
54
+ code: 'BAD_REQUEST' | 'TARGET_NOT_FOUND' | 'NOT_LATEST' | 'SESSION_BUSY';
55
+ }>;
44
56
  private submitLocked;
45
57
  drain(sessionKey: string): Promise<void>;
46
58
  update(sessionKey: string, id: string, body: {
@@ -1,7 +1,9 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { cancelQueuedSessionInput, claimNextSessionInput, findSessionInput, finishSessionInputRun, getSessionInputState, insertSessionInput, mutateQueuedSessionInput, recoverSessionInputState, setSessionInputStatus } from "../../storage/sqlite/session-input-repository.js";
4
+ import { replaceLatestSessionTurnAndQueueInput, validateLatestSessionTurnTarget } from "../../storage/sqlite/session-turn-replace-repository.js";
4
5
  import "../../storage/sqlite/index.js";
6
+ import { deleteMediaUrisNoLongerReferenced } from "../../media/session-references.js";
5
7
  import crypto from "node:crypto";
6
8
  //#region src/gateway/service/session-input-coordinator.ts
7
9
  init_logger();
@@ -21,8 +23,7 @@ var SessionInputCoordinator = class {
21
23
  this.deps.emit("session.input-state", state);
22
24
  return state;
23
25
  }
24
- async submit(input) {
25
- const sessionKey = input.sessionKey.trim();
26
+ async runSubmissionExclusive(sessionKey, operation) {
26
27
  const previous = this.submissionTails.get(sessionKey) ?? Promise.resolve();
27
28
  let release = () => {};
28
29
  const current = new Promise((resolve) => {
@@ -32,15 +33,72 @@ var SessionInputCoordinator = class {
32
33
  this.submissionTails.set(sessionKey, tail);
33
34
  await previous;
34
35
  try {
35
- return await this.submitLocked({
36
- ...input,
37
- sessionKey
38
- });
36
+ return await operation();
39
37
  } finally {
40
38
  release();
41
39
  if (this.submissionTails.get(sessionKey) === tail) this.submissionTails.delete(sessionKey);
42
40
  }
43
41
  }
42
+ async submit(input) {
43
+ const sessionKey = input.sessionKey.trim();
44
+ return this.runSubmissionExclusive(sessionKey, () => this.submitLocked({
45
+ ...input,
46
+ sessionKey
47
+ }));
48
+ }
49
+ async replaceLatestTurn(input, beforeReplace) {
50
+ const sessionKey = input.sessionKey.trim();
51
+ return this.runSubmissionExclusive(sessionKey, async () => {
52
+ const clientMessageId = input.clientMessageId.trim();
53
+ const content = input.content.trim();
54
+ const targetTurnId = input.targetTurnId.trim();
55
+ if (!sessionKey || !clientMessageId || !targetTurnId || !content && !input.attachments?.length) return {
56
+ ok: false,
57
+ code: "BAD_REQUEST"
58
+ };
59
+ if (!await this.deps.sessionExists(sessionKey)) return {
60
+ ok: false,
61
+ code: "BAD_REQUEST"
62
+ };
63
+ if (findSessionInput(sessionKey, clientMessageId)) return {
64
+ ok: true,
65
+ effectiveDelivery: "next",
66
+ state: this.snapshot(sessionKey)
67
+ };
68
+ const target = validateLatestSessionTurnTarget(sessionKey, targetTurnId);
69
+ if (target.ok === false) return target;
70
+ await beforeReplace();
71
+ const attachments = await this.deps.prepareAttachments(sessionKey, input.attachments);
72
+ const result = replaceLatestSessionTurnAndQueueInput({
73
+ sessionKey,
74
+ targetTurnId,
75
+ clientMessageId,
76
+ content,
77
+ attachments,
78
+ thinking: input.thinking,
79
+ origin: input.origin
80
+ });
81
+ if (result.ok === false) return result;
82
+ if (!result.idempotent) {
83
+ const replacement = {
84
+ role: "user",
85
+ content,
86
+ media: attachments
87
+ };
88
+ await deleteMediaUrisNoLongerReferenced({
89
+ removed: result.removedMessages,
90
+ remaining: [...result.remainingMessages, replacement]
91
+ });
92
+ }
93
+ const state = this.publish(sessionKey);
94
+ this.drain(sessionKey);
95
+ return {
96
+ ok: true,
97
+ effectiveDelivery: "next",
98
+ state
99
+ };
100
+ });
101
+ }
44
102
  async submitLocked(input) {
45
103
  const sessionKey = input.sessionKey;
46
104
  const clientMessageId = input.clientMessageId.trim();
@@ -140,6 +140,14 @@ export declare class GatewayService {
140
140
  ok: false;
141
141
  code: "BAD_REQUEST" | "QUEUE_FULL";
142
142
  }>;
143
+ replaceLatestSessionTurn(...args: Parameters<GatewayAgentRunner['replaceLatestSessionTurn']>): Promise<{
144
+ ok: true;
145
+ effectiveDelivery: "next";
146
+ state: import("../storage/sqlite/session-input-repository.js").SessionInputState;
147
+ } | {
148
+ ok: false;
149
+ code: "BAD_REQUEST" | "TARGET_NOT_FOUND" | "NOT_LATEST" | "SESSION_BUSY";
150
+ }>;
143
151
  getSessionInputState(...args: Parameters<GatewayAgentRunner['getSessionInputState']>): import("../storage/sqlite/session-input-repository.js").SessionInputState;
144
152
  updateSessionInput(...args: Parameters<GatewayAgentRunner['updateSessionInput']>): Promise<{
145
153
  ok: boolean;
@@ -55,11 +55,6 @@ import { registerClarifyBridge } from "./clarify-runtime.js";
55
55
  import { ChannelManager } from "../channels/manager.js";
56
56
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
57
57
  import "../config/index.js";
58
- import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
59
- import "../knowledge/index.js";
60
- import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
61
- import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
62
- import { startConnectorSupervisor } from "../connectors/supervisor.js";
63
58
  import { DiscussionService } from "../discussions/service.js";
64
59
  import { DiscussionOrganizer } from "../discussions/organizer.js";
65
60
  import { DiscussionLiveWorker } from "../discussions/live-worker.js";
@@ -68,6 +63,11 @@ import { DiscussionSealer } from "../discussions/sealer.js";
68
63
  import "../discussions/index.js";
69
64
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
70
65
  import "../endpoint-tools/index.js";
66
+ import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
67
+ import "../knowledge/index.js";
68
+ import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
69
+ import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
70
+ import { startConnectorSupervisor } from "../connectors/supervisor.js";
71
71
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
72
72
  import { prepareAutomationAgentSession } from "./automation-agent-session.js";
73
73
  import { reconcileDreamingAutomations } from "./dreaming-automation-reconciler.js";
@@ -641,6 +641,9 @@ var GatewayService = class {
641
641
  submitSessionInput(...args) {
642
642
  return this.agentRunner.submitSessionInput(...args);
643
643
  }
644
+ replaceLatestSessionTurn(...args) {
645
+ return this.agentRunner.replaceLatestSessionTurn(...args);
646
+ }
644
647
  getSessionInputState(...args) {
645
648
  return this.agentRunner.getSessionInputState(...args);
646
649
  }
@@ -0,0 +1 @@
1
+ export declare function retrievalQueryAuditValue(query: string): string;
@@ -0,0 +1,8 @@
1
+ import { createHash } from "node:crypto";
2
+ //#region src/retrieval/audit.ts
3
+ function retrievalQueryAuditValue(query) {
4
+ const normalized = query.normalize("NFKC").trim();
5
+ return `sha256:${createHash("sha256").update(normalized).digest("hex").slice(0, 24)};length=${[...normalized].length}`;
6
+ }
7
+ //#endregion
8
+ export { retrievalQueryAuditValue };
@@ -0,0 +1,5 @@
1
+ export interface RankedCandidateChannel {
2
+ weight: number;
3
+ ids: string[];
4
+ }
5
+ export declare function fuseRankedCandidates(channels: RankedCandidateChannel[], rankConstant?: number): Map<string, number>;
@@ -0,0 +1,20 @@
1
+ //#region src/retrieval/candidateFusion.ts
2
+ function fuseRankedCandidates(channels, rankConstant = 60) {
3
+ const activeChannels = channels.filter((channel) => channel.weight > 0 && channel.ids.length > 0);
4
+ if (!activeChannels.length) return /* @__PURE__ */ new Map();
5
+ const maximum = activeChannels.reduce((sum, channel) => sum + channel.weight / (rankConstant + 1), 0);
6
+ const scores = /* @__PURE__ */ new Map();
7
+ for (const channel of activeChannels) {
8
+ const seen = /* @__PURE__ */ new Set();
9
+ channel.ids.forEach((id, index) => {
10
+ if (!id || seen.has(id)) return;
11
+ seen.add(id);
12
+ const contribution = channel.weight / (rankConstant + index + 1);
13
+ scores.set(id, (scores.get(id) ?? 0) + contribution);
14
+ });
15
+ }
16
+ for (const [id, score] of scores) scores.set(id, score / maximum);
17
+ return scores;
18
+ }
19
+ //#endregion
20
+ export { fuseRankedCandidates };
@@ -0,0 +1,16 @@
1
+ export type RetrievalTimeHint = 'current' | 'recent' | 'historical' | 'future';
2
+ export interface RetrievalScope {
3
+ sessionKey?: string;
4
+ workspaceId?: string;
5
+ projectId?: string;
6
+ }
7
+ export interface RetrievalQueryProfile {
8
+ normalized: string;
9
+ terms: string[];
10
+ cjkBigrams: string[];
11
+ identifiers: string[];
12
+ intentKinds: string[];
13
+ timeHints: RetrievalTimeHint[];
14
+ scope: RetrievalScope;
15
+ }
16
+ export declare function buildRetrievalQueryProfile(query: string, scope?: RetrievalScope): RetrievalQueryProfile;
@@ -0,0 +1,66 @@
1
+ import { extractCjkBigrams, extractLexicalTerms, extractRetrievalIdentifiers, normalizeRetrievalText } from "./textFeatures.js";
2
+ //#region src/retrieval/queryProfile.ts
3
+ const INTENT_RULES = [
4
+ {
5
+ kinds: ["boundary"],
6
+ pattern: /\b(?:avoid|never|permission|confirm|approval)\b|不要|禁止|避免|确认|授权|边界/i
7
+ },
8
+ {
9
+ kinds: ["preference", "tool_preference"],
10
+ pattern: /\b(?:prefer|preference|format|language|style)\b|喜欢|偏好|格式|语言|风格|简洁|详细/i
11
+ },
12
+ {
13
+ kinds: [
14
+ "project_context",
15
+ "workspace_fact",
16
+ "task_lesson"
17
+ ],
18
+ pattern: /\b(?:project|repository|repo|workspace|codebase|deploy|release)\b|项目|仓库|代码库|工作区|发布|部署/i
19
+ },
20
+ {
21
+ kinds: ["long_term_goal", "commitment"],
22
+ pattern: /\b(?:goal|plan|deadline|commitment)\b|目标|计划|截止|承诺/i
23
+ },
24
+ {
25
+ kinds: ["routine"],
26
+ pattern: /\b(?:routine|usually|weekly|daily|every time)\b|习惯|通常|每周|每天|每次/i
27
+ },
28
+ {
29
+ kinds: ["relationship"],
30
+ pattern: /\b(?:person|people|colleague|collaborator|relationship)\b|同事|合作伙伴|关系|联系人/i
31
+ }
32
+ ];
33
+ const TIME_RULES = [
34
+ {
35
+ hint: "current",
36
+ pattern: /\b(?:now|current|today)\b|现在|当前|今天/i
37
+ },
38
+ {
39
+ hint: "recent",
40
+ pattern: /\b(?:recent|recently|latest)\b|最近|近期|最新/i
41
+ },
42
+ {
43
+ hint: "historical",
44
+ pattern: /\b(?:previous|before|history|last time)\b|之前|以前|历史|上次/i
45
+ },
46
+ {
47
+ hint: "future",
48
+ pattern: /\b(?:future|next|later|upcoming)\b|未来|下次|之后|即将/i
49
+ }
50
+ ];
51
+ function buildRetrievalQueryProfile(query, scope = {}) {
52
+ const normalized = normalizeRetrievalText(query);
53
+ const intentKinds = INTENT_RULES.filter((rule) => rule.pattern.test(normalized)).flatMap((rule) => rule.kinds);
54
+ const timeHints = TIME_RULES.filter((rule) => rule.pattern.test(normalized)).map((rule) => rule.hint);
55
+ return {
56
+ normalized,
57
+ terms: extractLexicalTerms(normalized),
58
+ cjkBigrams: extractCjkBigrams(normalized),
59
+ identifiers: extractRetrievalIdentifiers(normalized),
60
+ intentKinds: [...new Set(intentKinds)],
61
+ timeHints: [...new Set(timeHints)],
62
+ scope: { ...scope }
63
+ };
64
+ }
65
+ //#endregion
66
+ export { buildRetrievalQueryProfile };
@@ -0,0 +1,5 @@
1
+ export declare function normalizeRetrievalText(value: string): string;
2
+ export declare function extractLexicalTerms(value: string): string[];
3
+ export declare function extractCjkBigrams(value: string): string[];
4
+ export declare function extractRetrievalIdentifiers(value: string): string[];
5
+ export declare function retrievalLexicalSimilarity(left: string, right: string): number;
@@ -0,0 +1,71 @@
1
+ //#region src/retrieval/textFeatures.ts
2
+ const ENGLISH_STOP_WORDS = new Set([
3
+ "a",
4
+ "an",
5
+ "and",
6
+ "are",
7
+ "can",
8
+ "did",
9
+ "do",
10
+ "does",
11
+ "for",
12
+ "how",
13
+ "i",
14
+ "in",
15
+ "is",
16
+ "it",
17
+ "me",
18
+ "my",
19
+ "of",
20
+ "on",
21
+ "or",
22
+ "the",
23
+ "to",
24
+ "was",
25
+ "what",
26
+ "when",
27
+ "where",
28
+ "which",
29
+ "who",
30
+ "why",
31
+ "with",
32
+ "you",
33
+ "your"
34
+ ]);
35
+ function normalizeRetrievalText(value) {
36
+ return value.normalize("NFKC").toLowerCase().replace(/\s+/g, " ").trim();
37
+ }
38
+ function extractLexicalTerms(value) {
39
+ const terms = normalizeRetrievalText(value).match(/[\p{L}\p{N}_]+/gu)?.filter((term) => term.length > 1 && !ENGLISH_STOP_WORDS.has(term)) ?? [];
40
+ return [...new Set(terms)];
41
+ }
42
+ function extractCjkBigrams(value) {
43
+ const features = [];
44
+ for (const sequence of normalizeRetrievalText(value).match(/\p{Script=Han}+/gu) ?? []) {
45
+ const characters = [...sequence];
46
+ for (let index = 0; index < characters.length - 1; index += 1) features.push(`${characters[index]}${characters[index + 1]}`);
47
+ }
48
+ return [...new Set(features)];
49
+ }
50
+ function extractRetrievalIdentifiers(value) {
51
+ const normalized = normalizeRetrievalText(value);
52
+ const identifiers = [
53
+ ...normalized.match(/@[a-z0-9_.-]+\/[a-z0-9_.-]+/g) ?? [],
54
+ ...normalized.match(/(?:[a-z0-9_.-]+\/)+[a-z0-9_.-]+/g) ?? [],
55
+ ...normalized.match(/\b[a-z0-9_-]+\.[a-z0-9]{1,12}\b/g) ?? [],
56
+ ...normalized.match(/#[0-9]+\b/g) ?? [],
57
+ ...normalized.match(/\b[a-z]+-[a-z0-9-]*[0-9][a-z0-9-]*\b/g) ?? []
58
+ ];
59
+ const unique = [...new Set(identifiers)];
60
+ return unique.filter((identifier) => !unique.includes(`@${identifier}`));
61
+ }
62
+ function retrievalLexicalSimilarity(left, right) {
63
+ const leftFeatures = new Set([...extractLexicalTerms(left).map((term) => `term:${term}`), ...extractCjkBigrams(left).map((term) => `han:${term}`)]);
64
+ const rightFeatures = new Set([...extractLexicalTerms(right).map((term) => `term:${term}`), ...extractCjkBigrams(right).map((term) => `han:${term}`)]);
65
+ if (leftFeatures.size === 0 || rightFeatures.size === 0) return 0;
66
+ let shared = 0;
67
+ for (const feature of leftFeatures) if (rightFeatures.has(feature)) shared += 1;
68
+ return 2 * shared / (leftFeatures.size + rightFeatures.size);
69
+ }
70
+ //#endregion
71
+ export { extractCjkBigrams, extractLexicalTerms, extractRetrievalIdentifiers, normalizeRetrievalText, retrievalLexicalSimilarity };
@@ -3,6 +3,7 @@ import type { TranscriptStoredRow } from './session-context-for-llm.js';
3
3
  /** Transcript row for TUI and HTTP clients (flattened from persisted session messages). */
4
4
  export interface ClientHistoryMessage {
5
5
  id?: string;
6
+ turnId?: string;
6
7
  role: 'user' | 'assistant' | 'system';
7
8
  content: string;
8
9
  displayIndex?: number;
@@ -110,6 +110,7 @@ function messagesToClientHistory(messages, opts) {
110
110
  const text = flattenMessageContent(m.content);
111
111
  out.push({
112
112
  role: m.role,
113
+ ...typeof m.turnId === "string" ? { turnId: m.turnId } : {},
113
114
  content: text,
114
115
  ...m.media?.length ? { media: m.media } : {},
115
116
  timestamp: parseTimestamp(m.timestamp)
@@ -121,6 +122,7 @@ function messagesToClientHistory(messages, opts) {
121
122
  const toolCalls = toolCallsWithResults(collectMessageToolCalls(m.content, m.tool_calls), results);
122
123
  out.push({
123
124
  role: "assistant",
125
+ ...typeof m.turnId === "string" ? { turnId: m.turnId } : {},
124
126
  content: text,
125
127
  timestamp: parseTimestamp(m.timestamp),
126
128
  toolCalls
@@ -408,6 +410,7 @@ function transcriptRowsToClientHistory(rows, opts) {
408
410
  if (messageRow.role === "user" || messageRow.role === "system") {
409
411
  out.push({
410
412
  id,
413
+ ...messageRow.turnId ? { turnId: messageRow.turnId } : {},
411
414
  role: messageRow.role,
412
415
  kind: "message",
413
416
  content: flattenMessageContent(messageRow.content ?? ""),
@@ -420,6 +423,7 @@ function transcriptRowsToClientHistory(rows, opts) {
420
423
  const rawContent = rawAssistantContent(messageRow.content);
421
424
  out.push({
422
425
  id,
426
+ ...messageRow.turnId ? { turnId: messageRow.turnId } : {},
423
427
  role: "assistant",
424
428
  kind: "message",
425
429
  content: flattenMessageContent(messageRow.content ?? ""),
@@ -1,5 +1,5 @@
1
- import { SessionStatus } from "./types.js";
2
1
  import { buildSessionContextForLlm, isTranscriptContextEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray } from "./session-context-for-llm.js";
2
+ import { SessionStatus } from "./types.js";
3
3
  import { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput, projectWorkspacePath } from "./session-workspace.js";
4
4
  import { emitSessionTranscriptUpdate, onSessionTranscriptUpdate } from "./transcript-events.js";
5
5
  import { fallbackTitleFromMessages, generateSessionTitleFromMessages, getSessionTitleSource, isWebchatSessionKey, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, provisionalTitleFromUserText, sanitizeGeneratedSessionTitle, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm } from "./session-title.js";