@xopcai/xopc 0.0.206 → 0.0.207

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 (170) hide show
  1. package/README.md +7 -7
  2. package/README.zh-CN.md +7 -7
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store-URW-e_me.js → activity-store-BmpM0zwM.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BLK6kRCJ.js → agent-avatar-dicebear-DhK5wi6_.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-Bc3Lc-n2.js +68 -0
  8. package/dist/gateway/static/root/assets/{api-C_MS4arC.js → api-CzaAcDOn.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-CnUN6BJk.js → app-management-settings-panel-Dqj5G_cd.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-C8Nx8hZE.js → appearance-settings-Bm1uLGMi.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-BKtwU47-.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-C7FqeJZD.js → archive-plugin-CgnzBplN.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-DCYQgsYE.js → attachment-load-Cuybcmhn.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-ilGeRLDN.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-Bf1WROsh.js → binary-plugins-D6BBx6Ps.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BPK08Pjv.js → block-editor-Dk1c3Spa.js} +3 -3
  17. package/dist/gateway/static/root/assets/browser-settings-page-BCu8AZbs.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-cqVoDHyp.js → browser-workflow-inputs-DvfIzCgV.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-Des1UTsS.js → browser-workflows-page-DZScuPlF.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-BbWQBtTe.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-D4MjqV2a.js → capability-presets-api-hoA8R_J1.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BTVU46Yn.js +3 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-CcimZduy.js → channel-recipient-api-BS8I65NT.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-BEQsC9a9.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-DRwbgtOT.js +1 -0
  26. package/dist/gateway/static/root/assets/chat-terminal-dock-BIPhWBDI.js +36 -0
  27. package/dist/gateway/static/root/assets/{chat-terminal-dock-B1njb2Cr.css → chat-terminal-dock-uQUnjRtf.css} +1 -1
  28. package/dist/gateway/static/root/assets/{connectors-api-CUvFu8jh.js → connectors-api-B_78jmvM.js} +1 -1
  29. package/dist/gateway/static/root/assets/{connectors-page-BJoHjWnu.js → connectors-page-w_3kpqbc.js} +2 -2
  30. package/dist/gateway/static/root/assets/{cron-expression-hFSZZpvM.js → cron-expression-BBheaBIr.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-CKZ0gc-Y.js → date-picker-CDwj7UrT.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-zv1oHtg4.js → dependency-picker-Dnrc2qZe.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-DY9ykMtD.js → desktop-pet-Bj_vUjXp.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-XiSmmt26.js → desktop-pet-settings-uiCwJJk4.js} +1 -1
  35. package/dist/gateway/static/root/assets/{directory-picker-path-field-CZkgk15r.js → directory-picker-path-field-D0zUQ-TO.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-debug-page-CTppsTEi.js → extension-debug-page-_GZ4y2da.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-CHRTUvAa.js → extension-page-scR96Edg.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-z2UBx25A.js → extension-settings-page-CILsAwxx.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-api-DzFPJTnm.js → gateway-config-api-984O_4wM.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-CGpoH1gU.js → gateway-config-swr-D4hvsdJA.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-settings-DBa2I6VM.js → gateway-settings-aF4eQHo3.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-Te-TREBt.js → gateway-startup-retry-Deo5-O87.js} +1 -1
  43. package/dist/gateway/static/root/assets/{heartbeat-settings-DyQGGdBu.js → heartbeat-settings-D5DrFWH6.js} +1 -1
  44. package/dist/gateway/static/root/assets/{home-page-EkT4eGeP.js → home-page-DiMWxngC.js} +2 -2
  45. package/dist/gateway/static/root/assets/{index-CrwXzRpA.js → index-DzKLVgY-.js} +47 -47
  46. package/dist/gateway/static/root/assets/index-wR5jX-lw.css +2 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-fb0zS8pk.js → keyboard-shortcuts-settings-DGmOlNcB.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-De8vuwu1.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-DFdheruU.js → local-apps-page-CzS2sCxg.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-CieddUjx.js → locale-store-C7xtkP3D.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-BI9stsVO.js +2 -0
  52. package/dist/gateway/static/root/assets/{management-settings-D3PsQ612.js → management-settings-Cpxs43JB.js} +1 -1
  53. package/dist/gateway/static/root/assets/{markdown-split-x5K52Thz.js → markdown-split-CQvFHxUa.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-view-Cjjey5Y6.js → markdown-view-BRwrSbwM.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-DNtEkRAh.js → media-plugins-Bs9MsiaM.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-Dxk5Rzj_.js +3 -0
  57. package/dist/gateway/static/root/assets/{notes-page-nWEqlwDw.js → notes-page-Dux_g6aZ.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-CGafcgJ8.js +4 -0
  59. package/dist/gateway/static/root/assets/{preview-open-alternatives-CXcIKVi9.js → preview-open-alternatives-fvhtN4Y2.js} +1 -1
  60. package/dist/gateway/static/root/assets/{product-open-page-CZLJudPk.js → product-open-page-f_jbg-9N.js} +1 -1
  61. package/dist/gateway/static/root/assets/{project-detail-page-Cf1v94LO.js → project-detail-page-C6mNsjYr.js} +1 -1
  62. package/dist/gateway/static/root/assets/{projects-page-BRMZkNht.js → projects-page-D1G6VIxR.js} +1 -1
  63. package/dist/gateway/static/root/assets/remote-access-hub-CIez6X0x.js +1 -0
  64. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-RYjduQV6.js → runtime-tools-settings-panel-zapSiJrv.js} +1 -1
  65. package/dist/gateway/static/root/assets/{schema-form--1ZXg4qC.js → schema-form-CFyz8y5v.js} +1 -1
  66. package/dist/gateway/static/root/assets/sessions-page-6irxQjHb.js +1 -0
  67. package/dist/gateway/static/root/assets/settings-advanced-gate-CRb0QTG2.js +1 -0
  68. package/dist/gateway/static/root/assets/{settings-form-section-71-8j3zt.js → settings-form-section-DCiK4TIq.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-loading-skeleton-C5Jn1l0q.js → settings-loading-skeleton-DFUJEv4G.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-TYYGe6kZ.js → settings-page-Cnp9Bdd0.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-jA5I-17g.js → setup-status-panel-BFMGTGBO.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-BMUQIGfk.js → share-preview-page-DA8nA4cz.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-CaKfvJzQ.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-BOBUcYr5.js +1 -0
  75. package/dist/gateway/static/root/assets/{skills-page-BzZT1SKg.js → skills-page-BJJACxzz.js} +1 -1
  76. package/dist/gateway/static/root/assets/{skills-page.utils-DnaBw5Ji.js → skills-page.utils--1-vOg3V.js} +1 -1
  77. package/dist/gateway/static/root/assets/{system-settings-panel-DqiPQgVI.js → system-settings-panel-DY0lIaXY.js} +1 -1
  78. package/dist/gateway/static/root/assets/task-detail-page-Ciuwe7AG.js +1 -0
  79. package/dist/gateway/static/root/assets/{theme-store-BP3_RpaY.js → theme-store-DoyRfkoi.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-autosave-BJkQ-vpu.js → use-autosave-DzIR5Lxf.js} +1 -1
  81. package/dist/gateway/static/root/assets/{user-context-page-BP8-sOPi.js → user-context-page-yf18T_BZ.js} +1 -1
  82. package/dist/gateway/static/root/assets/{voice-api-key-field-C6c8e7Mx.js → voice-api-key-field-B7MZS8tS.js} +1 -1
  83. package/dist/gateway/static/root/assets/{work-discovery-overlay-CCNjWKql.js → work-discovery-overlay-zyX6yxxF.js} +1 -1
  84. package/dist/gateway/static/root/assets/work-discovery-page-2e5J0sIp.js +1 -0
  85. package/dist/gateway/static/root/assets/workflow-run-setup-panel-Cj1vPWRM.js +3 -0
  86. package/dist/gateway/static/root/assets/workflows-page-D37zWlWY.js +5 -0
  87. package/dist/gateway/static/root/assets/{working-directory-picker-modal-vWi33CZJ.js → working-directory-picker-modal-Bm7cox3y.js} +1 -1
  88. package/dist/gateway/static/root/index.html +10 -10
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/embedded/transcript-runtime.d.ts +2 -1
  91. package/dist/src/agent/embedded/transcript-runtime.js +38 -4
  92. package/dist/src/agent/inbound/inbound-loop.d.ts +1 -1
  93. package/dist/src/agent/memory/compaction-ledger.d.ts +11 -0
  94. package/dist/src/agent/memory/compaction-ledger.js +108 -0
  95. package/dist/src/agent/memory/compaction-serializer.d.ts +2 -0
  96. package/dist/src/agent/memory/compaction-serializer.js +52 -0
  97. package/dist/src/agent/memory/compaction-source-planner.d.ts +20 -0
  98. package/dist/src/agent/memory/compaction-source-planner.js +67 -0
  99. package/dist/src/agent/memory/compaction.d.ts +11 -5
  100. package/dist/src/agent/memory/compaction.js +245 -153
  101. package/dist/src/agent/prompt/sections/behavior.js +1 -1
  102. package/dist/src/agent/prompt/sections/memory-skills.js +4 -2
  103. package/dist/src/agent/prompt/sections/tooling.js +2 -0
  104. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  105. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  106. package/dist/src/agent/tools/factory.js +5 -0
  107. package/dist/src/agent/tools/index.d.ts +1 -0
  108. package/dist/src/agent/tools/index.js +2 -1
  109. package/dist/src/agent/tools/session-recall-tool.d.ts +7 -0
  110. package/dist/src/agent/tools/session-recall-tool.js +82 -0
  111. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  112. package/dist/src/config/agent-profile.js +1 -1
  113. package/dist/src/config/schema.d.ts +1 -0
  114. package/dist/src/gateway/agents-admin.js +1 -1
  115. package/dist/src/gateway/heartbeat/service.js +1 -1
  116. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
  117. package/dist/src/gateway/service/run-gateway-agent.js +3 -3
  118. package/dist/src/heartbeat/index.js +1 -1
  119. package/dist/src/session/compaction-types.d.ts +30 -0
  120. package/dist/src/session/compaction-types.js +35 -0
  121. package/dist/src/session/manager.d.ts +3 -0
  122. package/dist/src/session/session-context-for-llm.d.ts +4 -2
  123. package/dist/src/session/session-context-for-llm.js +2 -1
  124. package/dist/src/session/store.d.ts +10 -1
  125. package/dist/src/session/store.js +55 -23
  126. package/dist/src/session/types.d.ts +3 -2
  127. package/dist/src/storage/sqlite/index.d.ts +1 -1
  128. package/dist/src/storage/sqlite/index.js +2 -2
  129. package/dist/src/storage/sqlite/migrations/123_remove_v2_compaction_boundaries.sql +25 -0
  130. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  131. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  132. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  133. package/dist/src/storage/sqlite/schema.js +1 -1
  134. package/dist/src/storage/sqlite/transcript-repository.d.ts +24 -1
  135. package/dist/src/storage/sqlite/transcript-repository.js +78 -29
  136. package/dist/src/user-context/config.d.ts +4 -0
  137. package/dist/src/user-context/config.js +2 -0
  138. package/package.json +3 -3
  139. package/skills/THIRD_PARTY_NOTICES.md +1 -1
  140. package/skills/engineering/define-task/SKILL.md +48 -0
  141. package/skills/engineering/define-task/references/task-contract-rubric.md +15 -0
  142. package/dist/gateway/static/root/assets/agents-D5HVmdNx.js +0 -68
  143. package/dist/gateway/static/root/assets/apps-page-DKCA_LFY.js +0 -1
  144. package/dist/gateway/static/root/assets/automations-page-BEOE4ZKM.js +0 -6
  145. package/dist/gateway/static/root/assets/browser-settings-page-CLRmMdU9.js +0 -8
  146. package/dist/gateway/static/root/assets/capabilities-settings-panel-BNcVi4ar.js +0 -7
  147. package/dist/gateway/static/root/assets/capability-presets-settings-panel-uFwW2ah5.js +0 -3
  148. package/dist/gateway/static/root/assets/channels-settings-DSLP8OjS.js +0 -1
  149. package/dist/gateway/static/root/assets/channels-status-swr-D0OR6Ylw.js +0 -1
  150. package/dist/gateway/static/root/assets/chat-terminal-dock-wpi7abPg.js +0 -38
  151. package/dist/gateway/static/root/assets/index-BpLqHdfz.css +0 -2
  152. package/dist/gateway/static/root/assets/local-app-workbench-page-CCC3Cvb8.js +0 -2
  153. package/dist/gateway/static/root/assets/logs-page-B6jfkNDF.js +0 -2
  154. package/dist/gateway/static/root/assets/messages-CySMn8WL.js +0 -3
  155. package/dist/gateway/static/root/assets/notes-workbench-QstkgWsW.js +0 -4
  156. package/dist/gateway/static/root/assets/remote-access-hub-D55FTXZw.js +0 -1
  157. package/dist/gateway/static/root/assets/sessions-page-C5Yy6eIn.js +0 -1
  158. package/dist/gateway/static/root/assets/settings-advanced-gate-BqO_8bUh.js +0 -1
  159. package/dist/gateway/static/root/assets/shares-settings-Dru1a2rZ.js +0 -1
  160. package/dist/gateway/static/root/assets/skill-reload-api-C8iqS6kF.js +0 -1
  161. package/dist/gateway/static/root/assets/task-detail-page-DQP5vDr-.js +0 -1
  162. package/dist/gateway/static/root/assets/work-discovery-page-DL_Ie0s2.js +0 -1
  163. package/dist/gateway/static/root/assets/workflow-run-setup-panel-DLO-dMSN.js +0 -3
  164. package/dist/gateway/static/root/assets/workflows-page-B4-k2FHB.js +0 -5
  165. package/dist/src/agent/memory/compaction-planner.d.ts +0 -16
  166. package/dist/src/agent/memory/compaction-planner.js +0 -168
  167. package/dist/src/agent/memory/summary-generator.d.ts +0 -46
  168. package/dist/src/agent/memory/summary-generator.js +0 -229
  169. package/skills/engineering/define-goal/SKILL.md +0 -41
  170. package/skills/engineering/define-goal/references/objective-rubric.md +0 -12
@@ -15,6 +15,7 @@ import { createExecCommandTool } from "./exec-command.js";
15
15
  import { createApplyPatchTool } from "./apply-patch.js";
16
16
  import { createMemoryGetTool, createMemorySearchTool } from "./memory-tool.js";
17
17
  import { createSessionSearchTool } from "./session-search-tool.js";
18
+ import { createSessionRecallTool } from "./session-recall-tool.js";
18
19
  import { createGrepTool } from "./grep.js";
19
20
  import { createFindTool } from "./find.js";
20
21
  import { createWebFetchTool, createWebSearchTool } from "./web.js";
@@ -299,6 +300,10 @@ var AgentToolsFactory = class {
299
300
  ...this.deps.getCurrentContext?.()?.sessionKey ? { sessionKey: this.deps.getCurrentContext().sessionKey } : {}
300
301
  })
301
302
  })] : [],
303
+ ...this.deps.getSessionStore ? [createSessionRecallTool({
304
+ getSessionStore: this.deps.getSessionStore,
305
+ getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey
306
+ })] : [],
302
307
  ...this.deps.getSessionStore && getPrimary ? [createSessionSearchTool({
303
308
  getSessionStore: this.deps.getSessionStore,
304
309
  getPrimaryModel: getPrimary,
@@ -7,6 +7,7 @@ export { createExecCommandTool, type ExecCommandDetails, type ExecCommandUpdateD
7
7
  export { createApplyPatchTool, type AppliedPatchChange, type ApplyPatchDetails, } from './apply-patch.js';
8
8
  export { createMemorySearchTool, createMemoryGetTool, type MemoryToolOptions, } from './memory-tool.js';
9
9
  export { createSessionSearchTool } from './session-search-tool.js';
10
+ export { createSessionRecallTool, type SessionRecallToolDeps } from './session-recall-tool.js';
10
11
  export { grepTool, createGrepTool, type GrepToolInput, type GrepToolDetails, } from './grep.js';
11
12
  export { findTool, createFindTool, type FindToolInput, type FindToolDetails, } from './find.js';
12
13
  export { createWebSearchTool, createWebFetchTool } from './web.js';
@@ -9,6 +9,7 @@ import { fuzzyFindText, generateDiffString, normalizeForFuzzyMatch, normalizeToL
9
9
  import { createApplyPatchTool } from "./apply-patch.js";
10
10
  import { createMemoryGetTool, createMemorySearchTool } from "./memory-tool.js";
11
11
  import { createSessionSearchTool } from "./session-search-tool.js";
12
+ import { createSessionRecallTool } from "./session-recall-tool.js";
12
13
  import { createGrepTool, grepTool } from "./grep.js";
13
14
  import { createFindTool, findTool } from "./find.js";
14
15
  import { createWebFetchTool, createWebSearchTool } from "./web.js";
@@ -41,4 +42,4 @@ import { createManagedJobTool } from "./managed-job-tool.js";
41
42
  import { resolveImageModelConfigForTool } from "../image/tool-model-config.js";
42
43
  import { createImageTool } from "./image-tool.js";
43
44
  import { createImageGenerateTool, resolveImageGenerationModelConfigForTool } from "./image-generate-tool.js";
44
- export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_TOOL_METADATA, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, ToolConcurrencyController, assertBrowserUrlAllowed, buildSandboxToolMap, createApplyPatchTool, createAutomationTool, createBrowserRecipeTool, createClarifyTool, createCreateShareTool, createDelegateTool, createDesktopPetTool, createDreamingTool, createExecCommandTool, createExecuteCodeTool, createFindTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createManagedJobTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createReadMediaTool, createSendMediaTool, createSessionSearchTool, createSessionStatusTool, createSkillInstallTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createSkillsMarketplaceSearchTool, createTodoTool, createToolManualTool, createUpdatePlanTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, createXopcUseTool, findTool, formatSize, fuzzyFindText, generateDiffString, getToolMetadata, grepTool, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, resolveToolLockMode, restoreLineEndings, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
45
+ export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_TOOL_METADATA, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, ToolConcurrencyController, assertBrowserUrlAllowed, buildSandboxToolMap, createApplyPatchTool, createAutomationTool, createBrowserRecipeTool, createClarifyTool, createCreateShareTool, createDelegateTool, createDesktopPetTool, createDreamingTool, createExecCommandTool, createExecuteCodeTool, createFindTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createManagedJobTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createReadMediaTool, createSendMediaTool, createSessionRecallTool, createSessionSearchTool, createSessionStatusTool, createSkillInstallTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createSkillsMarketplaceSearchTool, createTodoTool, createToolManualTool, createUpdatePlanTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, createXopcUseTool, findTool, formatSize, fuzzyFindText, generateDiffString, getToolMetadata, grepTool, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, resolveToolLockMode, restoreLineEndings, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
@@ -0,0 +1,7 @@
1
+ import type { AgentTool } from '@earendil-works/pi-agent-core';
2
+ import type { SessionStore } from '../../session/store.js';
3
+ export interface SessionRecallToolDeps {
4
+ getSessionStore: () => SessionStore;
5
+ getCurrentSessionKey: () => string | undefined;
6
+ }
7
+ export declare function createSessionRecallTool(deps: SessionRecallToolDeps): AgentTool;
@@ -0,0 +1,82 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ //#region src/agent/tools/session-recall-tool.ts
3
+ const SessionRecallSchema = Type.Object({
4
+ query: Type.String({
5
+ minLength: 1,
6
+ maxLength: 500,
7
+ description: "Keywords, an exact phrase, path, URL, ID, date, or name to find in this session."
8
+ }),
9
+ limit: Type.Optional(Type.Integer({
10
+ minimum: 1,
11
+ maximum: 20,
12
+ default: 8
13
+ })),
14
+ beforeSeq: Type.Optional(Type.Integer({
15
+ minimum: 1,
16
+ description: "Return matches older than this transcript sequence number."
17
+ })),
18
+ maxCharsPerResult: Type.Optional(Type.Integer({
19
+ minimum: 500,
20
+ maximum: 2e4,
21
+ default: 6e3
22
+ }))
23
+ });
24
+ function excerpt(content, query, maxChars) {
25
+ if (content.length <= maxChars) return content;
26
+ const matchAt = content.toLowerCase().indexOf(query.toLowerCase());
27
+ const center = matchAt >= 0 ? matchAt + Math.floor(query.length / 2) : Math.floor(content.length / 2);
28
+ const start = Math.max(0, Math.min(content.length - maxChars, center - Math.floor(maxChars / 2)));
29
+ const end = Math.min(content.length, start + maxChars);
30
+ return `${start > 0 ? "…\n" : ""}${content.slice(start, end)}${end < content.length ? "\n…" : ""}`;
31
+ }
32
+ function createSessionRecallTool(deps) {
33
+ return {
34
+ name: "session_recall",
35
+ label: "Session recall",
36
+ description: "Search the authoritative raw transcript of the current session, including turns older than context compaction. Use when a continuation summary lacks an exact fact, quote, path, URL, ID, date, decision, or tool outcome. This tool cannot access other sessions.",
37
+ parameters: SessionRecallSchema,
38
+ supportsParallel: true,
39
+ idempotent: true,
40
+ async execute(_toolCallId, params) {
41
+ const input = params;
42
+ const sessionKey = deps.getCurrentSessionKey();
43
+ if (!sessionKey) return {
44
+ content: [{
45
+ type: "text",
46
+ text: "session_recall is unavailable outside an active session."
47
+ }],
48
+ details: { error: "missing_session" }
49
+ };
50
+ const query = input.query.trim();
51
+ const limit = Math.min(20, Math.max(1, input.limit ?? 8));
52
+ const maxChars = Math.min(2e4, Math.max(500, input.maxCharsPerResult ?? 6e3));
53
+ const results = deps.getSessionStore().recallSession(sessionKey, query, {
54
+ limit,
55
+ ...input.beforeSeq ? { beforeSeq: input.beforeSeq } : {}
56
+ }).map((match) => ({
57
+ seq: match.seq,
58
+ entryId: match.entryId,
59
+ role: match.role,
60
+ createdAt: new Date(match.createdAt).toISOString(),
61
+ content: excerpt(match.content, query, maxChars)
62
+ }));
63
+ const nextBeforeSeq = results.length === limit ? Math.min(...results.map((result) => result.seq)) : void 0;
64
+ const payload = {
65
+ success: true,
66
+ query,
67
+ results,
68
+ count: results.length,
69
+ ...nextBeforeSeq ? { nextBeforeSeq } : {}
70
+ };
71
+ return {
72
+ content: [{
73
+ type: "text",
74
+ text: JSON.stringify(payload, null, 2)
75
+ }],
76
+ details: payload
77
+ };
78
+ }
79
+ };
80
+ }
81
+ //#endregion
82
+ export { createSessionRecallTool };
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v122).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v123).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -1,6 +1,6 @@
1
- import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
2
1
  import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
3
2
  import "../agent-manifest/index.js";
3
+ import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
4
4
  import { init_session_key, parseSessionKey } from "../routing/session-key.js";
5
5
  import { agentExists, getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
6
6
  //#region src/config/agent-profile.ts
@@ -1537,6 +1537,7 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1537
1537
  summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
1538
1538
  summaryRetries: z.ZodDefault<z.ZodNumber>;
1539
1539
  qualityGuard: z.ZodDefault<z.ZodBoolean>;
1540
+ gapAudit: z.ZodDefault<z.ZodBoolean>;
1540
1541
  model: z.ZodOptional<z.ZodString>;
1541
1542
  minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
1542
1543
  maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
@@ -1,5 +1,5 @@
1
- import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
1
  import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
2
+ import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
3
3
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
4
4
  import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
5
5
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
4
+ import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
4
5
  import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
5
6
  import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
6
- import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
7
7
  import { createHeartbeatWake } from "../../heartbeat/wake.js";
8
8
  import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
9
9
  import { readFile } from "fs/promises";
@@ -320,6 +320,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
320
320
  summaryTimeoutMs: number;
321
321
  summaryRetries: number;
322
322
  qualityGuard: boolean;
323
+ gapAudit: boolean;
323
324
  minToolResultKeepChars: number;
324
325
  maxActiveTranscriptBytes: number;
325
326
  postCompactionSections: string[];
@@ -187,11 +187,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
187
187
  skipTaskReview: reviewHint?.skipTaskReview ?? false,
188
188
  outboundMetadata: {}
189
189
  });
190
- } catch (goalErr) {
190
+ } catch (completionErr) {
191
191
  log.warn({
192
- err: goalErr,
192
+ err: completionErr,
193
193
  sessionKey
194
- }, `Session turn complete failed: ${goalErr instanceof Error ? goalErr.message : String(goalErr)}`);
194
+ }, `Session turn complete failed: ${completionErr instanceof Error ? completionErr.message : String(completionErr)}`);
195
195
  }
196
196
  agentService.endInboundTurn(sessionKey);
197
197
  }
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
2
+ import { appendCronEventLines } from "./event-prompt.js";
2
3
  import { isWithinActiveHours } from "./active-hours.js";
3
4
  import { isHeartbeatContentEmpty } from "./content-check.js";
4
- import { appendCronEventLines } from "./event-prompt.js";
5
5
  import { createHeartbeatWake } from "./wake.js";
6
6
  export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
@@ -0,0 +1,30 @@
1
+ export declare const HANDOVER_ITEM_KINDS: readonly ["objective", "decision", "pending_user_ask", "todo", "constraint", "file_change", "tool_outcome", "failure", "current_state", "next_action"];
2
+ export type HandoverItemKind = typeof HANDOVER_ITEM_KINDS[number];
3
+ export type HandoverItemStatus = 'active' | 'completed' | 'superseded';
4
+ export interface CompactionSourceRef {
5
+ entryId: string;
6
+ seq: number;
7
+ }
8
+ export interface CompactionHandoverItem {
9
+ id: string;
10
+ kind: HandoverItemKind;
11
+ text: string;
12
+ status: HandoverItemStatus;
13
+ sources: CompactionSourceRef[];
14
+ identifiers: string[];
15
+ }
16
+ export interface CompactionHandover {
17
+ version: 1;
18
+ sourceThroughSeq: number;
19
+ previousBoundaryId?: string;
20
+ items: CompactionHandoverItem[];
21
+ }
22
+ export interface CompactionAudit {
23
+ status: 'passed' | 'degraded' | 'disabled';
24
+ mode: 'structural' | 'risk' | 'full';
25
+ missingItemsFound: number;
26
+ repaired: boolean;
27
+ auditModelRef?: string;
28
+ }
29
+ export declare function isCompactionHandover(value: unknown): value is CompactionHandover;
30
+ export declare function isCompactionAudit(value: unknown): value is CompactionAudit;
@@ -0,0 +1,35 @@
1
+ //#region src/session/compaction-types.ts
2
+ const HANDOVER_ITEM_KINDS = [
3
+ "objective",
4
+ "decision",
5
+ "pending_user_ask",
6
+ "todo",
7
+ "constraint",
8
+ "file_change",
9
+ "tool_outcome",
10
+ "failure",
11
+ "current_state",
12
+ "next_action"
13
+ ];
14
+ function isCompactionHandover(value) {
15
+ if (!value || typeof value !== "object") return false;
16
+ const handover = value;
17
+ const sourceThroughSeq = Number(handover.sourceThroughSeq);
18
+ if (handover.version !== 1 || !Number.isInteger(handover.sourceThroughSeq) || sourceThroughSeq < 0 || handover.previousBoundaryId !== void 0 && typeof handover.previousBoundaryId !== "string" || !Array.isArray(handover.items)) return false;
19
+ return handover.items.every((item) => {
20
+ if (!item || typeof item !== "object") return false;
21
+ const record = item;
22
+ return typeof record.id === "string" && record.id.length > 0 && HANDOVER_ITEM_KINDS.includes(record.kind) && typeof record.text === "string" && record.text.length > 0 && (record.status === "active" || record.status === "completed" || record.status === "superseded") && Array.isArray(record.sources) && record.sources.length > 0 && record.sources.every((source) => {
23
+ if (!source || typeof source !== "object") return false;
24
+ const ref = source;
25
+ return typeof ref.entryId === "string" && ref.entryId.length > 0 && Number.isInteger(ref.seq) && Number(ref.seq) > 0 && Number(ref.seq) <= sourceThroughSeq;
26
+ }) && Array.isArray(record.identifiers) && record.identifiers.every((identifier) => typeof identifier === "string");
27
+ });
28
+ }
29
+ function isCompactionAudit(value) {
30
+ if (!value || typeof value !== "object") return false;
31
+ const audit = value;
32
+ return (audit.status === "passed" || audit.status === "degraded" || audit.status === "disabled") && (audit.mode === "structural" || audit.mode === "risk" || audit.mode === "full") && Number.isInteger(audit.missingItemsFound) && typeof audit.repaired === "boolean" && (audit.auditModelRef === void 0 || typeof audit.auditModelRef === "string");
33
+ }
34
+ //#endregion
35
+ export { HANDOVER_ITEM_KINDS, isCompactionAudit, isCompactionHandover };
@@ -185,6 +185,9 @@ export declare class SessionIndex extends EventEmitter {
185
185
  compactionCount: number;
186
186
  totalTokensBefore: number;
187
187
  totalTokensAfter: number;
188
+ auditPassedCount: number;
189
+ auditDegradedCount: number;
190
+ auditMissingItemsFound: number;
188
191
  lastCompactionAt: string;
189
192
  }>;
190
193
  listCompactionBoundaries(key: string): Promise<import("./types.js").CompactionBoundarySummary[]>;
@@ -6,6 +6,7 @@
6
6
  * {@link buildSessionContextForLlm} first (or use {@link SessionStore.loadMessages}, which already does).
7
7
  */
8
8
  import type { AgentMessage } from '@earendil-works/pi-agent-core';
9
+ import { type CompactionAudit, type CompactionHandover } from './compaction-types.js';
9
10
  /** Persisted-only row: never sent to the model as a chat message. */
10
11
  export interface XopcTranscriptContextEntry {
11
12
  kind: 'context';
@@ -73,15 +74,16 @@ export interface XopcTranscriptCompactionEntry {
73
74
  type: 'compaction';
74
75
  at: string;
75
76
  baseSeq: number;
76
- plannerVersion: number;
77
+ plannerVersion: 3;
77
78
  summaryModelRef: string;
78
79
  qualityAudit: 'passed' | 'disabled';
80
+ handover: CompactionHandover;
81
+ audit: CompactionAudit;
79
82
  summary: string;
80
83
  messages: AgentMessage[];
81
84
  firstKeptIndex: number;
82
85
  tokensBefore: number;
83
86
  tokensAfter: number;
84
- restoredFromCompactionId?: string;
85
87
  }
86
88
  /** Persisted label change for a transcript entry. */
87
89
  export interface XopcTranscriptLabelEntry {
@@ -1,3 +1,4 @@
1
+ import { isCompactionAudit, isCompactionHandover } from "./compaction-types.js";
1
2
  //#region src/session/session-context-for-llm.ts
2
3
  function isTranscriptContextEntry(x) {
3
4
  if (!x || typeof x !== "object") return false;
@@ -24,7 +25,7 @@ function isTranscriptSummaryMessageEntry(x) {
24
25
  function isTranscriptCompactionEntry(x) {
25
26
  if (!x || typeof x !== "object") return false;
26
27
  const row = x;
27
- return row.type === "compaction" && typeof row.at === "string" && typeof row.baseSeq === "number" && Number.isInteger(row.baseSeq) && typeof row.plannerVersion === "number" && Number.isInteger(row.plannerVersion) && typeof row.summaryModelRef === "string" && (row.qualityAudit === "passed" || row.qualityAudit === "disabled") && typeof row.summary === "string" && Array.isArray(row.messages) && typeof row.firstKeptIndex === "number" && typeof row.tokensBefore === "number" && typeof row.tokensAfter === "number";
28
+ return row.type === "compaction" && typeof row.at === "string" && typeof row.baseSeq === "number" && Number.isInteger(row.baseSeq) && row.plannerVersion === 3 && typeof row.summaryModelRef === "string" && (row.qualityAudit === "passed" || row.qualityAudit === "disabled") && typeof row.summary === "string" && isCompactionHandover(row.handover) && isCompactionAudit(row.audit) && Array.isArray(row.messages) && typeof row.firstKeptIndex === "number" && typeof row.tokensBefore === "number" && typeof row.tokensAfter === "number";
28
29
  }
29
30
  function isTranscriptLabelEntry(x) {
30
31
  if (!x || typeof x !== "object") return false;
@@ -32,11 +32,13 @@ export declare class SessionStore {
32
32
  private window;
33
33
  private compactor;
34
34
  private compactionHooks;
35
+ private readonly compactionTails;
35
36
  constructor(options: SessionStoreOptions, windowConfig?: Partial<WindowConfig>, compactionConfig?: Partial<CompactionConfig>);
36
37
  setCompactionHooks(hooks: SessionCompactionHooks): void;
37
38
  private runCompactionHook;
38
39
  private resolveWorkspaceCwd;
39
40
  private runStoreMutation;
41
+ private runCompactionExclusive;
40
42
  initialize(): Promise<void>;
41
43
  getSessionsRoot(): string;
42
44
  resolveTranscriptPath(sessionKey: string, options?: {
@@ -142,12 +144,15 @@ export declare class SessionStore {
142
144
  tool: number;
143
145
  needsTrim: boolean;
144
146
  };
145
- applyCompaction(key: string, messages: AgentMessage[], result: CompactionResult): Promise<AgentMessage[]>;
147
+ applyCompaction(key: string, result: CompactionResult, expectedSnapshot?: import("../storage/sqlite/transcript-repository.js").CompactionSourceSnapshot): Promise<AgentMessage[]>;
146
148
  compact(key: string, messages: AgentMessage[], model: Model<Api>, instructions?: string, force?: boolean, executionOptions?: CompactionExecutionOptions): Promise<CompactionResult>;
147
149
  getCompactionStats(key: string): Promise<{
148
150
  compactionCount: number;
149
151
  totalTokensBefore: number;
150
152
  totalTokensAfter: number;
153
+ auditPassedCount: number;
154
+ auditDegradedCount: number;
155
+ auditMissingItemsFound: number;
151
156
  lastCompactionAt: string;
152
157
  }>;
153
158
  listCompactionBoundaries(key: string): Promise<CompactionBoundarySummary[]>;
@@ -158,6 +163,10 @@ export declare class SessionStore {
158
163
  }): Promise<AgentMessage[]>;
159
164
  estimateTokenUsage(_key: string, messages: AgentMessage[]): Promise<number>;
160
165
  searchInSession(key: string, keyword: string): Promise<Message[]>;
166
+ recallSession(key: string, query: string, options?: {
167
+ limit?: number;
168
+ beforeSeq?: number;
169
+ }): import("../storage/sqlite/transcript-repository.js").SessionTranscriptRecallMatch[];
161
170
  exportSession(key: string, format: ExportFormat): Promise<string>;
162
171
  importSessionExport(targetKey: string, jsonContent: string): Promise<{
163
172
  sessionKey: string;
@@ -6,7 +6,7 @@ import "./types.js";
6
6
  import { buildSessionContextForLlm, buildSessionDisplayMessages, isRuntimeOnlyTranscriptMessage, isTranscriptCompactionEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray } from "./session-context-for-llm.js";
7
7
  import { estimateTokensFromMessages } from "../storage/sqlite/row-mappers.js";
8
8
  import { deleteSessionRecord, ensureSessionRecord, findSessionKeyBySessionId, getGlobalSessionStats, getSessionMetadata, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord } from "../storage/sqlite/session-repository.js";
9
- import { appendCompactionBoundary, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary } from "../storage/sqlite/transcript-repository.js";
9
+ import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "../storage/sqlite/transcript-repository.js";
10
10
  import "../storage/sqlite/index.js";
11
11
  import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
12
12
  import { readPostCompactionContext } from "../agent/reply/post-compaction-context.js";
@@ -35,6 +35,7 @@ var SessionStore = class {
35
35
  window;
36
36
  compactor;
37
37
  compactionHooks = {};
38
+ compactionTails = /* @__PURE__ */ new Map();
38
39
  constructor(options, windowConfig, compactionConfig) {
39
40
  this.options = options;
40
41
  this.window = new SlidingWindow(windowConfig);
@@ -64,6 +65,21 @@ var SessionStore = class {
64
65
  async runStoreMutation(fn) {
65
66
  return fn();
66
67
  }
68
+ async runCompactionExclusive(sessionKey, fn) {
69
+ const previous = this.compactionTails.get(sessionKey) ?? Promise.resolve();
70
+ let release;
71
+ const current = new Promise((resolve) => {
72
+ release = resolve;
73
+ });
74
+ this.compactionTails.set(sessionKey, current);
75
+ await previous;
76
+ try {
77
+ return await fn();
78
+ } finally {
79
+ release();
80
+ if (this.compactionTails.get(sessionKey) === current) this.compactionTails.delete(sessionKey);
81
+ }
82
+ }
67
83
  async initialize() {
68
84
  requireXopcDatabase();
69
85
  log.debug("Session store initialized (SQLite)");
@@ -297,12 +313,13 @@ var SessionStore = class {
297
313
  plannerVersion: row.plannerVersion,
298
314
  summaryModelRef: row.summaryModelRef,
299
315
  qualityAudit: row.qualityAudit,
316
+ handover: row.handover,
317
+ audit: row.audit,
300
318
  summary: row.summary,
301
319
  messages: row.messages,
302
320
  firstKeptIndex: row.firstKeptIndex,
303
321
  tokensBefore: row.tokensBefore,
304
- tokensAfter: row.tokensAfter,
305
- restoredFromCompactionId: row.restoredFromCompactionId
322
+ tokensAfter: row.tokensAfter
306
323
  });
307
324
  return {
308
325
  type: "xopc_session_transcript",
@@ -419,21 +436,25 @@ var SessionStore = class {
419
436
  getWindowStats(messages) {
420
437
  return this.window.getStats(messages);
421
438
  }
422
- async applyCompaction(key, messages, result) {
423
- const compacted = this.compactor.applyCompaction(messages, result);
439
+ async applyCompaction(key, result, expectedSnapshot = loadCompactionSourceSnapshot(key)) {
440
+ if (!expectedSnapshot) throw new Error(`Session not found: ${key}`);
441
+ if (!result.compacted || !result.handover || !result.audit) throw new Error("Cannot persist an incomplete compaction result");
442
+ const compacted = result.messages;
424
443
  return this.runStoreMutation(async () => {
425
- appendCompactionBoundary(key, {
444
+ if (!appendCompactionBoundaryIfUnchanged(key, expectedSnapshot, {
426
445
  type: "compaction",
427
446
  at: (/* @__PURE__ */ new Date()).toISOString(),
428
- plannerVersion: result.plannerVersion ?? 2,
447
+ plannerVersion: 3,
429
448
  summaryModelRef: result.summaryModelRef ?? "unknown",
430
449
  qualityAudit: result.qualityAudit ?? "disabled",
450
+ handover: result.handover,
451
+ audit: result.audit,
431
452
  summary: result.summary,
432
453
  messages: compacted,
433
454
  firstKeptIndex: result.firstKeptIndex,
434
455
  tokensBefore: result.tokensBefore,
435
456
  tokensAfter: result.tokensAfter
436
- });
457
+ })) throw new Error(`Session changed while compaction was running: ${key}`);
437
458
  log.info({
438
459
  key,
439
460
  tokensBefore: result.tokensBefore,
@@ -445,23 +466,27 @@ var SessionStore = class {
445
466
  });
446
467
  }
447
468
  async compact(key, messages, model, instructions, force, executionOptions) {
448
- const tokenCount = this.estimateTokens(messages);
449
- await this.runCompactionHook("before", {
450
- sessionKey: key,
451
- messageCount: messages.length,
452
- tokenCount
453
- });
454
- const result = await this.compactor.compact(messages, model, instructions, force, executionOptions);
455
- if (result.compacted) {
456
- const compacted = await this.applyCompaction(key, messages, result);
457
- await this.runCompactionHook("after", {
469
+ return this.runCompactionExclusive(key, async () => {
470
+ const snapshot = loadCompactionSourceSnapshot(key);
471
+ if (!snapshot) throw new Error(`Session not found: ${key}`);
472
+ const tokenCount = this.estimateTokens(messages);
473
+ await this.runCompactionHook("before", {
458
474
  sessionKey: key,
459
- messageCount: compacted.length,
460
- tokenCount: result.tokensAfter,
461
- compactedCount: Math.max(0, Math.min(messages.length, result.firstKeptIndex))
475
+ messageCount: messages.length,
476
+ tokenCount
462
477
  });
463
- }
464
- return result;
478
+ const result = await this.compactor.compact(snapshot.entries, model, instructions, force, executionOptions);
479
+ if (result.compacted) {
480
+ const compacted = await this.applyCompaction(key, result, snapshot);
481
+ await this.runCompactionHook("after", {
482
+ sessionKey: key,
483
+ messageCount: compacted.length,
484
+ tokenCount: result.tokensAfter,
485
+ compactedCount: Math.max(0, Math.min(messages.length, result.firstKeptIndex))
486
+ });
487
+ }
488
+ return result;
489
+ });
465
490
  }
466
491
  async getCompactionStats(key) {
467
492
  if (!await this.getMetadata(key)) return void 0;
@@ -470,6 +495,9 @@ var SessionStore = class {
470
495
  compactionCount: boundaries.length,
471
496
  totalTokensBefore: boundaries.reduce((sum, boundary) => sum + boundary.tokensBefore, 0),
472
497
  totalTokensAfter: boundaries.reduce((sum, boundary) => sum + boundary.tokensAfter, 0),
498
+ auditPassedCount: boundaries.filter((boundary) => boundary.audit.status === "passed").length,
499
+ auditDegradedCount: boundaries.filter((boundary) => boundary.audit.status === "degraded").length,
500
+ auditMissingItemsFound: boundaries.reduce((sum, boundary) => sum + boundary.audit.missingItemsFound, 0),
473
501
  lastCompactionAt: boundaries[0]?.createdAt
474
502
  };
475
503
  }
@@ -498,6 +526,10 @@ var SessionStore = class {
498
526
  const q = keyword.toLowerCase();
499
527
  return this.convertMessages(messages.filter((m) => this.extractTextContent(this.messageContent(m)).toLowerCase().includes(q)));
500
528
  }
529
+ recallSession(key, query, options) {
530
+ requireXopcDatabase();
531
+ return searchSessionTranscript(key, query, options);
532
+ }
501
533
  async exportSession(key, format) {
502
534
  const metadata = await this.getMetadata(key);
503
535
  if (!metadata) throw new Error(`Session not found: ${key}`);
@@ -1,3 +1,4 @@
1
+ import type { CompactionAudit } from './compaction-types.js';
1
2
  import type { TranscriptStoredRow } from './session-context-for-llm.js';
2
3
  export interface Message {
3
4
  role: 'system' | 'user' | 'assistant' | 'tool' | 'toolResult';
@@ -174,7 +175,7 @@ export interface SessionExport {
174
175
  /** Full on-disk rows (LLM + `kind: 'context'`) for audit / round-trip. */
175
176
  transcriptRows: TranscriptStoredRow[];
176
177
  }
177
- /** Append-only context boundary produced by compaction or logical restoration. */
178
+ /** Append-only context boundary produced by compaction. */
178
179
  export interface CompactionBoundarySummary {
179
180
  id: string;
180
181
  seq: number;
@@ -183,5 +184,5 @@ export interface CompactionBoundarySummary {
183
184
  tokensBefore: number;
184
185
  tokensAfter: number;
185
186
  summaryPreview: string;
186
- restoredFromCompactionId?: string;
187
+ audit: CompactionAudit;
187
188
  }
@@ -20,7 +20,7 @@ export { buildRelationshipPrompt, getRelationshipSettings, isProactiveSupportAll
20
20
  export { buildDefaultSessionMetadata, type SessionMetadataSeed, } from './session-metadata.js';
21
21
  export { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow, type SessionConfigRow, type SessionRow, type TranscriptEntryRow, } from './row-mappers.js';
22
22
  export { deleteSessionRecord, ensureSessionRecord, getCurrentSessionId, getGlobalSessionStats, findSessionKeyBySessionId, getSessionPersistedLevels, getSessionMetadata, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord, resolveSessionAgentId, updateSessionStats, } from './session-repository.js';
23
- export { appendCompactionBoundary, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, } from './transcript-repository.js';
23
+ export { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, loadCompactionSourceSnapshot, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript, type CompactionSourceSnapshot, type SessionTranscriptRecallMatch, type TranscriptSourceEntry, } from './transcript-repository.js';
24
24
  export { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord, } from './notes-repository.js';
25
25
  export { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgentContextRecord, type NoteAgentContextRecord, } from './note-agent-context-repository.js';
26
26
  export { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryTurnFeedback, getMemoryRecord, hasUnresolvedMemoryConflict, listMemorySignals, listMemoryTraceEvents, listMemoryRecords, markMemoryRecordsConflicted, searchMemoryRecords, setMemoryRecordStatus, setMemoryProviderState, setMemoryTurnFeedback, summarizeMemoryRecallFeedback, upsertMemoryRecord, type AppendMemorySignalInput, type AppendMemoryTraceEventInput, type ListMemoryRecordsOptions, type MemoryRecallFeedbackSummary, type MemorySignalRowPayload, type MemoryFeedback, type MemoryFeedbackRating, type MemoryTraceEventPayload, type SearchMemoryRecordsOptions, type SetMemoryTurnFeedbackInput, type UpsertMemoryRecordInput, } from './memory-records-repository.js';
@@ -21,7 +21,7 @@ import { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages,
21
21
  import { deleteSessionRecord, ensureSessionRecord, findSessionKeyBySessionId, getCurrentSessionId, getGlobalSessionStats, getSessionMetadata, getSessionPersistedLevels, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord, resolveSessionAgentId, updateSessionStats } from "./session-repository.js";
22
22
  import { getSessionTaskPlan, setSessionTaskPlan } from "./session-task-plan-repository.js";
23
23
  import { buildRelationshipPrompt, getRelationshipSettings, isProactiveSupportAllowed, updateRelationshipSettings } from "./relationship-settings-repository.js";
24
- import { appendCompactionBoundary, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary } from "./transcript-repository.js";
24
+ import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "./transcript-repository.js";
25
25
  import { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord } from "./notes-repository.js";
26
26
  import { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgentContextRecord } from "./note-agent-context-repository.js";
27
27
  import { attachMemoryEvidence, claimKnowledgeSourceItems, completeKnowledgeSourceItemSynthesis, deleteMemoryEvidenceForRecord, finishKnowledgeSyncRun, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listMemoryEvidence, pruneBoundedKnowledgeSourceItems, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, startKnowledgeSyncRun, upsertKnowledgeSourceItems } from "./knowledge-repository.js";
@@ -32,4 +32,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
32
32
  import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
33
33
  import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
34
34
  import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
35
- 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, appendCompactionBoundary, appendComposerInputHistory, appendConnectorExecutionAudit, appendMemorySignal, appendMemoryTraceEvent, appendTranscriptEntry, applyPendingMigrations, attachMemoryEvidence, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeConnectorApproval, consumeContextConsent, createCollaborationRule, createConnectorApproval, createContextEvidence, createEndpointPrincipal, createObjectLinkRecord, createUnderstanding, decideConnectorApproval, decideContextConsent, deleteCollaborationRule, deleteConnectorConnection, deleteConnectorInstallation, deleteMemoryEvidenceForRecord, deleteMemoryRecord, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, deleteUnderstanding, discoverSqlMigrations, enqueueConnectorLearningJob, ensureContextConsent, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextConsolidationRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActivityEventRecord, getCachedConnectorCatalogEntry, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextConsolidationRun, getCurrentSessionId, getEndpointPrincipal, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getMemoryProviderState, getMemoryRecord, getMemoryTurnFeedback, getNoteAgentContextRecord, getNoteRecord, getRelationshipSettings, getSessionConfig, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getTurnPersonalization, getUnderstanding, getUserProfile, getUserTrustPolicy, getXopcDatabase, hasContextConsent, hasSessionConfig, hasUnresolvedMemoryConflict, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isUnderstandingSuppressed, isXopcDatabaseOpen, linkUnderstandingEvidence, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextConsolidationDecisions, listContextConsolidationRuns, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listMemoryEvidence, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listUnderstandingEvidence, listUnderstandings, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, markMemoryRecordsConflicted, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recordContextConsolidationDecision, recordContextFeedback, recordContextRun, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, rejectUnderstanding, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceTranscriptRows, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, reviseCollaborationRule, reviseUnderstanding, revokeEndpointPrincipal, runSqliteWriteTransaction, searchMemoryRecords, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setMemoryProviderState, setMemoryRecordStatus, setMemoryTurnFeedback, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUnderstandingStatus, setUserTrustPolicy, startContextConsolidationRun, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeMemoryRecallFeedback, summarizeUserUnderstandingQuality, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserProfile, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertMemoryRecord, upsertNoteAgentContextRecord, upsertNoteRecord };
35
+ 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, appendMemorySignal, appendMemoryTraceEvent, appendTranscriptEntry, applyPendingMigrations, attachMemoryEvidence, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeConnectorApproval, consumeContextConsent, createCollaborationRule, createConnectorApproval, createContextEvidence, createEndpointPrincipal, createObjectLinkRecord, createUnderstanding, decideConnectorApproval, decideContextConsent, deleteCollaborationRule, deleteConnectorConnection, deleteConnectorInstallation, deleteMemoryEvidenceForRecord, deleteMemoryRecord, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, deleteUnderstanding, discoverSqlMigrations, enqueueConnectorLearningJob, ensureContextConsent, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextConsolidationRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActivityEventRecord, getCachedConnectorCatalogEntry, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextConsolidationRun, getCurrentSessionId, getEndpointPrincipal, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getMemoryProviderState, getMemoryRecord, getMemoryTurnFeedback, getNoteAgentContextRecord, getNoteRecord, getRelationshipSettings, getSessionConfig, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getTurnPersonalization, getUnderstanding, getUserProfile, getUserTrustPolicy, getXopcDatabase, hasContextConsent, hasSessionConfig, hasUnresolvedMemoryConflict, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isUnderstandingSuppressed, isXopcDatabaseOpen, linkUnderstandingEvidence, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextConsolidationDecisions, listContextConsolidationRuns, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listMemoryEvidence, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listUnderstandingEvidence, listUnderstandings, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, markMemoryRecordsConflicted, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recordContextConsolidationDecision, recordContextFeedback, recordContextRun, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, rejectUnderstanding, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceTranscriptRows, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, reviseCollaborationRule, reviseUnderstanding, revokeEndpointPrincipal, runSqliteWriteTransaction, searchMemoryRecords, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setMemoryProviderState, setMemoryRecordStatus, setMemoryTurnFeedback, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUnderstandingStatus, setUserTrustPolicy, startContextConsolidationRun, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeMemoryRecallFeedback, summarizeUserUnderstandingQuality, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserProfile, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertMemoryRecord, upsertNoteAgentContextRecord, upsertNoteRecord };