@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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-CkUp1qvf.js → activity-store-BLz30jWq.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DDuem4HM.js → agent-avatar-dicebear-BKZO0EFn.js} +1 -1
- package/dist/gateway/static/root/assets/agents-ZCIC8mhO.js +2 -0
- package/dist/gateway/static/root/assets/{api-BnuPQhJW.js → api-N2qKY-WI.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-DdZw8Hi1.js → app-management-settings-panel-CNZkpXCD.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BN8Vk2bX.js → appearance-settings-Drf5a563.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CuL8Q4yF.js → apps-page-DJmgBaAm.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-C82MaDQj.js → archive-plugin-ChVwOXE5.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-uilrwSdW.js → attachment-load-BVK3Y2d9.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-CkDZjAmy.js → automation-suggestion-card-DH4N0SYR.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-Ddot8-Md.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-B7NTL0_T.js → binary-plugins-CeHY6VVP.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-D3GIllO3.js +184 -0
- package/dist/gateway/static/root/assets/browser-settings-page-DvETvRcg.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-UFVUzn4v.js → browser-workflow-inputs-femCtfpo.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-CGgC0N92.js → browser-workflows-page-o0GVE_aF.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-ChXIYbys.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-DUIorGUd.js → capability-presets-api-Bx-JJC0R.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUekXsJy.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-BYwSB8c6.js → channel-recipient-api-CTw3ibx4.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CkhveNsQ.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-DRTb8DBk.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-CsbegNqi.js → connector-logo-CQznQcd4.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-DkSGIxWP.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-BtP-xUQ9.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DkbIzdA3.js → desktop-pet-settings-CIeH4VyP.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-dBQvj1sG.js → directory-picker-path-field-Ddgt6c3K.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-DkdnKMZx.js → dreaming-settings-gd9W6SLj.js} +3 -3
- package/dist/gateway/static/root/assets/{extension-debug-page-BfxoIiNo.js → extension-debug-page-CJGwUaQX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-EIJ3wIb7.js → extension-page-B3zHKJAB.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DBBec51N.js → extension-settings-page-Cj9rrSr1.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-4_u53Ufq.js → gateway-config-api-BdmtlJRP.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-v9kJM59H.js → gateway-settings-C2RwKIsl.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CXITih5d.js → gateway-startup-retry-mcMq_uu_.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-5Ryd_rx4.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-DizZ6Cpl.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-D54YQPon.js → goals-config-api-CAO1J4jn.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-Dqry_hi2.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-DDezXaVi.js → goals-settings-Boj2izKZ.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CRsIUeZN.js → heartbeat-settings-DbPC9a_y.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-CY6cQUHL.js → image-generation-api-DrLCLTXn.js} +1 -1
- package/dist/gateway/static/root/assets/index-DEdyUjxM.css +1 -0
- package/dist/gateway/static/root/assets/{index-Dfq2laZe.js → index-vHb2z7VS.js} +7 -7
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D9k7EDdY.js → keyboard-shortcuts-settings-BrxfptgY.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-BP0_Ih0e.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DbaiBolh.js → local-apps-page-DNCRlfFs.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Dqp9H2Uf.js → locale-store-CzIfXqm8.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-mT48mcF4.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-BGlQR-Be.js → markdown-split-CIUH9Lor.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BpaeV6f_.js → media-plugins-DX4AgkCs.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CKZuaOeG.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-Cd2HpciM.js → notes-page-D1KprtxL.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-wgt2Osyk.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-DyimBUp_.js → page-tabs-DjZPJGf6.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BKZulEYr.js → preview-open-alternatives-DNiJTpwZ.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-Bjz9BxBY.js → product-open-page-CNfR17-g.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CDjHvxJm.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-kJZwQXfC.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-MJdI9ek_.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-BPTqb2_r.js → save-bar-controls-BGZFVO9S.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-YN0D81Dk.js → schedule-field-BAZiHtds.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BmY5PSS2.js → schema-form-CesBcwJH.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BqC7GDC_.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CYwz8MfF.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-B-RhgD_p.js → settings-form-section-Bxc54BLj.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-DkPupX2B.js → settings-loading-skeleton-CYrho7Db.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-2QBMvaxj.js → settings-page-C03X5fkh.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-CtrW-LD6.js → settings-page-layout-CZAJbv4E.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Jv8_bcOD.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BezIW1n9.js → share-preview-page-DSC7tKKG.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-h8tGDkA3.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-D2DGvRUn.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-vqhjSMhZ.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-WAFhKyAu.js → system-settings-panel-BO89zw5H.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-BiC0gIBa.js → theme-store-1OkdVC8l.js} +1 -1
- package/dist/gateway/static/root/assets/time-picker-mtD64kFB.js +1 -0
- package/dist/gateway/static/root/assets/{typed-models-lib-WAQO3F_8.js → typed-models-lib-D-_vct_y.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-CKlfsSeU.js → use-channel-catalog-VlFtjlET.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BgF0WxjM.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BAFHF0_v.js → voice-api-key-field-BhDk-UV_.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-page-CP0Daig-.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-NEWZPKB_.js +1 -0
- package/dist/gateway/static/root/assets/work-page-BkWntcQh.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-1OP4HyvS.js → workflow-run-setup-panel-uVw4Yoej.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DRvhNQGe.js +11 -0
- package/dist/gateway/static/root/index.html +7 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +71 -24
- package/dist/src/agent/embedded/run-turn.js +68 -4
- package/dist/src/agent/inbound/inbound-loop.d.ts +0 -2
- package/dist/src/agent/inbound/inbound-loop.js +0 -2
- package/dist/src/agent/memory/compaction-planner.d.ts +16 -0
- package/dist/src/agent/memory/compaction-planner.js +152 -0
- package/dist/src/agent/memory/compaction-policy.d.ts +10 -0
- package/dist/src/agent/memory/compaction-policy.js +24 -0
- package/dist/src/agent/memory/compaction.d.ts +21 -22
- package/dist/src/agent/memory/compaction.js +220 -194
- package/dist/src/agent/memory/context-budget.d.ts +40 -0
- package/dist/src/agent/memory/context-budget.js +106 -0
- package/dist/src/agent/orchestration/context-overflow.d.ts +1 -0
- package/dist/src/agent/orchestration/context-overflow.js +19 -0
- package/dist/src/agent/orchestration/loop-guard.js +13 -9
- package/dist/src/agent/reply/post-compaction-context.d.ts +4 -0
- package/dist/src/agent/reply/post-compaction-context.js +5 -3
- package/dist/src/agent/service/process-direct-one-shot.js +1 -2
- package/dist/src/agent/service/process-direct-streaming.js +1 -2
- package/dist/src/agent/service.d.ts +0 -2
- package/dist/src/agent/service.js +13 -44
- package/dist/src/agent/session/session-inspector.js +10 -2
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/schema.d.ts +17 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +23 -0
- package/dist/src/gateway/hono/lib/config-payload.js +3 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +28 -0
- package/dist/src/gateway/hono/routes/sessions.js +17 -42
- package/dist/src/gateway/service/sessions-api.d.ts +2 -3
- package/dist/src/gateway/service/sessions-api.js +4 -7
- package/dist/src/session/index.d.ts +1 -2
- package/dist/src/session/index.js +1 -2
- package/dist/src/session/init-session-turn.d.ts +0 -1
- package/dist/src/session/init-session-turn.js +1 -2
- package/dist/src/session/manager.d.ts +11 -17
- package/dist/src/session/manager.js +11 -14
- package/dist/src/session/session-context-for-llm.d.ts +19 -1
- package/dist/src/session/session-context-for-llm.js +87 -129
- package/dist/src/session/store.d.ts +28 -23
- package/dist/src/session/store.js +94 -83
- package/dist/src/session/transcript-format.d.ts +2 -8
- package/dist/src/session/types.d.ts +8 -6
- package/dist/src/session/user-round-delete.d.ts +3 -6
- package/dist/src/session/user-round-delete.js +12 -16
- package/dist/src/storage/sqlite/index.d.ts +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- package/dist/src/storage/sqlite/migrations/060_remove_runtime_transcript_messages.sql +45 -0
- package/dist/src/storage/sqlite/migrations/061_drop_compaction_checkpoints.sql +2 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +0 -19
- package/dist/src/storage/sqlite/transcript-repository.d.ts +6 -11
- package/dist/src/storage/sqlite/transcript-repository.js +90 -84
- package/dist/src/user-context/config.d.ts +67 -2
- package/dist/src/user-context/config.js +36 -3
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-BiaQhiQp.js +0 -2
- package/dist/gateway/static/root/assets/automations-page-TZOluRNp.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-D_LDNlB-.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-C-l6O68Z.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BW8c0xPp.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-PTz00nR4.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-h9CsE0GT.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-C058Mcfr.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BWALafGW.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-CkT98fPT.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-y2Y3p7_k.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DuzL-alv.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-OeLtfKI2.js +0 -2
- package/dist/gateway/static/root/assets/index-o4uaOGKT.css +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-3ssYIEK6.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-DoCY0Mm9.js +0 -7
- package/dist/gateway/static/root/assets/messages-KEk-hTFt.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-CatZNAPc.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-DJUOgqm4.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BQQAD_nu.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-fIGXTTnA.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BuU-8FCe.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DlKoeZm3.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-BSUcDFnb.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Bk2-SwGJ.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-e_Fx1kVC.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-D_cCADfj.js +0 -2
- package/dist/gateway/static/root/assets/time-picker-fqRXpNJV.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-9Ov4htPW.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-DGN2FxWv.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-HmyWSgUo.js +0 -1
- package/dist/gateway/static/root/assets/work-page-D3iKVjFq.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-B5L4SFw4.js +0 -11
- package/dist/src/agent/lifecycle/handlers/compaction.d.ts +0 -13
- package/dist/src/agent/lifecycle/handlers/compaction.js +0 -18
- package/dist/src/session/compaction-checkpoints.d.ts +0 -8
- 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
|
|
15
|
-
return
|
|
16
|
-
if (typeof
|
|
17
|
-
if (typeof
|
|
18
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
41
|
-
const
|
|
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
|
|
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.
|
|
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/
|
|
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
|
|
467
|
+
const boundaries = await service.sessions.listCompactionBoundaries(key);
|
|
469
468
|
return c.json({
|
|
470
469
|
ok: true,
|
|
471
|
-
payload: {
|
|
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
|
|
491
|
-
if (!
|
|
476
|
+
const compactionId = typeof body.compactionId === "string" ? body.compactionId.trim() : "";
|
|
477
|
+
if (!compactionId) return c.json({
|
|
492
478
|
ok: false,
|
|
493
|
-
error: "
|
|
479
|
+
error: "compactionId required"
|
|
494
480
|
}, 400);
|
|
495
481
|
try {
|
|
496
|
-
await service.sessions.
|
|
482
|
+
await service.sessions.restoreBeforeCompactionBoundary(key, compactionId);
|
|
497
483
|
} catch (err) {
|
|
498
484
|
logRouteError(log, c, err, "gateway.route.sessions", {
|
|
499
|
-
operation: "
|
|
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")
|
|
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
|
|
704
|
-
|
|
705
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
96
|
-
|
|
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
|
-
|
|
97
|
-
return this.opts.sessionIndex.
|
|
96
|
+
listCompactionBoundaries(key) {
|
|
97
|
+
return this.opts.sessionIndex.listCompactionBoundaries(key);
|
|
98
98
|
}
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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,
|
|
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 };
|
|
@@ -50,8 +50,7 @@ async function initSessionTurn(opts) {
|
|
|
50
50
|
now,
|
|
51
51
|
policy: resetPolicy
|
|
52
52
|
}) : { fresh: false };
|
|
53
|
-
const
|
|
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;
|