@xopcai/xopc 0.0.170 → 0.0.171

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 (185) 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-CkUp1qvf.js → activity-store-BLz30jWq.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DDuem4HM.js → agent-avatar-dicebear-BKZO0EFn.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-ZCIC8mhO.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-BnuPQhJW.js → api-N2qKY-WI.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-DdZw8Hi1.js → app-management-settings-panel-CNZkpXCD.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BN8Vk2bX.js → appearance-settings-Drf5a563.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-CuL8Q4yF.js → apps-page-DJmgBaAm.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-C82MaDQj.js → archive-plugin-ChVwOXE5.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-uilrwSdW.js → attachment-load-BVK3Y2d9.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-CkDZjAmy.js → automation-suggestion-card-DH4N0SYR.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-Ddot8-Md.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-B7NTL0_T.js → binary-plugins-CeHY6VVP.js} +1 -1
  15. package/dist/gateway/static/root/assets/block-editor-D3GIllO3.js +184 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-DvETvRcg.js +8 -0
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-UFVUzn4v.js → browser-workflow-inputs-femCtfpo.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-CGgC0N92.js → browser-workflows-page-o0GVE_aF.js} +2 -2
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-ChXIYbys.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-DUIorGUd.js → capability-presets-api-Bx-JJC0R.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUekXsJy.js +1 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-BYwSB8c6.js → channel-recipient-api-CTw3ibx4.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-CkhveNsQ.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-DRTb8DBk.js +1 -0
  25. package/dist/gateway/static/root/assets/{connector-logo-CsbegNqi.js → connector-logo-CQznQcd4.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-DkSGIxWP.js +2 -0
  27. package/dist/gateway/static/root/assets/desktop-pet-BtP-xUQ9.js +1 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-settings-DkbIzdA3.js → desktop-pet-settings-CIeH4VyP.js} +1 -1
  29. package/dist/gateway/static/root/assets/{directory-picker-path-field-dBQvj1sG.js → directory-picker-path-field-Ddgt6c3K.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dreaming-settings-DkdnKMZx.js → dreaming-settings-gd9W6SLj.js} +3 -3
  31. package/dist/gateway/static/root/assets/{extension-debug-page-BfxoIiNo.js → extension-debug-page-CJGwUaQX.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-EIJ3wIb7.js → extension-page-B3zHKJAB.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-settings-page-DBBec51N.js → extension-settings-page-Cj9rrSr1.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-4_u53Ufq.js → gateway-config-api-BdmtlJRP.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-settings-v9kJM59H.js → gateway-settings-C2RwKIsl.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-CXITih5d.js → gateway-startup-retry-mcMq_uu_.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-5Ryd_rx4.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-DizZ6Cpl.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-D54YQPon.js → goals-config-api-CAO1J4jn.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-Dqry_hi2.js +2 -0
  41. package/dist/gateway/static/root/assets/{goals-settings-DDezXaVi.js → goals-settings-Boj2izKZ.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-CRsIUeZN.js → heartbeat-settings-DbPC9a_y.js} +1 -1
  43. package/dist/gateway/static/root/assets/{image-generation-api-CY6cQUHL.js → image-generation-api-DrLCLTXn.js} +1 -1
  44. package/dist/gateway/static/root/assets/index-DEdyUjxM.css +1 -0
  45. package/dist/gateway/static/root/assets/{index-Dfq2laZe.js → index-vHb2z7VS.js} +7 -7
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D9k7EDdY.js → keyboard-shortcuts-settings-BrxfptgY.js} +1 -1
  47. package/dist/gateway/static/root/assets/local-app-workbench-page-BP0_Ih0e.js +2 -0
  48. package/dist/gateway/static/root/assets/{local-apps-page-DbaiBolh.js → local-apps-page-DNCRlfFs.js} +1 -1
  49. package/dist/gateway/static/root/assets/{locale-store-Dqp9H2Uf.js → locale-store-CzIfXqm8.js} +1 -1
  50. package/dist/gateway/static/root/assets/logs-page-mT48mcF4.js +7 -0
  51. package/dist/gateway/static/root/assets/{markdown-split-BGlQR-Be.js → markdown-split-CIUH9Lor.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-BpaeV6f_.js → media-plugins-DX4AgkCs.js} +1 -1
  53. package/dist/gateway/static/root/assets/messages-CKZuaOeG.js +3 -0
  54. package/dist/gateway/static/root/assets/{notes-page-Cd2HpciM.js → notes-page-D1KprtxL.js} +1 -1
  55. package/dist/gateway/static/root/assets/notes-workbench-wgt2Osyk.js +4 -0
  56. package/dist/gateway/static/root/assets/{page-tabs-DyimBUp_.js → page-tabs-DjZPJGf6.js} +1 -1
  57. package/dist/gateway/static/root/assets/{preview-open-alternatives-BKZulEYr.js → preview-open-alternatives-DNiJTpwZ.js} +1 -1
  58. package/dist/gateway/static/root/assets/{product-open-page-Bjz9BxBY.js → product-open-page-CNfR17-g.js} +1 -1
  59. package/dist/gateway/static/root/assets/project-detail-page-CDjHvxJm.js +1 -0
  60. package/dist/gateway/static/root/assets/projects-page-kJZwQXfC.js +1 -0
  61. package/dist/gateway/static/root/assets/remote-access-hub-MJdI9ek_.js +1 -0
  62. package/dist/gateway/static/root/assets/{save-bar-controls-BPTqb2_r.js → save-bar-controls-BGZFVO9S.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schedule-field-YN0D81Dk.js → schedule-field-BAZiHtds.js} +1 -1
  64. package/dist/gateway/static/root/assets/{schema-form-BmY5PSS2.js → schema-form-CesBcwJH.js} +1 -1
  65. package/dist/gateway/static/root/assets/sessions-page-BqC7GDC_.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-CYwz8MfF.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-form-section-B-RhgD_p.js → settings-form-section-Bxc54BLj.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DkPupX2B.js → settings-loading-skeleton-CYrho7Db.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-page-2QBMvaxj.js → settings-page-C03X5fkh.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-layout-CtrW-LD6.js → settings-page-layout-CZAJbv4E.js} +1 -1
  71. package/dist/gateway/static/root/assets/setup-status-panel-Jv8_bcOD.js +1 -0
  72. package/dist/gateway/static/root/assets/{share-preview-page-BezIW1n9.js → share-preview-page-DSC7tKKG.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-h8tGDkA3.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-D2DGvRUn.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-vqhjSMhZ.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-WAFhKyAu.js → system-settings-panel-BO89zw5H.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-BiC0gIBa.js → theme-store-1OkdVC8l.js} +1 -1
  78. package/dist/gateway/static/root/assets/time-picker-mtD64kFB.js +1 -0
  79. package/dist/gateway/static/root/assets/{typed-models-lib-WAQO3F_8.js → typed-models-lib-D-_vct_y.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-channel-catalog-CKlfsSeU.js → use-channel-catalog-VlFtjlET.js} +1 -1
  81. package/dist/gateway/static/root/assets/user-context-page-BgF0WxjM.js +1 -0
  82. package/dist/gateway/static/root/assets/{voice-api-key-field-BAFHF0_v.js → voice-api-key-field-BhDk-UV_.js} +1 -1
  83. package/dist/gateway/static/root/assets/work-discovery-page-CP0Daig-.js +1 -0
  84. package/dist/gateway/static/root/assets/work-item-detail-page-NEWZPKB_.js +1 -0
  85. package/dist/gateway/static/root/assets/work-page-BkWntcQh.js +1 -0
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-1OP4HyvS.js → workflow-run-setup-panel-uVw4Yoej.js} +2 -2
  87. package/dist/gateway/static/root/assets/workflows-page-DRvhNQGe.js +11 -0
  88. package/dist/gateway/static/root/index.html +7 -7
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/embedded/run-for-session.js +71 -24
  91. package/dist/src/agent/embedded/run-turn.js +68 -4
  92. package/dist/src/agent/inbound/inbound-loop.d.ts +0 -2
  93. package/dist/src/agent/inbound/inbound-loop.js +0 -2
  94. package/dist/src/agent/memory/compaction-planner.d.ts +16 -0
  95. package/dist/src/agent/memory/compaction-planner.js +152 -0
  96. package/dist/src/agent/memory/compaction-policy.d.ts +10 -0
  97. package/dist/src/agent/memory/compaction-policy.js +24 -0
  98. package/dist/src/agent/memory/compaction.d.ts +21 -22
  99. package/dist/src/agent/memory/compaction.js +220 -194
  100. package/dist/src/agent/memory/context-budget.d.ts +40 -0
  101. package/dist/src/agent/memory/context-budget.js +106 -0
  102. package/dist/src/agent/orchestration/context-overflow.d.ts +1 -0
  103. package/dist/src/agent/orchestration/context-overflow.js +19 -0
  104. package/dist/src/agent/orchestration/loop-guard.js +13 -9
  105. package/dist/src/agent/reply/post-compaction-context.d.ts +4 -0
  106. package/dist/src/agent/reply/post-compaction-context.js +5 -3
  107. package/dist/src/agent/service/process-direct-one-shot.js +1 -2
  108. package/dist/src/agent/service/process-direct-streaming.js +1 -2
  109. package/dist/src/agent/service.d.ts +0 -2
  110. package/dist/src/agent/service.js +13 -44
  111. package/dist/src/agent/session/session-inspector.js +10 -2
  112. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  113. package/dist/src/config/schema.d.ts +17 -1
  114. package/dist/src/gateway/hono/lib/config-payload.d.ts +23 -0
  115. package/dist/src/gateway/hono/lib/config-payload.js +3 -0
  116. package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
  117. package/dist/src/gateway/hono/routes/config-patch/misc.js +28 -0
  118. package/dist/src/gateway/hono/routes/sessions.js +17 -42
  119. package/dist/src/gateway/service/sessions-api.d.ts +2 -3
  120. package/dist/src/gateway/service/sessions-api.js +4 -7
  121. package/dist/src/session/index.d.ts +1 -2
  122. package/dist/src/session/index.js +1 -2
  123. package/dist/src/session/init-session-turn.d.ts +0 -1
  124. package/dist/src/session/init-session-turn.js +1 -2
  125. package/dist/src/session/manager.d.ts +11 -17
  126. package/dist/src/session/manager.js +11 -14
  127. package/dist/src/session/session-context-for-llm.d.ts +19 -1
  128. package/dist/src/session/session-context-for-llm.js +87 -129
  129. package/dist/src/session/store.d.ts +28 -23
  130. package/dist/src/session/store.js +94 -83
  131. package/dist/src/session/transcript-format.d.ts +2 -8
  132. package/dist/src/session/types.d.ts +8 -6
  133. package/dist/src/session/user-round-delete.d.ts +3 -6
  134. package/dist/src/session/user-round-delete.js +12 -16
  135. package/dist/src/storage/sqlite/index.d.ts +1 -1
  136. package/dist/src/storage/sqlite/index.js +2 -2
  137. package/dist/src/storage/sqlite/migrations/060_remove_runtime_transcript_messages.sql +45 -0
  138. package/dist/src/storage/sqlite/migrations/061_drop_compaction_checkpoints.sql +2 -0
  139. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  140. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  141. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  142. package/dist/src/storage/sqlite/schema.js +1 -1
  143. package/dist/src/storage/sqlite/schema.sql +0 -19
  144. package/dist/src/storage/sqlite/transcript-repository.d.ts +6 -11
  145. package/dist/src/storage/sqlite/transcript-repository.js +90 -84
  146. package/dist/src/user-context/config.d.ts +67 -2
  147. package/dist/src/user-context/config.js +36 -3
  148. package/package.json +1 -1
  149. package/dist/gateway/static/root/assets/agents-BiaQhiQp.js +0 -2
  150. package/dist/gateway/static/root/assets/automations-page-TZOluRNp.js +0 -6
  151. package/dist/gateway/static/root/assets/block-editor-D_LDNlB-.js +0 -184
  152. package/dist/gateway/static/root/assets/browser-settings-page-C-l6O68Z.js +0 -8
  153. package/dist/gateway/static/root/assets/capabilities-settings-panel-BW8c0xPp.js +0 -7
  154. package/dist/gateway/static/root/assets/capability-presets-settings-panel-PTz00nR4.js +0 -1
  155. package/dist/gateway/static/root/assets/channels-settings-h9CsE0GT.js +0 -1
  156. package/dist/gateway/static/root/assets/channels-status-swr-C058Mcfr.js +0 -1
  157. package/dist/gateway/static/root/assets/connectors-page-BWALafGW.js +0 -2
  158. package/dist/gateway/static/root/assets/desktop-pet-CkT98fPT.js +0 -1
  159. package/dist/gateway/static/root/assets/goal-create-dialog-y2Y3p7_k.js +0 -1
  160. package/dist/gateway/static/root/assets/goal-detail-page-DuzL-alv.js +0 -4
  161. package/dist/gateway/static/root/assets/goals-page-OeLtfKI2.js +0 -2
  162. package/dist/gateway/static/root/assets/index-o4uaOGKT.css +0 -1
  163. package/dist/gateway/static/root/assets/local-app-workbench-page-3ssYIEK6.js +0 -2
  164. package/dist/gateway/static/root/assets/logs-page-DoCY0Mm9.js +0 -7
  165. package/dist/gateway/static/root/assets/messages-KEk-hTFt.js +0 -3
  166. package/dist/gateway/static/root/assets/notes-workbench-CatZNAPc.js +0 -4
  167. package/dist/gateway/static/root/assets/project-detail-page-DJUOgqm4.js +0 -1
  168. package/dist/gateway/static/root/assets/projects-page-BQQAD_nu.js +0 -1
  169. package/dist/gateway/static/root/assets/remote-access-hub-fIGXTTnA.js +0 -1
  170. package/dist/gateway/static/root/assets/sessions-page-BuU-8FCe.js +0 -1
  171. package/dist/gateway/static/root/assets/settings-advanced-gate-DlKoeZm3.js +0 -1
  172. package/dist/gateway/static/root/assets/setup-status-panel-BSUcDFnb.js +0 -1
  173. package/dist/gateway/static/root/assets/shares-settings-Bk2-SwGJ.js +0 -1
  174. package/dist/gateway/static/root/assets/skill-reload-api-e_Fx1kVC.js +0 -1
  175. package/dist/gateway/static/root/assets/skills-page-D_cCADfj.js +0 -2
  176. package/dist/gateway/static/root/assets/time-picker-fqRXpNJV.js +0 -1
  177. package/dist/gateway/static/root/assets/user-context-page-9Ov4htPW.js +0 -1
  178. package/dist/gateway/static/root/assets/work-discovery-page-DGN2FxWv.js +0 -1
  179. package/dist/gateway/static/root/assets/work-item-detail-page-HmyWSgUo.js +0 -1
  180. package/dist/gateway/static/root/assets/work-page-D3iKVjFq.js +0 -1
  181. package/dist/gateway/static/root/assets/workflows-page-B5L4SFw4.js +0 -11
  182. package/dist/src/agent/lifecycle/handlers/compaction.d.ts +0 -13
  183. package/dist/src/agent/lifecycle/handlers/compaction.js +0 -18
  184. package/dist/src/session/compaction-checkpoints.d.ts +0 -8
  185. package/dist/src/session/compaction-checkpoints.js +0 -19
@@ -1,10 +1,9 @@
1
1
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
- import { buildSessionContextForLlm } from "../../session/session-context-for-llm.js";
2
+ import { buildSessionContextForLlm, isRuntimeOnlyTranscriptMessage } from "../../session/session-context-for-llm.js";
3
3
  import { classifyStoredRow, estimateTokensFromMessages, extractFtsContent, transcriptEntryRowToStoredRow } from "./row-mappers.js";
4
4
  import { getCurrentSessionId, readCurrentSessionId } from "./session-repository.js";
5
5
  import { randomUUID } from "node:crypto";
6
6
  //#region src/storage/sqlite/transcript-repository.ts
7
- const MAX_CHECKPOINTS_PER_TRANSCRIPT = 15;
8
7
  function nextSeq(db, sessionId) {
9
8
  return (db.prepare(`SELECT COALESCE(MAX(seq), 0) AS max_seq FROM transcript_entries WHERE session_id = ?`).get(sessionId).max_seq ?? 0) + 1;
10
9
  }
@@ -34,6 +33,7 @@ function isUserMessageRow(row) {
34
33
  return classified.entryKind === "message" && classified.role === "user";
35
34
  }
36
35
  function appendTranscriptEntry(sessionKey, row, opts) {
36
+ if (isRuntimeOnlyTranscriptMessage(row)) throw new Error("Runtime-only messages cannot be persisted in a session transcript");
37
37
  return runSqliteWriteTransaction((db) => {
38
38
  const sessionId = opts?.sessionId ?? readCurrentSessionId(db, sessionKey);
39
39
  if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
@@ -58,6 +58,31 @@ function appendTranscriptEntry(sessionKey, row, opts) {
58
58
  return inserted;
59
59
  });
60
60
  }
61
+ function appendCompactionBoundary(sessionKey, row) {
62
+ return runSqliteWriteTransaction((db) => {
63
+ const sessionId = readCurrentSessionId(db, sessionKey);
64
+ if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
65
+ const boundary = {
66
+ ...row,
67
+ baseSeq: nextSeq(db, sessionId) - 1
68
+ };
69
+ const inserted = insertEntry(db, {
70
+ sessionId,
71
+ sessionKey,
72
+ row: boundary
73
+ });
74
+ const now = Date.now();
75
+ db.prepare(`UPDATE sessions SET
76
+ message_count = ?,
77
+ estimated_tokens = ?,
78
+ compacted_count = compacted_count + 1,
79
+ updated_at = ?,
80
+ last_accessed_at = ?,
81
+ last_interaction_at = ?
82
+ WHERE session_key = ?`).run(boundary.messages.length, boundary.tokensAfter, now, now, now, sessionKey);
83
+ return inserted;
84
+ });
85
+ }
61
86
  function loadTranscriptRowsForSession(sessionKey) {
62
87
  const sessionId = getCurrentSessionId(sessionKey);
63
88
  if (!sessionId) return [];
@@ -79,25 +104,30 @@ function loadTranscriptRows(sessionId) {
79
104
  ORDER BY seq ASC`).all(sessionId).map(transcriptEntryRowToStoredRow);
80
105
  }
81
106
  function loadLlmMessagesForSession(sessionKey) {
82
- return buildSessionContextForLlm(loadTranscriptRowsForSession(sessionKey));
107
+ const sessionId = getCurrentSessionId(sessionKey);
108
+ if (!sessionId) return [];
109
+ return buildSessionContextForLlm(getSqliteDatabase().prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
110
+ FROM transcript_entries
111
+ WHERE session_id = ?
112
+ AND seq >= COALESCE(
113
+ (SELECT MAX(seq) FROM transcript_entries WHERE session_id = ? AND entry_kind = 'compaction'),
114
+ 1
115
+ )
116
+ ORDER BY seq ASC`).all(sessionId, sessionId).map(transcriptEntryRowToStoredRow));
83
117
  }
84
- function replaceTranscriptRows(sessionKey, rows, opts) {
118
+ function replaceTranscriptRows(sessionKey, rows) {
119
+ if (rows.some(isRuntimeOnlyTranscriptMessage)) throw new Error("Runtime-only messages cannot be persisted in a session transcript");
85
120
  runSqliteWriteTransaction((db) => {
86
121
  const sessionId = readCurrentSessionId(db, sessionKey);
87
122
  if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
88
123
  db.prepare(`DELETE FROM transcript_fts WHERE session_id = ?`).run(sessionId);
89
124
  db.prepare(`DELETE FROM transcript_entries WHERE session_id = ?`).run(sessionId);
90
- const toWrite = [...rows];
91
- if (opts?.appendCompaction) toWrite.push({
92
- type: "compaction",
93
- ...opts.appendCompaction
94
- });
95
- for (const row of toWrite) insertEntry(db, {
125
+ for (const row of rows) insertEntry(db, {
96
126
  sessionId,
97
127
  sessionKey,
98
128
  row
99
129
  });
100
- const llm = buildSessionContextForLlm(toWrite);
130
+ const llm = buildSessionContextForLlm(rows);
101
131
  const now = Date.now();
102
132
  const hiddenUpdate = llm.some((message) => message.role === "user") ? `hidden_from_session_list = 0,` : "";
103
133
  db.prepare(`UPDATE sessions SET
@@ -110,14 +140,6 @@ function replaceTranscriptRows(sessionKey, rows, opts) {
110
140
  WHERE session_key = ?`).run(llm.length, estimateTokensFromMessages(llm), now, now, now, sessionKey);
111
141
  });
112
142
  }
113
- function loadCheckpointRows(sessionKey, checkpointId) {
114
- const db = getSqliteDatabase();
115
- if (!db.prepare(`SELECT checkpoint_id FROM compaction_checkpoints
116
- WHERE session_key = ? AND checkpoint_id = ?`).get(sessionKey, checkpointId)) return [];
117
- return db.prepare(`SELECT payload_json FROM checkpoint_entries
118
- WHERE checkpoint_id = ?
119
- ORDER BY seq ASC`).all(checkpointId).map((entry) => JSON.parse(entry.payload_json));
120
- }
121
143
  function paginateTranscriptMessages(sessionKey, options = {}) {
122
144
  const sessionId = getCurrentSessionId(sessionKey);
123
145
  if (!sessionId) return {
@@ -171,86 +193,70 @@ function paginateTranscriptMessages(sessionKey, options = {}) {
171
193
  endSeq: rows[rows.length - 1]?.seq ?? 0
172
194
  };
173
195
  }
174
- function captureCompactionCheckpoint(sessionKey) {
175
- return runSqliteWriteTransaction((db) => {
176
- const sessionId = readCurrentSessionId(db, sessionKey);
177
- if (!sessionId) return null;
178
- const entries = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
179
- FROM transcript_entries WHERE session_id = ? ORDER BY seq ASC`).all(sessionId);
180
- if (entries.length === 0) return null;
181
- const checkpointId = randomUUID();
182
- const now = Date.now();
183
- const messageCount = entries.filter((e) => e.entry_kind === "message").length;
184
- const sizeBytes = entries.reduce((sum, e) => sum + e.payload_json.length, 0);
185
- db.prepare(`INSERT INTO compaction_checkpoints
186
- (checkpoint_id, session_id, session_key, created_at, message_count, size_bytes)
187
- VALUES (?, ?, ?, ?, ?, ?)`).run(checkpointId, sessionId, sessionKey, now, messageCount, sizeBytes);
188
- const insertCheckpointEntry = db.prepare(`INSERT INTO checkpoint_entries (checkpoint_id, seq, entry_kind, role, payload_json)
189
- VALUES (?, ?, ?, ?, ?)`);
190
- for (const entry of entries) insertCheckpointEntry.run(checkpointId, entry.seq, entry.entry_kind, entry.role, entry.payload_json);
191
- pruneCompactionCheckpoints(db, sessionId);
192
- return checkpointId;
196
+ function listCompactionBoundaries(sessionKey) {
197
+ const db = getSqliteDatabase();
198
+ const sessionId = getCurrentSessionId(sessionKey);
199
+ if (!sessionId) return [];
200
+ return db.prepare(`SELECT entry_id, seq, payload_json, created_at
201
+ FROM transcript_entries
202
+ WHERE session_id = ? AND entry_kind = 'compaction'
203
+ ORDER BY seq DESC`).all(sessionId).map((row) => {
204
+ const payload = JSON.parse(row.payload_json);
205
+ return {
206
+ id: row.entry_id,
207
+ seq: row.seq,
208
+ createdAt: new Date(row.created_at).toISOString(),
209
+ messageCount: payload.messages.length,
210
+ tokensBefore: payload.tokensBefore,
211
+ tokensAfter: payload.tokensAfter,
212
+ summaryPreview: payload.summary.slice(0, 500),
213
+ restoredFromCompactionId: payload.restoredFromCompactionId
214
+ };
193
215
  });
194
216
  }
195
- function pruneCompactionCheckpoints(db, sessionId) {
196
- const rows = db.prepare(`SELECT checkpoint_id FROM compaction_checkpoints
197
- WHERE session_id = ?
198
- ORDER BY created_at ASC`).all(sessionId);
199
- if (rows.length <= MAX_CHECKPOINTS_PER_TRANSCRIPT) return;
200
- const toDelete = rows.slice(0, rows.length - MAX_CHECKPOINTS_PER_TRANSCRIPT);
201
- const del = db.prepare(`DELETE FROM compaction_checkpoints WHERE checkpoint_id = ?`);
202
- for (const row of toDelete) del.run(row.checkpoint_id);
203
- }
204
- function listCompactionCheckpoints(sessionKey) {
205
- return getSqliteDatabase().prepare(`SELECT checkpoint_id, created_at, message_count, size_bytes
206
- FROM compaction_checkpoints
207
- WHERE session_key = ?
208
- ORDER BY created_at DESC`).all(sessionKey).map((row) => ({
209
- id: row.checkpoint_id,
210
- sizeBytes: row.size_bytes,
211
- modifiedAt: new Date(row.created_at).toISOString()
212
- }));
213
- }
214
- function getCompactionCheckpointDetail(sessionKey, checkpointId) {
215
- const row = getSqliteDatabase().prepare(`SELECT checkpoint_id, created_at, message_count, size_bytes
216
- FROM compaction_checkpoints
217
- WHERE session_key = ? AND checkpoint_id = ?`).get(sessionKey, checkpointId);
218
- if (!row) return null;
219
- return {
220
- id: row.checkpoint_id,
221
- sizeBytes: row.size_bytes,
222
- modifiedAt: new Date(row.created_at).toISOString(),
223
- messageCount: row.message_count
224
- };
225
- }
226
- function restoreCompactionCheckpoint(sessionKey, checkpointId) {
217
+ function restoreBeforeCompactionBoundary(sessionKey, compactionId) {
227
218
  runSqliteWriteTransaction((db) => {
228
219
  const sessionId = readCurrentSessionId(db, sessionKey);
229
220
  if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
230
- if (!db.prepare(`SELECT checkpoint_id FROM compaction_checkpoints
231
- WHERE session_key = ? AND checkpoint_id = ?`).get(sessionKey, checkpointId)) throw new Error(`Checkpoint not found: ${checkpointId}`);
232
- const entries = db.prepare(`SELECT seq, entry_kind, role, payload_json
233
- FROM checkpoint_entries
234
- WHERE checkpoint_id = ?
235
- ORDER BY seq ASC`).all(checkpointId);
236
- db.prepare(`DELETE FROM transcript_fts WHERE session_id = ?`).run(sessionId);
237
- db.prepare(`DELETE FROM transcript_entries WHERE session_id = ?`).run(sessionId);
238
- for (const entry of entries) insertEntry(db, {
221
+ const boundary = db.prepare(`SELECT seq FROM transcript_entries
222
+ WHERE session_id = ? AND entry_id = ? AND entry_kind = 'compaction'`).get(sessionId, compactionId);
223
+ if (!boundary) throw new Error(`Compaction boundary not found: ${compactionId}`);
224
+ const restoredMessages = buildSessionContextForLlm(db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
225
+ FROM transcript_entries
226
+ WHERE session_id = ? AND seq < ?
227
+ ORDER BY seq ASC`).all(sessionId, boundary.seq).map(transcriptEntryRowToStoredRow));
228
+ if (restoredMessages.length === 0) throw new Error(`No restorable context exists before compaction boundary: ${compactionId}`);
229
+ const current = db.prepare(`SELECT estimated_tokens FROM sessions WHERE session_key = ?`).get(sessionKey);
230
+ const tokensAfter = estimateTokensFromMessages(restoredMessages);
231
+ const baseSeq = nextSeq(db, sessionId) - 1;
232
+ insertEntry(db, {
239
233
  sessionId,
240
234
  sessionKey,
241
- row: JSON.parse(entry.payload_json),
242
- createdAt: Date.now()
235
+ row: {
236
+ type: "compaction",
237
+ at: (/* @__PURE__ */ new Date()).toISOString(),
238
+ baseSeq,
239
+ plannerVersion: 2,
240
+ summaryModelRef: "logical-restore",
241
+ qualityAudit: "disabled",
242
+ summary: `Restored the effective context that existed before compaction boundary ${compactionId}.`,
243
+ messages: restoredMessages,
244
+ firstKeptIndex: 0,
245
+ tokensBefore: current.estimated_tokens,
246
+ tokensAfter,
247
+ restoredFromCompactionId: compactionId
248
+ }
243
249
  });
244
- const llm = buildSessionContextForLlm(entries.map((e) => JSON.parse(e.payload_json)));
245
250
  const now = Date.now();
246
251
  db.prepare(`UPDATE sessions SET
247
252
  message_count = ?,
248
253
  estimated_tokens = ?,
254
+ compacted_count = compacted_count + 1,
249
255
  updated_at = ?,
250
256
  last_accessed_at = ?,
251
257
  last_interaction_at = ?
252
- WHERE session_key = ?`).run(llm.length, estimateTokensFromMessages(llm), now, now, now, sessionKey);
258
+ WHERE session_key = ?`).run(restoredMessages.length, tokensAfter, now, now, now, sessionKey);
253
259
  });
254
260
  }
255
261
  //#endregion
256
- export { appendTranscriptEntry, captureCompactionCheckpoint, getCompactionCheckpointDetail, listCompactionCheckpoints, loadCheckpointRows, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreCompactionCheckpoint };
262
+ export { appendCompactionBoundary, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary };
@@ -5,6 +5,39 @@ export declare const UserMemoryModeSchema: z.ZodEnum<{
5
5
  readOnly: "readOnly";
6
6
  confirmWrite: "confirmWrite";
7
7
  }>;
8
+ export declare const DEFAULT_CONTEXT_COMPACTION_POLICY: {
9
+ enabled: boolean;
10
+ triggerThreshold: number;
11
+ reserveTokens: number;
12
+ minMessagesBeforeCompact: number;
13
+ keepRecentTokens: number;
14
+ recentTurnsPreserve: number;
15
+ summaryMaxTokens: number;
16
+ summaryChunkTokens: number;
17
+ summaryTimeoutMs: number;
18
+ summaryRetries: number;
19
+ qualityGuard: boolean;
20
+ minToolResultKeepChars: number;
21
+ maxActiveTranscriptBytes: number;
22
+ postCompactionSections: string[];
23
+ };
24
+ export declare const ContextCompactionPolicySchema: z.ZodDefault<z.ZodObject<{
25
+ enabled: z.ZodDefault<z.ZodBoolean>;
26
+ triggerThreshold: z.ZodDefault<z.ZodNumber>;
27
+ reserveTokens: z.ZodDefault<z.ZodNumber>;
28
+ minMessagesBeforeCompact: z.ZodDefault<z.ZodNumber>;
29
+ keepRecentTokens: z.ZodDefault<z.ZodNumber>;
30
+ recentTurnsPreserve: z.ZodDefault<z.ZodNumber>;
31
+ summaryMaxTokens: z.ZodDefault<z.ZodNumber>;
32
+ summaryChunkTokens: z.ZodDefault<z.ZodNumber>;
33
+ summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
34
+ summaryRetries: z.ZodDefault<z.ZodNumber>;
35
+ qualityGuard: z.ZodDefault<z.ZodBoolean>;
36
+ model: z.ZodOptional<z.ZodString>;
37
+ minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
38
+ maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
39
+ postCompactionSections: z.ZodDefault<z.ZodArray<z.ZodString>>;
40
+ }, z.core.$strict>>;
8
41
  export declare const UserMemoryConfigSchema: z.ZodDefault<z.ZodObject<{
9
42
  mode: z.ZodDefault<z.ZodEnum<{
10
43
  off: "off";
@@ -43,7 +76,23 @@ export declare const UserMemoryConfigSchema: z.ZodDefault<z.ZodObject<{
43
76
  }>>;
44
77
  }, z.core.$strict>>;
45
78
  retention: z.ZodOptional<z.ZodObject<{
46
- compaction: z.ZodDefault<z.ZodBoolean>;
79
+ compaction: z.ZodDefault<z.ZodObject<{
80
+ enabled: z.ZodDefault<z.ZodBoolean>;
81
+ triggerThreshold: z.ZodDefault<z.ZodNumber>;
82
+ reserveTokens: z.ZodDefault<z.ZodNumber>;
83
+ minMessagesBeforeCompact: z.ZodDefault<z.ZodNumber>;
84
+ keepRecentTokens: z.ZodDefault<z.ZodNumber>;
85
+ recentTurnsPreserve: z.ZodDefault<z.ZodNumber>;
86
+ summaryMaxTokens: z.ZodDefault<z.ZodNumber>;
87
+ summaryChunkTokens: z.ZodDefault<z.ZodNumber>;
88
+ summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
89
+ summaryRetries: z.ZodDefault<z.ZodNumber>;
90
+ qualityGuard: z.ZodDefault<z.ZodBoolean>;
91
+ model: z.ZodOptional<z.ZodString>;
92
+ minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
93
+ maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
94
+ postCompactionSections: z.ZodDefault<z.ZodArray<z.ZodString>>;
95
+ }, z.core.$strict>>;
47
96
  maxAgeDays: z.ZodOptional<z.ZodNumber>;
48
97
  maxItems: z.ZodOptional<z.ZodNumber>;
49
98
  maxChars: z.ZodOptional<z.ZodNumber>;
@@ -153,7 +202,23 @@ export declare const UserContextConfigSchema: z.ZodDefault<z.ZodObject<{
153
202
  }>>;
154
203
  }, z.core.$strict>>;
155
204
  retention: z.ZodOptional<z.ZodObject<{
156
- compaction: z.ZodDefault<z.ZodBoolean>;
205
+ compaction: z.ZodDefault<z.ZodObject<{
206
+ enabled: z.ZodDefault<z.ZodBoolean>;
207
+ triggerThreshold: z.ZodDefault<z.ZodNumber>;
208
+ reserveTokens: z.ZodDefault<z.ZodNumber>;
209
+ minMessagesBeforeCompact: z.ZodDefault<z.ZodNumber>;
210
+ keepRecentTokens: z.ZodDefault<z.ZodNumber>;
211
+ recentTurnsPreserve: z.ZodDefault<z.ZodNumber>;
212
+ summaryMaxTokens: z.ZodDefault<z.ZodNumber>;
213
+ summaryChunkTokens: z.ZodDefault<z.ZodNumber>;
214
+ summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
215
+ summaryRetries: z.ZodDefault<z.ZodNumber>;
216
+ qualityGuard: z.ZodDefault<z.ZodBoolean>;
217
+ model: z.ZodOptional<z.ZodString>;
218
+ minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
219
+ maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
220
+ postCompactionSections: z.ZodDefault<z.ZodArray<z.ZodString>>;
221
+ }, z.core.$strict>>;
157
222
  maxAgeDays: z.ZodOptional<z.ZodNumber>;
158
223
  maxItems: z.ZodOptional<z.ZodNumber>;
159
224
  maxChars: z.ZodOptional<z.ZodNumber>;
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { z } from "zod";
3
3
  //#region src/user-context/config.ts
4
- var UserMemoryModeSchema, UserMemoryConfigSchema, UserUnderstandingConfigSchema, UserContextPrivacySchema, UserContextProviderRoutingSchema, DreamingPhaseSchema, UserContextDreamingSchema, UserContextConfigSchema;
4
+ var UserMemoryModeSchema, DEFAULT_CONTEXT_COMPACTION_POLICY, ContextCompactionPolicySchema, UserMemoryConfigSchema, UserUnderstandingConfigSchema, UserContextPrivacySchema, UserContextProviderRoutingSchema, DreamingPhaseSchema, UserContextDreamingSchema, UserContextConfigSchema;
5
5
  var init_config = __esmMin((() => {
6
6
  UserMemoryModeSchema = z.enum([
7
7
  "off",
@@ -9,6 +9,39 @@ var init_config = __esmMin((() => {
9
9
  "confirmWrite",
10
10
  "auto"
11
11
  ]);
12
+ DEFAULT_CONTEXT_COMPACTION_POLICY = {
13
+ enabled: true,
14
+ triggerThreshold: .8,
15
+ reserveTokens: 8192,
16
+ minMessagesBeforeCompact: 10,
17
+ keepRecentTokens: 2e4,
18
+ recentTurnsPreserve: 3,
19
+ summaryMaxTokens: 2e3,
20
+ summaryChunkTokens: 24e3,
21
+ summaryTimeoutMs: 18e4,
22
+ summaryRetries: 2,
23
+ qualityGuard: true,
24
+ minToolResultKeepChars: 1e3,
25
+ maxActiveTranscriptBytes: 2e6,
26
+ postCompactionSections: ["Session Startup", "Red Lines"]
27
+ };
28
+ ContextCompactionPolicySchema = z.object({
29
+ enabled: z.boolean().default(true),
30
+ triggerThreshold: z.number().min(.1).max(.98).default(.8),
31
+ reserveTokens: z.number().int().min(1024).default(8192),
32
+ minMessagesBeforeCompact: z.number().int().min(2).default(10),
33
+ keepRecentTokens: z.number().int().min(1e3).default(2e4),
34
+ recentTurnsPreserve: z.number().int().min(1).max(12).default(3),
35
+ summaryMaxTokens: z.number().int().min(256).default(2e3),
36
+ summaryChunkTokens: z.number().int().min(1e3).default(24e3),
37
+ summaryTimeoutMs: z.number().int().min(1e3).max(6e5).default(18e4),
38
+ summaryRetries: z.number().int().min(0).max(5).default(2),
39
+ qualityGuard: z.boolean().default(true),
40
+ model: z.string().min(1).optional(),
41
+ minToolResultKeepChars: z.number().int().min(200).default(1e3),
42
+ maxActiveTranscriptBytes: z.number().int().min(64e3).default(2e6),
43
+ postCompactionSections: z.array(z.string().min(1)).max(12).default(["Session Startup", "Red Lines"])
44
+ }).strict().default(DEFAULT_CONTEXT_COMPACTION_POLICY);
12
45
  UserMemoryConfigSchema = z.object({
13
46
  mode: UserMemoryModeSchema.default("off"),
14
47
  sources: z.array(z.enum([
@@ -42,7 +75,7 @@ var init_config = __esmMin((() => {
42
75
  ]).optional()
43
76
  }).strict().optional(),
44
77
  retention: z.object({
45
- compaction: z.boolean().default(true),
78
+ compaction: ContextCompactionPolicySchema,
46
79
  maxAgeDays: z.number().int().positive().optional(),
47
80
  maxItems: z.number().int().positive().optional(),
48
81
  maxChars: z.number().int().positive().optional()
@@ -153,4 +186,4 @@ var init_config = __esmMin((() => {
153
186
  }));
154
187
  //#endregion
155
188
  init_config();
156
- export { UserContextConfigSchema, UserContextDreamingSchema, UserContextPrivacySchema, UserContextProviderRoutingSchema, UserMemoryConfigSchema, UserMemoryModeSchema, UserUnderstandingConfigSchema, init_config };
189
+ export { ContextCompactionPolicySchema, DEFAULT_CONTEXT_COMPACTION_POLICY, UserContextConfigSchema, UserContextDreamingSchema, UserContextPrivacySchema, UserContextProviderRoutingSchema, UserMemoryConfigSchema, UserMemoryModeSchema, UserUnderstandingConfigSchema, init_config };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.170",
3
+ "version": "0.0.171",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",