@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
@@ -11,12 +11,16 @@ const DEFAULT_CONFIG = {
11
11
  * Stable fingerprint for tool call comparison.
12
12
  * Recursively sorts object keys; truncates long string values.
13
13
  */
14
- function fingerprint(toolName, params) {
15
- return `${toolName}::${JSON.stringify(params, (_key, value) => {
16
- if (typeof value === "object" && value !== null && !Array.isArray(value)) return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));
17
- if (typeof value === "string" && value.length > 200) return `${value.slice(0, 80)}…[${value.length}]`;
18
- return value;
19
- })}`;
14
+ function stableJson(value) {
15
+ return JSON.stringify(value, (_key, item) => {
16
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) return Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)));
17
+ if (typeof item === "string" && item.length > 200) return `${item.slice(0, 80)}…[${item.length}]`;
18
+ return item;
19
+ });
20
+ }
21
+ function fingerprint(call) {
22
+ const result = call.resultPreview === void 0 ? "" : `::result=${stableJson(call.resultPreview)}`;
23
+ return `${call.name}::${stableJson(call.params)}${result}`;
20
24
  }
21
25
  /**
22
26
  * Analyze recent tool calls and produce loop guard result.
@@ -70,11 +74,11 @@ function findConsecutiveRepeats(calls) {
70
74
  let index = calls.length - 1;
71
75
  while (index >= 0) {
72
76
  const current = calls[index];
73
- const fp = fingerprint(current.name, current.params);
77
+ const fp = fingerprint(current);
74
78
  let count = 1;
75
79
  while (index - count >= 0) {
76
80
  const prev = calls[index - count];
77
- if (fingerprint(prev.name, prev.params) !== fp) break;
81
+ if (fingerprint(prev) !== fp) break;
78
82
  count++;
79
83
  }
80
84
  if (count >= 2) groups.push({
@@ -92,7 +96,7 @@ function findConsecutiveRepeats(calls) {
92
96
  function countFrequency(calls) {
93
97
  const map = /* @__PURE__ */ new Map();
94
98
  for (const call of calls) {
95
- const fp = fingerprint(call.name, call.params);
99
+ const fp = fingerprint(call);
96
100
  map.set(fp, (map.get(fp) ?? 0) + 1);
97
101
  }
98
102
  return map;
@@ -5,6 +5,8 @@ export type PostCompactionContextOptions = {
5
5
  agentId?: string;
6
6
  nowMs?: number;
7
7
  userTimezone?: string;
8
+ sectionNames?: string[];
9
+ maxContextChars?: number;
8
10
  };
9
11
  export declare function readPostCompactionContextFromAgentsMd(agentsMdContent: string, options?: PostCompactionContextOptions): string | null;
10
12
  export declare function readPostCompactionContext(params: {
@@ -13,4 +15,6 @@ export declare function readPostCompactionContext(params: {
13
15
  agentId?: string;
14
16
  nowMs?: number;
15
17
  userTimezone?: string;
18
+ sectionNames?: string[];
19
+ maxContextChars?: number;
16
20
  }): string | null;
@@ -53,7 +53,7 @@ function extractSections(content, sectionNames, foundNames) {
53
53
  return results;
54
54
  }
55
55
  function readPostCompactionContextFromAgentsMd(agentsMdContent, options) {
56
- const sectionNames = DEFAULT_POST_COMPACTION_SECTIONS;
56
+ const sectionNames = options?.sectionNames ?? DEFAULT_POST_COMPACTION_SECTIONS;
57
57
  if (sectionNames.length === 0) return null;
58
58
  const foundSectionNames = [];
59
59
  const sections = extractSections(agentsMdContent, sectionNames, foundSectionNames);
@@ -62,7 +62,7 @@ function readPostCompactionContextFromAgentsMd(agentsMdContent, options) {
62
62
  const timezone = options?.userTimezone?.trim() || Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
63
63
  const nowMs = options?.nowMs ?? Date.now();
64
64
  const dateStamp = new Intl.DateTimeFormat("en-CA", { timeZone: timezone }).format(new Date(nowMs));
65
- const maxContextChars = MAX_CONTEXT_CHARS;
65
+ const maxContextChars = Math.max(1, options?.maxContextChars ?? MAX_CONTEXT_CHARS);
66
66
  const combined = sections.join("\n\n").replaceAll("YYYY-MM-DD", dateStamp);
67
67
  const safeContent = combined.length > maxContextChars ? `${combined.slice(0, maxContextChars)}\n...[truncated]...` : combined;
68
68
  const isDefaultSections = sectionNames.length === DEFAULT_POST_COMPACTION_SECTIONS.length && sectionNames.every((name, index) => normalizeHeading(name) === normalizeHeading(DEFAULT_POST_COMPACTION_SECTIONS[index] ?? ""));
@@ -84,7 +84,9 @@ function readPostCompactionContext(params) {
84
84
  cfg,
85
85
  agentId,
86
86
  nowMs: params.nowMs,
87
- userTimezone: params.userTimezone
87
+ userTimezone: params.userTimezone,
88
+ sectionNames: params.sectionNames,
89
+ maxContextChars: params.maxContextChars
88
90
  });
89
91
  } catch {
90
92
  return null;
@@ -17,8 +17,7 @@ async function runProcessDirect(deps, input) {
17
17
  cfg: deps.config,
18
18
  sessionKey: input.sessionKey,
19
19
  body: input.content,
20
- resetSession: deps.resetSession,
21
- skipImplicitExpiry: channel === "webchat"
20
+ resetSession: deps.resetSession
22
21
  });
23
22
  resetTriggeredAtInit = turn.resetTriggered;
24
23
  if (turn.bareReset && turn.ackMessage) return turn.ackMessage;
@@ -154,8 +154,7 @@ async function* runProcessDirectStreaming(deps, input) {
154
154
  cfg,
155
155
  sessionKey,
156
156
  body: input.content,
157
- resetSession: deps.resetSession,
158
- skipImplicitExpiry: channel === "webchat"
157
+ resetSession: deps.resetSession
159
158
  });
160
159
  resetTriggeredAtInit = turn.resetTriggered;
161
160
  if (turn.bareReset && turn.ackMessage) {
@@ -102,7 +102,6 @@ export declare class AgentService {
102
102
  private createHookRunner;
103
103
  private createProgressManager;
104
104
  private initializeReliabilityModules;
105
- private initializeLifecycleHandlers;
106
105
  setChannelManager(channelManager: ChannelManager): void;
107
106
  /**
108
107
  * Apply config after save or hot reload so the default model updates without restarting the gateway.
@@ -191,7 +190,6 @@ export declare class AgentService {
191
190
  * Handle events from a specific session's agent
192
191
  */
193
192
  private handleSessionEvent;
194
- private checkAndCompact;
195
193
  private getContextWindowForSession;
196
194
  private dispose;
197
195
  }
@@ -15,6 +15,7 @@ import { onSessionTranscriptUpdate } from "../session/transcript-events.js";
15
15
  import { persistInboundAttachments } from "../channels/attachments/inbound-persist.js";
16
16
  import { AgentManager } from "./agent-manager.js";
17
17
  import { maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle } from "../session/session-title.js";
18
+ import { resolveCompactionPolicy } from "./memory/compaction-policy.js";
18
19
  import { SessionStore } from "../session/store.js";
19
20
  import { SessionConfigStore } from "../session/config-store.js";
20
21
  import "../session/index.js";
@@ -38,7 +39,6 @@ import "./middleware/index.js";
38
39
  import { TurnDiffTracker } from "./coding/turn-diff-tracker.js";
39
40
  import { LifecycleManager } from "./lifecycle/manager.js";
40
41
  import "./lifecycle/index.js";
41
- import { CompactionLifecycleHandler } from "./lifecycle/handlers/compaction.js";
42
42
  import { MessageRouter } from "./messaging/message-router.js";
43
43
  import { CommandHandler } from "./messaging/command-handler.js";
44
44
  import { StreamManager } from "./messaging/stream-manager.js";
@@ -203,10 +203,20 @@ var AgentService = class {
203
203
  return this.currentContext?.sessionKey;
204
204
  }
205
205
  });
206
+ this.sessionStore.setCompactionHooks({
207
+ before: ({ sessionKey, messageCount, tokenCount }) => this.hookHandler.triggerWithSessionKey(sessionKey, "before_compaction", {
208
+ messageCount,
209
+ tokenCount
210
+ }),
211
+ after: ({ sessionKey, messageCount, tokenCount, compactedCount }) => this.hookHandler.triggerWithSessionKey(sessionKey, "after_compaction", {
212
+ messageCount,
213
+ tokenCount,
214
+ compactedCount
215
+ })
216
+ });
206
217
  this.progressManager = this.createProgressManager();
207
218
  this.initializeReliabilityModules();
208
219
  this.lifecycleManager = new LifecycleManager();
209
- this.initializeLifecycleHandlers();
210
220
  this.streamManager = new StreamManager();
211
221
  this.sessionContextManager = new SessionContextManager();
212
222
  this.feedbackCoordinator = new FeedbackCoordinator({
@@ -400,7 +410,6 @@ var AgentService = class {
400
410
  setupSessionEventHandling: (sk) => this.setupSessionEventHandling(sk),
401
411
  sessionHydrator: this.sessionHydrator,
402
412
  getLastAssistantPlainText: (sk) => this.getLastAssistantPlainText(sk),
403
- checkAndCompact: (sk, msgs) => this.checkAndCompact(sk, msgs),
404
413
  enqueueMaybeAutoTitleAfterPersist: (sk) => this.enqueueMaybeAutoTitleAfterPersist(sk),
405
414
  getConfig: () => this.effectiveAppConfig(),
406
415
  resetSession: (sk) => this.resetSession(sk),
@@ -418,19 +427,9 @@ var AgentService = class {
418
427
  keepRecentMessages: 20,
419
428
  preserveSystemMessages: true
420
429
  };
421
- const compactionConfig = {
422
- enabled: true,
423
- mode: "abstractive",
424
- reserveTokens: 8e3,
425
- triggerThreshold: .8,
426
- minMessagesBeforeCompact: 10,
427
- keepRecentMessages: 10,
428
- evictionWindow: .2,
429
- retentionWindow: 6
430
- };
431
430
  const appCfg = this.config.config;
432
431
  if (!appCfg) throw new Error("AgentService requires config.config for session store paths");
433
- return new SessionStore({ config: appCfg }, windowConfig, compactionConfig);
432
+ return new SessionStore({ config: appCfg }, windowConfig, resolveCompactionPolicy(appCfg));
434
433
  }
435
434
  createHookRunner() {
436
435
  if (!this.config.extensionRegistry) return void 0;
@@ -498,15 +497,6 @@ var AgentService = class {
498
497
  });
499
498
  this.contextMiddleware = new ContextMiddleware();
500
499
  }
501
- initializeLifecycleHandlers() {
502
- this.lifecycleManager.on("llm_response", new CompactionLifecycleHandler({
503
- minMessages: 20,
504
- maxTokens: 8e3,
505
- preserveReasoning: true,
506
- accumulateUsage: true
507
- }));
508
- log.debug({ handlers: this.lifecycleManager.getRegisteredHandlers() }, "Lifecycle handlers initialized");
509
- }
510
500
  setChannelManager(channelManager) {
511
501
  this.inboundLoop.setChannelManager(channelManager);
512
502
  }
@@ -809,27 +799,6 @@ var AgentService = class {
809
799
  }
810
800
  this.agentEventHandler.handle(event, currentContext);
811
801
  }
812
- async checkAndCompact(sessionKey, messages) {
813
- const contextWindow = this.getContextWindowForSession(sessionKey);
814
- const prep = this.sessionStore.prepareCompaction(sessionKey, messages, contextWindow);
815
- if (!prep.needsCompaction) return;
816
- log.info({
817
- sessionKey,
818
- reason: prep.stats?.reason,
819
- usagePercent: prep.stats?.usagePercent
820
- }, "Session needs compaction");
821
- const result = await this.sessionStore.compact(sessionKey, messages, contextWindow, void 0, false);
822
- await this.hookHandler.trigger("after_compaction", {
823
- messageCount: messages.length,
824
- tokenCount: result.tokensBefore,
825
- compactedCount: messages.length - result.firstKeptIndex
826
- });
827
- log.info({
828
- sessionKey,
829
- tokensBefore: result.tokensBefore,
830
- tokensAfter: result.tokensAfter
831
- }, "Session compacted");
832
- }
833
802
  getContextWindowForSession(sessionKey) {
834
803
  try {
835
804
  return this.modelManager.getResolvedModelForSession(sessionKey).contextWindow ?? 128e3;
@@ -2,8 +2,10 @@ import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { init_workspace_defaults, resolveDefaultAgentWorkspaceDir } from "../../config/workspace-defaults.js";
4
4
  import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
5
+ import { init_providers, resolveModel } from "../../providers/index.js";
5
6
  import { effectiveWorkspacePathForSession, projectWorkspacePath } from "../../session/session-workspace.js";
6
7
  import { getProjectForSession } from "../../projects/workspace.js";
8
+ import { resolveCompactionPolicy } from "../memory/compaction-policy.js";
7
9
  import { resolveVerboseLevel } from "../../session/config-store.js";
8
10
  import { resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel } from "../../session/thinking-resolve.js";
9
11
  import "../../session/index.js";
@@ -12,6 +14,7 @@ import { formatSessionContextReport } from "../service/session-context-report.js
12
14
  //#region src/agent/session/session-inspector.ts
13
15
  init_workspace_defaults();
14
16
  init_logger();
17
+ init_providers();
15
18
  const log = createLogger("SessionInspector");
16
19
  var SessionInspector = class {
17
20
  opts;
@@ -37,8 +40,13 @@ var SessionInspector = class {
37
40
  */
38
41
  async compact(sessionKey, options) {
39
42
  const messages = await this.opts.sessionStore.load(sessionKey);
40
- const contextWindow = await this.contextWindowForSession(sessionKey);
41
- const result = await this.opts.sessionStore.compact(sessionKey, messages, contextWindow, options?.instructions, options?.force ?? true);
43
+ await this.ensureEffectiveSessionModel(sessionKey);
44
+ const policy = resolveCompactionPolicy(this.opts.getConfig());
45
+ const sessionModel = this.opts.modelManager.getResolvedModelForSession(sessionKey);
46
+ const model = policy.model ? resolveModel(policy.model) : sessionModel;
47
+ const primaryRef = `${model.provider}/${model.id}`;
48
+ const fallbackModels = this.opts.modelManager.getFallbackCandidatesForSession(sessionKey).map((candidate) => resolveModel(`${candidate.provider}/${candidate.model}`)).filter((candidate) => `${candidate.provider}/${candidate.id}` !== primaryRef);
49
+ const result = await this.opts.sessionStore.compact(sessionKey, messages, model, options?.instructions, options?.force ?? true, { fallbackModels });
42
50
  if (result.compacted) this.opts.agentManager.removeAgent(sessionKey);
43
51
  log.info({
44
52
  sessionKey,
@@ -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 v59).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v61).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -1552,7 +1552,23 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1552
1552
  }>>;
1553
1553
  }, z.core.$strict>>;
1554
1554
  retention: z.ZodOptional<z.ZodObject<{
1555
- compaction: z.ZodDefault<z.ZodBoolean>;
1555
+ compaction: z.ZodDefault<z.ZodObject<{
1556
+ enabled: z.ZodDefault<z.ZodBoolean>;
1557
+ triggerThreshold: z.ZodDefault<z.ZodNumber>;
1558
+ reserveTokens: z.ZodDefault<z.ZodNumber>;
1559
+ minMessagesBeforeCompact: z.ZodDefault<z.ZodNumber>;
1560
+ keepRecentTokens: z.ZodDefault<z.ZodNumber>;
1561
+ recentTurnsPreserve: z.ZodDefault<z.ZodNumber>;
1562
+ summaryMaxTokens: z.ZodDefault<z.ZodNumber>;
1563
+ summaryChunkTokens: z.ZodDefault<z.ZodNumber>;
1564
+ summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
1565
+ summaryRetries: z.ZodDefault<z.ZodNumber>;
1566
+ qualityGuard: z.ZodDefault<z.ZodBoolean>;
1567
+ model: z.ZodOptional<z.ZodString>;
1568
+ minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
1569
+ maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
1570
+ postCompactionSections: z.ZodDefault<z.ZodArray<z.ZodString>>;
1571
+ }, z.core.$strict>>;
1556
1572
  maxAgeDays: z.ZodOptional<z.ZodNumber>;
1557
1573
  maxItems: z.ZodOptional<z.ZodNumber>;
1558
1574
  maxChars: z.ZodOptional<z.ZodNumber>;
@@ -307,6 +307,29 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
307
307
  maxEntries: number;
308
308
  };
309
309
  };
310
+ userContext: {
311
+ memory: {
312
+ retention: {
313
+ compaction: {
314
+ enabled: boolean;
315
+ triggerThreshold: number;
316
+ reserveTokens: number;
317
+ minMessagesBeforeCompact: number;
318
+ keepRecentTokens: number;
319
+ recentTurnsPreserve: number;
320
+ summaryMaxTokens: number;
321
+ summaryChunkTokens: number;
322
+ summaryTimeoutMs: number;
323
+ summaryRetries: number;
324
+ qualityGuard: boolean;
325
+ minToolResultKeepChars: number;
326
+ maxActiveTranscriptBytes: number;
327
+ postCompactionSections: string[];
328
+ model?: string;
329
+ };
330
+ };
331
+ };
332
+ };
310
333
  tui: {
311
334
  defaultAgent: string;
312
335
  };
@@ -1,3 +1,4 @@
1
+ import { ContextCompactionPolicySchema, init_config } from "../../../user-context/config.js";
1
2
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
2
3
  import { resolveModelsJsonPath } from "../../../config/paths.js";
3
4
  import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
@@ -20,6 +21,7 @@ init_credentials();
20
21
  init_models_json();
21
22
  init_providers();
22
23
  init_plugin_registry();
24
+ init_config();
23
25
  function readModelsJsonProviderApiKey(providerId) {
24
26
  const { config } = loadModelsJson(resolveModelsJsonPath());
25
27
  const key = (config.providers?.[providerId])?.apiKey;
@@ -175,6 +177,7 @@ async function buildSafeWebConfigPayload(service, options = {}) {
175
177
  browser: buildSafeBrowserConfigForWeb(config.browser),
176
178
  goals: resolveGoalsConfigForWeb(config),
177
179
  session: resolveSessionConfigForWeb(config),
180
+ userContext: { memory: { retention: { compaction: ContextCompactionPolicySchema.parse(config.userContext?.memory.retention?.compaction) } } },
178
181
  tui: { defaultAgent: config.tui?.defaultAgent ?? "coder" },
179
182
  tunnel: {
180
183
  enabled: config.tunnel?.enabled === true,
@@ -2,7 +2,7 @@
2
2
  * `PATCH /api/config` — tail sections that are each <50 lines:
3
3
  * update / goals / session / gateway.{skillsMarketplaceProvider,
4
4
  * skillsStoreBaseUrl} / providers / providersConfig / stt / tts / tools /
5
- * tunnel / bindings / mcp.
5
+ * userContext.memory.retention.compaction / tunnel / bindings / mcp.
6
6
  *
7
7
  * Most of these delegate to a `mergeXxxConfigPatch(config, body) → { ok,
8
8
  * message? }` helper that lives next to the schema, so this file is mostly
@@ -1,3 +1,4 @@
1
+ import { ContextCompactionPolicySchema, init_config } from "../../../../user-context/config.js";
1
2
  import { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema, VoiceConfigSchema, init_schema } from "../../../../config/schema.js";
2
3
  import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
3
4
  import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
@@ -13,6 +14,7 @@ import { PATCH_OK, patchError } from "./result.js";
13
14
  //#region src/gateway/hono/routes/config-patch/misc.ts
14
15
  init_schema();
15
16
  init_credentials();
17
+ init_config();
16
18
  async function applyMiscPatch(config, body) {
17
19
  if (body.update !== void 0 && typeof body.update === "object" && body.update !== null) {
18
20
  const updateResult = mergeUpdateConfigPatch(config, body.update);
@@ -28,6 +30,32 @@ async function applyMiscPatch(config, body) {
28
30
  const sessionResult = mergeSessionConfigPatch(config, body.session);
29
31
  if (sessionResult.ok === false) return patchError(sessionResult.message);
30
32
  }
33
+ if (body.userContext !== void 0) {
34
+ if (typeof body.userContext !== "object" || body.userContext === null || Array.isArray(body.userContext)) return patchError("userContext must be an object");
35
+ const userContextPatch = body.userContext;
36
+ if (userContextPatch.memory !== void 0) {
37
+ if (typeof userContextPatch.memory !== "object" || userContextPatch.memory === null || Array.isArray(userContextPatch.memory)) return patchError("userContext.memory must be an object");
38
+ const memoryPatch = userContextPatch.memory;
39
+ if (memoryPatch.retention !== void 0) {
40
+ if (typeof memoryPatch.retention !== "object" || memoryPatch.retention === null || Array.isArray(memoryPatch.retention)) return patchError("userContext.memory.retention must be an object");
41
+ const retentionPatch = memoryPatch.retention;
42
+ if (retentionPatch.compaction !== void 0) {
43
+ const parsed = ContextCompactionPolicySchema.safeParse(retentionPatch.compaction);
44
+ if (!parsed.success) return patchError(parsed.error.issues.map((issue) => issue.message).join("; "));
45
+ config.userContext = {
46
+ ...config.userContext,
47
+ memory: {
48
+ ...config.userContext?.memory,
49
+ retention: {
50
+ ...config.userContext?.memory?.retention,
51
+ compaction: parsed.data
52
+ }
53
+ }
54
+ };
55
+ }
56
+ }
57
+ }
58
+ }
31
59
  if (body.tui !== void 0) {
32
60
  if (typeof body.tui !== "object" || body.tui === null || Array.isArray(body.tui)) return patchError("tui must be an object");
33
61
  const tuiPatch = body.tui;
@@ -5,7 +5,6 @@ import { evictEmbeddedSessionRunner } from "../../../agent/embedded/session-runn
5
5
  import { messagesToClientHistory } from "../../../session/client-history.js";
6
6
  import { deleteMediaUrisNoLongerReferenced } from "../../../media/session-references.js";
7
7
  import { createGatewayRouteLogger, logRouteError } from "../lib/route-logger.js";
8
- import { computeUserRoundDeleteRange } from "../../../session/user-round-delete.js";
9
8
  import { respondStartupUnavailable } from "../lib/startup-unavailable.js";
10
9
  import { randomUUID } from "node:crypto";
11
10
  //#region src/gateway/hono/routes/sessions.ts
@@ -459,48 +458,35 @@ function registerSessionsRoutes(authenticated, deps) {
459
458
  evictEmbeddedSessionRunner(key, "gateway_bash_execution_appended");
460
459
  return c.json({ ok: true });
461
460
  });
462
- authenticated.get("/api/sessions/:key/compaction/checkpoints", async (c) => {
461
+ authenticated.get("/api/sessions/:key/compaction/boundaries", async (c) => {
463
462
  const key = c.req.param("key");
464
463
  if (!await service.sessionIndexInstance.getSessionMetadata(key)) return c.json({
465
464
  ok: false,
466
465
  error: "Session not found"
467
466
  }, 404);
468
- const checkpoints = await service.sessions.listCompactionCheckpoints(key);
467
+ const boundaries = await service.sessions.listCompactionBoundaries(key);
469
468
  return c.json({
470
469
  ok: true,
471
- payload: { checkpoints }
472
- });
473
- });
474
- authenticated.get("/api/sessions/:key/compaction/checkpoints/:checkpointId", async (c) => {
475
- const key = c.req.param("key");
476
- const checkpointId = c.req.param("checkpointId");
477
- const checkpoint = await service.sessions.getCompactionCheckpoint(key, checkpointId);
478
- if (!checkpoint) return c.json({
479
- ok: false,
480
- error: "Checkpoint not found"
481
- }, 404);
482
- return c.json({
483
- ok: true,
484
- payload: { checkpoint }
470
+ payload: { boundaries }
485
471
  });
486
472
  });
487
473
  authenticated.post("/api/sessions/:key/compaction/restore", async (c) => {
488
474
  const key = c.req.param("key");
489
475
  const body = await c.req.json().catch(() => ({}));
490
- const checkpointId = typeof body.checkpointId === "string" ? body.checkpointId.trim() : "";
491
- if (!checkpointId) return c.json({
476
+ const compactionId = typeof body.compactionId === "string" ? body.compactionId.trim() : "";
477
+ if (!compactionId) return c.json({
492
478
  ok: false,
493
- error: "checkpointId required"
479
+ error: "compactionId required"
494
480
  }, 400);
495
481
  try {
496
- await service.sessions.restoreCompactionCheckpoint(key, checkpointId);
482
+ await service.sessions.restoreBeforeCompactionBoundary(key, compactionId);
497
483
  } catch (err) {
498
484
  logRouteError(log, c, err, "gateway.route.sessions", {
499
- operation: "restoreCheckpoint",
485
+ operation: "restoreCompactionBoundary",
500
486
  sessionKey: key
501
487
  });
502
488
  const msg = err instanceof Error ? err.message : String(err);
503
- if (msg.includes("not found") || msg.includes("Invalid")) return c.json({
489
+ if (msg.includes("not found")) return c.json({
504
490
  ok: false,
505
491
  error: msg
506
492
  }, 404);
@@ -695,30 +681,19 @@ function registerSessionsRoutes(authenticated, deps) {
695
681
  authenticated.delete("/api/sessions/:key/messages", async (c) => {
696
682
  const key = c.req.param("key");
697
683
  const body = await c.req.json().catch(() => ({}));
698
- const loaded = await service.sessionIndexInstance.loadMessages(key);
699
- if (!loaded) return c.json({ error: "Session not found" }, 404);
700
- let startIndex = typeof body.startIndex === "number" ? body.startIndex : -1;
701
- let count = typeof body.count === "number" ? body.count : 0;
702
684
  const userRoundIndex = typeof body.userRoundIndex === "number" ? body.userRoundIndex : void 0;
703
- if (userRoundIndex !== void 0) {
704
- const range = computeUserRoundDeleteRange(loaded, userRoundIndex);
705
- if (!range) return c.json({ error: "User round index out of range" }, 400);
706
- startIndex = range.startIndex;
707
- count = range.count;
708
- }
709
- if (startIndex < 0 || count <= 0) return c.json({ error: "Invalid startIndex or count" }, 400);
710
- if (startIndex >= loaded.length) return c.json({ error: "Index out of range" }, 400);
711
- const deleteCount = Math.min(count, loaded.length - startIndex);
712
- const removed = loaded.slice(startIndex, startIndex + deleteCount);
713
- const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));
714
- await service.sessionIndexInstance.saveMessages(key, next);
685
+ if (userRoundIndex === void 0 || !Number.isInteger(userRoundIndex) || userRoundIndex < 0) return c.json({ error: "userRoundIndex must be a non-negative integer" }, 400);
686
+ const result = await service.sessionIndexInstance.deleteUserRound(key, userRoundIndex);
687
+ if (!result) return c.json({ error: "User round index out of range" }, 400);
715
688
  await deleteMediaUrisNoLongerReferenced({
716
- removed,
717
- remaining: next
689
+ removed: result.removedMessages,
690
+ remaining: result.remainingMessages
718
691
  });
692
+ evictEmbeddedSessionRunner(key, "gateway_user_round_deleted");
693
+ service.agentService.evictSessionAgent(key);
719
694
  return c.json({
720
695
  ok: true,
721
- deleted: deleteCount
696
+ deleted: result.deleted
722
697
  });
723
698
  });
724
699
  authenticated.post("/api/sessions/:key/reset", async (c) => {
@@ -92,9 +92,8 @@ export declare class GatewaySessionsApi {
92
92
  verboseLevel?: string;
93
93
  workingDirectory?: string;
94
94
  }): Promise<import("../../agent/session/session-config-service.js").PatchSessionAgentConfigResult>;
95
- listCompactionCheckpoints(key: string): Promise<import("../../session/types.js").CompactionCheckpointSummary[]>;
96
- getCompactionCheckpoint(key: string, checkpointId: string): Promise<import("../../session/types.js").CompactionCheckpointDetail>;
97
- restoreCompactionCheckpoint(key: string, checkpointId: string): Promise<void>;
95
+ listCompactionBoundaries(key: string): Promise<import("../../session/types.js").CompactionBoundarySummary[]>;
96
+ restoreBeforeCompactionBoundary(key: string, compactionId: string): Promise<void>;
98
97
  runCompaction(key: string, options?: {
99
98
  instructions?: string;
100
99
  force?: boolean;
@@ -93,14 +93,11 @@ var GatewaySessionsApi = class {
93
93
  patchAgentConfig(sessionKey, body) {
94
94
  return this.opts.getAgentService().sessionConfig.patch(sessionKey, body);
95
95
  }
96
- listCompactionCheckpoints(key) {
97
- return this.opts.sessionIndex.listCompactionCheckpoints(key);
96
+ listCompactionBoundaries(key) {
97
+ return this.opts.sessionIndex.listCompactionBoundaries(key);
98
98
  }
99
- getCompactionCheckpoint(key, checkpointId) {
100
- return this.opts.sessionIndex.getCompactionCheckpointDetail(key, checkpointId);
101
- }
102
- async restoreCompactionCheckpoint(key, checkpointId) {
103
- await this.opts.sessionIndex.restoreCompactionCheckpoint(key, checkpointId);
99
+ async restoreBeforeCompactionBoundary(key, compactionId) {
100
+ await this.opts.sessionIndex.restoreBeforeCompactionBoundary(key, compactionId);
104
101
  this.opts.getAgentService().evictSessionAgent(key);
105
102
  }
106
103
  async runCompaction(key, options) {
@@ -6,8 +6,7 @@ export { SessionConfigStore, resolveThinkingLevel, resolveReasoningLevel, resolv
6
6
  export { resolveEffectiveThinkingLevel, resolveEffectiveReasoningLevel } from './thinking-resolve.js';
7
7
  export type { SessionAgentConfig } from './config-types.js';
8
8
  export { normalizeWorkingDirectoryInput, effectiveWorkspacePathForSession, projectWorkspacePath, } from './session-workspace.js';
9
- export { SessionStatus, type SessionMetadata, type SessionDetail, type SessionListQuery, type PaginatedResult, type SessionStats, type ExportFormat, type SessionExport, type SessionTranscriptSummary, type CompactionCheckpointSummary, type CompactionCheckpointDetail, } from './types.js';
10
- export { normalizeCompactionCheckpointId } from './compaction-checkpoints.js';
9
+ export { SessionStatus, type SessionMetadata, type SessionDetail, type SessionListQuery, type PaginatedResult, type SessionStats, type ExportFormat, type SessionExport, type SessionTranscriptSummary, type CompactionBoundarySummary, } from './types.js';
11
10
  export { shouldSkipWebchatInboundByAbortCutoff } from './abort-cutoff.js';
12
11
  export { DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_IDLE_MINUTES, evaluateSessionFreshness, resolveDailyResetAtMs, resolveSessionResetPolicy, type SessionFreshness, type SessionResetConfig, type SessionResetMode, type SessionResetPolicy, type SessionResetType, } from './reset-policy.js';
13
12
  export { resolveChannelResetConfig, resolveSessionResetType, } from './reset-type.js';
@@ -3,7 +3,6 @@ import { buildSessionContextForLlm, isTranscriptContextEntry, mergeLlmMessagesPr
3
3
  import { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput, projectWorkspacePath } from "./session-workspace.js";
4
4
  import { emitSessionTranscriptUpdate, onSessionTranscriptUpdate } from "./transcript-events.js";
5
5
  import { fallbackTitleFromMessages, generateSessionTitleFromMessages, getSessionTitleSource, isWebchatSessionKey, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, provisionalTitleFromUserText, sanitizeGeneratedSessionTitle, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm } from "./session-title.js";
6
- import { normalizeCompactionCheckpointId } from "./compaction-checkpoints.js";
7
6
  import { flattenMessageContent, messagesToClientHistory } from "./client-history.js";
8
7
  import { SessionStore } from "./store.js";
9
8
  import { applySessionPatchToMetadata } from "./patch-metadata.js";
@@ -18,4 +17,4 @@ import { resolveSession, resolveSessionKeyForRequest } from "./resolve-session.j
18
17
  import { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, bareResetAckMessage, matchResetTriggers, resolveResetTriggers, shouldSkipResetOverlapCommand, stripLeadingEnvelopeTimestamp } from "./reset-triggers.js";
19
18
  import { initSessionTurn } from "./init-session-turn.js";
20
19
  import { CURRENT_SESSION_TRANSCRIPT_VERSION, XOPC_SESSION_TRANSCRIPT_TYPE } from "./transcript-format.js";
21
- export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getSessionTitleSource, initSessionTurn, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeCompactionCheckpointId, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, projectWorkspacePath, provisionalTitleFromUserText, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeGeneratedSessionTitle, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
20
+ export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getSessionTitleSource, initSessionTurn, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, projectWorkspacePath, provisionalTitleFromUserText, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeGeneratedSessionTitle, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
@@ -19,6 +19,5 @@ export type InitSessionTurnOptions = {
19
19
  sessionKey: string;
20
20
  body?: string;
21
21
  resetSession: SessionResetFn;
22
- skipImplicitExpiry?: boolean;
23
22
  };
24
23
  export declare function initSessionTurn(opts: InitSessionTurnOptions): Promise<InitSessionTurnResult>;
@@ -50,8 +50,7 @@ async function initSessionTurn(opts) {
50
50
  now,
51
51
  policy: resetPolicy
52
52
  }) : { fresh: false };
53
- const skipImplicit = opts.skipImplicitExpiry ?? false;
54
- const staleRollover = Boolean(sessionMetadata && !skipImplicit && !freshness.fresh);
53
+ const staleRollover = Boolean(sessionMetadata && resetPolicy.configured === true && !freshness.fresh);
55
54
  const needsRollover = triggerMatch.resetTriggered || staleRollover;
56
55
  let sessionId = sessionMetadata?.sessionId;
57
56
  let previousSessionId;