@xopcai/xopc 0.0.205 → 0.0.207
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/README.zh-CN.md +7 -7
- 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-DJBadfSX.js → activity-store-BmpM0zwM.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Br6C32BX.js → agent-avatar-dicebear-DhK5wi6_.js} +1 -1
- package/dist/gateway/static/root/assets/agents-Bc3Lc-n2.js +68 -0
- package/dist/gateway/static/root/assets/{api-B5O7fKXa.js → api-CzaAcDOn.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Le1vJ1OO.js → app-management-settings-panel-Dqj5G_cd.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CZlAU60t.js → appearance-settings-Bm1uLGMi.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BKtwU47-.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CRzXRXPE.js → archive-plugin-CgnzBplN.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CYAAQ6Qi.js → attachment-load-Cuybcmhn.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-ilGeRLDN.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CVR5cUmS.js → binary-plugins-D6BBx6Ps.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CFe74rWi.js → block-editor-Dk1c3Spa.js} +46 -46
- package/dist/gateway/static/root/assets/browser-settings-page-BCu8AZbs.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bd68yluo.js → browser-workflow-inputs-DvfIzCgV.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-B0uiDLga.js → browser-workflows-page-DZScuPlF.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BbWQBtTe.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-BerPMp6f.js → capability-presets-api-hoA8R_J1.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BTVU46Yn.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-D2d21_XA.js → channel-recipient-api-BS8I65NT.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BEQsC9a9.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-DRwbgtOT.js +1 -0
- package/dist/gateway/static/root/assets/chat-terminal-dock-BIPhWBDI.js +36 -0
- package/dist/gateway/static/root/assets/chat-terminal-dock-uQUnjRtf.css +1 -0
- package/dist/gateway/static/root/assets/{connectors-api-Bq_vUzxP.js → connectors-api-B_78jmvM.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-w_3kpqbc.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-DZBxmKGR.js → cron-expression-BBheaBIr.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BNHd7HT7.js → date-picker-CDwj7UrT.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-D1kJBknt.js → dependency-picker-Dnrc2qZe.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Di75oHkC.js → desktop-pet-Bj_vUjXp.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-D6tD1uym.js → desktop-pet-settings-uiCwJJk4.js} +1 -1
- package/dist/gateway/static/root/assets/directory-picker-path-field-D0zUQ-TO.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-D91_S7NQ.js → extension-debug-page-_GZ4y2da.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DHzmmr_N.js → extension-page-scR96Edg.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BpJNtePi.js → extension-settings-page-CILsAwxx.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BAzLYTKZ.js → gateway-config-api-984O_4wM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-VVcfd3sG.js → gateway-config-swr-D4hvsdJA.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-C5-aKkTp.js → gateway-settings-aF4eQHo3.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-qAX_T2t2.js → gateway-startup-retry-Deo5-O87.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-D5DrFWH6.js +1 -0
- package/dist/gateway/static/root/assets/home-page-DiMWxngC.js +3 -0
- package/dist/gateway/static/root/assets/index-DzKLVgY-.js +85 -0
- package/dist/gateway/static/root/assets/index-wR5jX-lw.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-fpNjXnJK.js → keyboard-shortcuts-settings-DGmOlNcB.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-De8vuwu1.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DBpQIfNd.js → local-apps-page-CzS2sCxg.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-CbPVxonP.js → locale-store-C7xtkP3D.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BI9stsVO.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-CiK7Xkvi.js → management-settings-Cpxs43JB.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DVgpcOze.js → markdown-split-CQvFHxUa.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-Dl-0_9JR.js → markdown-view-BRwrSbwM.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DMj1lW-n.js → media-plugins-Bs9MsiaM.js} +1 -1
- package/dist/gateway/static/root/assets/messages-Dxk5Rzj_.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-DvX1sTlf.js → notes-page-Dux_g6aZ.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-CGafcgJ8.js +4 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DvsLigha.js → preview-open-alternatives-fvhtN4Y2.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DbCraAI3.js → product-open-page-f_jbg-9N.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-C6mNsjYr.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-D1G6VIxR.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CIez6X0x.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DzuUglQo.js → runtime-tools-settings-panel-zapSiJrv.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-plDnazVj.js → schema-form-CFyz8y5v.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-6irxQjHb.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CRb0QTG2.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BwAxX_7e.js → settings-form-section-DCiK4TIq.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-B3OiTnF9.js → settings-loading-skeleton-DFUJEv4G.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DvIWXBvp.js → settings-page-Cnp9Bdd0.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DThKKjLV.js → setup-status-panel-BFMGTGBO.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-CFnoGHJb.js → share-preview-page-DA8nA4cz.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CaKfvJzQ.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BOBUcYr5.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-B38fY22S.js → skills-page-BJJACxzz.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-vLIlk1c3.js → skills-page.utils--1-vOg3V.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DRV2wljT.js → system-settings-panel-DY0lIaXY.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-Ciuwe7AG.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-Bc_eRUev.js → theme-store-DoyRfkoi.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DTu23D9J.js → use-autosave-DzIR5Lxf.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-DCwqzN03.js → user-context-page-yf18T_BZ.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CVDMesWc.js → voice-api-key-field-B7MZS8tS.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-cyt93k0V.js → work-discovery-overlay-zyX6yxxF.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-page-2e5J0sIp.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-Cj1vPWRM.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-D37zWlWY.js +5 -0
- package/dist/gateway/static/root/assets/{working-directory-picker-modal-CYWdZUJ5.js → working-directory-picker-modal-Bm7cox3y.js} +1 -1
- package/dist/gateway/static/root/index.html +10 -10
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +11 -0
- package/dist/src/agent/agent-manager.js +36 -6
- package/dist/src/agent/embedded/transcript-runtime.d.ts +2 -1
- package/dist/src/agent/embedded/transcript-runtime.js +38 -4
- package/dist/src/agent/inbound/inbound-loop.d.ts +1 -1
- package/dist/src/agent/memory/compaction-ledger.d.ts +11 -0
- package/dist/src/agent/memory/compaction-ledger.js +108 -0
- package/dist/src/agent/memory/compaction-serializer.d.ts +2 -0
- package/dist/src/agent/memory/compaction-serializer.js +52 -0
- package/dist/src/agent/memory/compaction-source-planner.d.ts +20 -0
- package/dist/src/agent/memory/compaction-source-planner.js +67 -0
- package/dist/src/agent/memory/compaction.d.ts +11 -5
- package/dist/src/agent/memory/compaction.js +245 -153
- package/dist/src/agent/prompt/sections/behavior.js +1 -1
- package/dist/src/agent/prompt/sections/memory-skills.js +4 -2
- package/dist/src/agent/prompt/sections/tooling.js +2 -0
- package/dist/src/agent/service.d.ts +4 -1
- package/dist/src/agent/service.js +12 -0
- package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
- package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
- package/dist/src/agent/tools/factory.js +5 -0
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/session-recall-tool.d.ts +7 -0
- package/dist/src/agent/tools/session-recall-tool.js +82 -0
- package/dist/src/agent/tools/xopc-use-tool.js +6 -2
- package/dist/src/automations/api/routes.js +8 -0
- package/dist/src/automations/domain/index.js +2 -2
- package/dist/src/automations/domain/types.d.ts +17 -12
- package/dist/src/automations/domain/validation.d.ts +30 -32
- package/dist/src/automations/domain/validation.js +8 -10
- package/dist/src/automations/draft/automation-draft-prompt.js +9 -5
- package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -8
- package/dist/src/automations/draft/automation-draft-validator.js +3 -3
- package/dist/src/automations/index.js +2 -2
- package/dist/src/automations/service/action-executor.js +13 -4
- package/dist/src/automations/service/automation-service.d.ts +5 -1
- package/dist/src/automations/service/automation-service.js +19 -12
- package/dist/src/automations/storage/automation-repository.js +8 -4
- package/dist/src/automations/storage/automation-run-repository.d.ts +5 -0
- package/dist/src/automations/storage/automation-run-repository.js +24 -8
- package/dist/src/automations/storage/index.js +2 -2
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/schema.d.ts +1 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/automation-agent-session.d.ts +4 -0
- package/dist/src/gateway/automation-agent-session.js +40 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +3 -2
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
- package/dist/src/gateway/hono/routes/commands-skills.js +36 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
- package/dist/src/gateway/service/marketplace-service.d.ts +4 -1
- package/dist/src/gateway/service/marketplace-service.js +9 -0
- package/dist/src/gateway/service/run-gateway-agent.js +3 -3
- package/dist/src/gateway/service.js +19 -2
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/mobile/notification-service.js +7 -4
- package/dist/src/session/compaction-types.d.ts +30 -0
- package/dist/src/session/compaction-types.js +35 -0
- package/dist/src/session/manager.d.ts +3 -0
- package/dist/src/session/session-context-for-llm.d.ts +4 -2
- package/dist/src/session/session-context-for-llm.js +2 -1
- package/dist/src/session/store.d.ts +10 -1
- package/dist/src/session/store.js +55 -23
- package/dist/src/session/types.d.ts +3 -2
- 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/121_automation_inbox.sql +24 -0
- package/dist/src/storage/sqlite/migrations/122_automation_session_projects.sql +18 -0
- package/dist/src/storage/sqlite/migrations/123_remove_v2_compaction_boundaries.sql +25 -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/transcript-repository.d.ts +24 -1
- package/dist/src/storage/sqlite/transcript-repository.js +78 -29
- package/dist/src/user-context/config.d.ts +4 -0
- package/dist/src/user-context/config.js +2 -0
- package/package.json +4 -3
- package/skills/THIRD_PARTY_NOTICES.md +1 -1
- package/skills/engineering/define-task/SKILL.md +48 -0
- package/skills/engineering/define-task/references/task-contract-rubric.md +15 -0
- package/dist/gateway/static/root/assets/agents-DnFIy8Ye.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-CONlVc-f.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-DuG69tIj.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-Cvt-8fqE.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-yk3QkGBP.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DJjVOCJY.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-CaNnYUQo.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CZ5P9jbB.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DTpCnOsQ.js +0 -2
- package/dist/gateway/static/root/assets/directory-picker-path-field-Ly0TUflq.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CMZr1_Op.js +0 -1
- package/dist/gateway/static/root/assets/home-page-CBG9Bk-1.js +0 -3
- package/dist/gateway/static/root/assets/index-BBw9QL0p.js +0 -85
- package/dist/gateway/static/root/assets/index-Dm-cvIpl.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-Bi_0Sknt.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BmXcJCKz.js +0 -2
- package/dist/gateway/static/root/assets/messages-9zCa8KkW.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-CMyosgjY.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-DkS-kbpj.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B3NxP6S4.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DwhrMhjl.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BOfXXmBL.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-sPrZfZVR.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Dvl13Udt.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-D9elkZOz.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-Xd8PlB24.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page--DTi90d5.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-DrdcfX_N.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-DXyButkm.js +0 -5
- package/dist/src/agent/memory/compaction-planner.d.ts +0 -16
- package/dist/src/agent/memory/compaction-planner.js +0 -168
- package/dist/src/agent/memory/summary-generator.d.ts +0 -46
- package/dist/src/agent/memory/summary-generator.js +0 -229
- package/skills/engineering/define-goal/SKILL.md +0 -41
- package/skills/engineering/define-goal/references/objective-rubric.md +0 -12
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* {@link buildSessionContextForLlm} first (or use {@link SessionStore.loadMessages}, which already does).
|
|
7
7
|
*/
|
|
8
8
|
import type { AgentMessage } from '@earendil-works/pi-agent-core';
|
|
9
|
+
import { type CompactionAudit, type CompactionHandover } from './compaction-types.js';
|
|
9
10
|
/** Persisted-only row: never sent to the model as a chat message. */
|
|
10
11
|
export interface XopcTranscriptContextEntry {
|
|
11
12
|
kind: 'context';
|
|
@@ -73,15 +74,16 @@ export interface XopcTranscriptCompactionEntry {
|
|
|
73
74
|
type: 'compaction';
|
|
74
75
|
at: string;
|
|
75
76
|
baseSeq: number;
|
|
76
|
-
plannerVersion:
|
|
77
|
+
plannerVersion: 3;
|
|
77
78
|
summaryModelRef: string;
|
|
78
79
|
qualityAudit: 'passed' | 'disabled';
|
|
80
|
+
handover: CompactionHandover;
|
|
81
|
+
audit: CompactionAudit;
|
|
79
82
|
summary: string;
|
|
80
83
|
messages: AgentMessage[];
|
|
81
84
|
firstKeptIndex: number;
|
|
82
85
|
tokensBefore: number;
|
|
83
86
|
tokensAfter: number;
|
|
84
|
-
restoredFromCompactionId?: string;
|
|
85
87
|
}
|
|
86
88
|
/** Persisted label change for a transcript entry. */
|
|
87
89
|
export interface XopcTranscriptLabelEntry {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCompactionAudit, isCompactionHandover } from "./compaction-types.js";
|
|
1
2
|
//#region src/session/session-context-for-llm.ts
|
|
2
3
|
function isTranscriptContextEntry(x) {
|
|
3
4
|
if (!x || typeof x !== "object") return false;
|
|
@@ -24,7 +25,7 @@ function isTranscriptSummaryMessageEntry(x) {
|
|
|
24
25
|
function isTranscriptCompactionEntry(x) {
|
|
25
26
|
if (!x || typeof x !== "object") return false;
|
|
26
27
|
const row = x;
|
|
27
|
-
return row.type === "compaction" && typeof row.at === "string" && typeof row.baseSeq === "number" && Number.isInteger(row.baseSeq) &&
|
|
28
|
+
return row.type === "compaction" && typeof row.at === "string" && typeof row.baseSeq === "number" && Number.isInteger(row.baseSeq) && row.plannerVersion === 3 && typeof row.summaryModelRef === "string" && (row.qualityAudit === "passed" || row.qualityAudit === "disabled") && typeof row.summary === "string" && isCompactionHandover(row.handover) && isCompactionAudit(row.audit) && Array.isArray(row.messages) && typeof row.firstKeptIndex === "number" && typeof row.tokensBefore === "number" && typeof row.tokensAfter === "number";
|
|
28
29
|
}
|
|
29
30
|
function isTranscriptLabelEntry(x) {
|
|
30
31
|
if (!x || typeof x !== "object") return false;
|
|
@@ -32,11 +32,13 @@ export declare class SessionStore {
|
|
|
32
32
|
private window;
|
|
33
33
|
private compactor;
|
|
34
34
|
private compactionHooks;
|
|
35
|
+
private readonly compactionTails;
|
|
35
36
|
constructor(options: SessionStoreOptions, windowConfig?: Partial<WindowConfig>, compactionConfig?: Partial<CompactionConfig>);
|
|
36
37
|
setCompactionHooks(hooks: SessionCompactionHooks): void;
|
|
37
38
|
private runCompactionHook;
|
|
38
39
|
private resolveWorkspaceCwd;
|
|
39
40
|
private runStoreMutation;
|
|
41
|
+
private runCompactionExclusive;
|
|
40
42
|
initialize(): Promise<void>;
|
|
41
43
|
getSessionsRoot(): string;
|
|
42
44
|
resolveTranscriptPath(sessionKey: string, options?: {
|
|
@@ -142,12 +144,15 @@ export declare class SessionStore {
|
|
|
142
144
|
tool: number;
|
|
143
145
|
needsTrim: boolean;
|
|
144
146
|
};
|
|
145
|
-
applyCompaction(key: string,
|
|
147
|
+
applyCompaction(key: string, result: CompactionResult, expectedSnapshot?: import("../storage/sqlite/transcript-repository.js").CompactionSourceSnapshot): Promise<AgentMessage[]>;
|
|
146
148
|
compact(key: string, messages: AgentMessage[], model: Model<Api>, instructions?: string, force?: boolean, executionOptions?: CompactionExecutionOptions): Promise<CompactionResult>;
|
|
147
149
|
getCompactionStats(key: string): Promise<{
|
|
148
150
|
compactionCount: number;
|
|
149
151
|
totalTokensBefore: number;
|
|
150
152
|
totalTokensAfter: number;
|
|
153
|
+
auditPassedCount: number;
|
|
154
|
+
auditDegradedCount: number;
|
|
155
|
+
auditMissingItemsFound: number;
|
|
151
156
|
lastCompactionAt: string;
|
|
152
157
|
}>;
|
|
153
158
|
listCompactionBoundaries(key: string): Promise<CompactionBoundarySummary[]>;
|
|
@@ -158,6 +163,10 @@ export declare class SessionStore {
|
|
|
158
163
|
}): Promise<AgentMessage[]>;
|
|
159
164
|
estimateTokenUsage(_key: string, messages: AgentMessage[]): Promise<number>;
|
|
160
165
|
searchInSession(key: string, keyword: string): Promise<Message[]>;
|
|
166
|
+
recallSession(key: string, query: string, options?: {
|
|
167
|
+
limit?: number;
|
|
168
|
+
beforeSeq?: number;
|
|
169
|
+
}): import("../storage/sqlite/transcript-repository.js").SessionTranscriptRecallMatch[];
|
|
161
170
|
exportSession(key: string, format: ExportFormat): Promise<string>;
|
|
162
171
|
importSessionExport(targetKey: string, jsonContent: string): Promise<{
|
|
163
172
|
sessionKey: string;
|
|
@@ -6,7 +6,7 @@ import "./types.js";
|
|
|
6
6
|
import { buildSessionContextForLlm, buildSessionDisplayMessages, isRuntimeOnlyTranscriptMessage, isTranscriptCompactionEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray } from "./session-context-for-llm.js";
|
|
7
7
|
import { estimateTokensFromMessages } from "../storage/sqlite/row-mappers.js";
|
|
8
8
|
import { deleteSessionRecord, ensureSessionRecord, findSessionKeyBySessionId, getGlobalSessionStats, getSessionMetadata, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord } from "../storage/sqlite/session-repository.js";
|
|
9
|
-
import {
|
|
9
|
+
import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "../storage/sqlite/transcript-repository.js";
|
|
10
10
|
import "../storage/sqlite/index.js";
|
|
11
11
|
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
12
12
|
import { readPostCompactionContext } from "../agent/reply/post-compaction-context.js";
|
|
@@ -35,6 +35,7 @@ var SessionStore = class {
|
|
|
35
35
|
window;
|
|
36
36
|
compactor;
|
|
37
37
|
compactionHooks = {};
|
|
38
|
+
compactionTails = /* @__PURE__ */ new Map();
|
|
38
39
|
constructor(options, windowConfig, compactionConfig) {
|
|
39
40
|
this.options = options;
|
|
40
41
|
this.window = new SlidingWindow(windowConfig);
|
|
@@ -64,6 +65,21 @@ var SessionStore = class {
|
|
|
64
65
|
async runStoreMutation(fn) {
|
|
65
66
|
return fn();
|
|
66
67
|
}
|
|
68
|
+
async runCompactionExclusive(sessionKey, fn) {
|
|
69
|
+
const previous = this.compactionTails.get(sessionKey) ?? Promise.resolve();
|
|
70
|
+
let release;
|
|
71
|
+
const current = new Promise((resolve) => {
|
|
72
|
+
release = resolve;
|
|
73
|
+
});
|
|
74
|
+
this.compactionTails.set(sessionKey, current);
|
|
75
|
+
await previous;
|
|
76
|
+
try {
|
|
77
|
+
return await fn();
|
|
78
|
+
} finally {
|
|
79
|
+
release();
|
|
80
|
+
if (this.compactionTails.get(sessionKey) === current) this.compactionTails.delete(sessionKey);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
67
83
|
async initialize() {
|
|
68
84
|
requireXopcDatabase();
|
|
69
85
|
log.debug("Session store initialized (SQLite)");
|
|
@@ -297,12 +313,13 @@ var SessionStore = class {
|
|
|
297
313
|
plannerVersion: row.plannerVersion,
|
|
298
314
|
summaryModelRef: row.summaryModelRef,
|
|
299
315
|
qualityAudit: row.qualityAudit,
|
|
316
|
+
handover: row.handover,
|
|
317
|
+
audit: row.audit,
|
|
300
318
|
summary: row.summary,
|
|
301
319
|
messages: row.messages,
|
|
302
320
|
firstKeptIndex: row.firstKeptIndex,
|
|
303
321
|
tokensBefore: row.tokensBefore,
|
|
304
|
-
tokensAfter: row.tokensAfter
|
|
305
|
-
restoredFromCompactionId: row.restoredFromCompactionId
|
|
322
|
+
tokensAfter: row.tokensAfter
|
|
306
323
|
});
|
|
307
324
|
return {
|
|
308
325
|
type: "xopc_session_transcript",
|
|
@@ -419,21 +436,25 @@ var SessionStore = class {
|
|
|
419
436
|
getWindowStats(messages) {
|
|
420
437
|
return this.window.getStats(messages);
|
|
421
438
|
}
|
|
422
|
-
async applyCompaction(key,
|
|
423
|
-
|
|
439
|
+
async applyCompaction(key, result, expectedSnapshot = loadCompactionSourceSnapshot(key)) {
|
|
440
|
+
if (!expectedSnapshot) throw new Error(`Session not found: ${key}`);
|
|
441
|
+
if (!result.compacted || !result.handover || !result.audit) throw new Error("Cannot persist an incomplete compaction result");
|
|
442
|
+
const compacted = result.messages;
|
|
424
443
|
return this.runStoreMutation(async () => {
|
|
425
|
-
|
|
444
|
+
if (!appendCompactionBoundaryIfUnchanged(key, expectedSnapshot, {
|
|
426
445
|
type: "compaction",
|
|
427
446
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
428
|
-
plannerVersion:
|
|
447
|
+
plannerVersion: 3,
|
|
429
448
|
summaryModelRef: result.summaryModelRef ?? "unknown",
|
|
430
449
|
qualityAudit: result.qualityAudit ?? "disabled",
|
|
450
|
+
handover: result.handover,
|
|
451
|
+
audit: result.audit,
|
|
431
452
|
summary: result.summary,
|
|
432
453
|
messages: compacted,
|
|
433
454
|
firstKeptIndex: result.firstKeptIndex,
|
|
434
455
|
tokensBefore: result.tokensBefore,
|
|
435
456
|
tokensAfter: result.tokensAfter
|
|
436
|
-
});
|
|
457
|
+
})) throw new Error(`Session changed while compaction was running: ${key}`);
|
|
437
458
|
log.info({
|
|
438
459
|
key,
|
|
439
460
|
tokensBefore: result.tokensBefore,
|
|
@@ -445,23 +466,27 @@ var SessionStore = class {
|
|
|
445
466
|
});
|
|
446
467
|
}
|
|
447
468
|
async compact(key, messages, model, instructions, force, executionOptions) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
});
|
|
454
|
-
const result = await this.compactor.compact(messages, model, instructions, force, executionOptions);
|
|
455
|
-
if (result.compacted) {
|
|
456
|
-
const compacted = await this.applyCompaction(key, messages, result);
|
|
457
|
-
await this.runCompactionHook("after", {
|
|
469
|
+
return this.runCompactionExclusive(key, async () => {
|
|
470
|
+
const snapshot = loadCompactionSourceSnapshot(key);
|
|
471
|
+
if (!snapshot) throw new Error(`Session not found: ${key}`);
|
|
472
|
+
const tokenCount = this.estimateTokens(messages);
|
|
473
|
+
await this.runCompactionHook("before", {
|
|
458
474
|
sessionKey: key,
|
|
459
|
-
messageCount:
|
|
460
|
-
tokenCount
|
|
461
|
-
compactedCount: Math.max(0, Math.min(messages.length, result.firstKeptIndex))
|
|
475
|
+
messageCount: messages.length,
|
|
476
|
+
tokenCount
|
|
462
477
|
});
|
|
463
|
-
|
|
464
|
-
|
|
478
|
+
const result = await this.compactor.compact(snapshot.entries, model, instructions, force, executionOptions);
|
|
479
|
+
if (result.compacted) {
|
|
480
|
+
const compacted = await this.applyCompaction(key, result, snapshot);
|
|
481
|
+
await this.runCompactionHook("after", {
|
|
482
|
+
sessionKey: key,
|
|
483
|
+
messageCount: compacted.length,
|
|
484
|
+
tokenCount: result.tokensAfter,
|
|
485
|
+
compactedCount: Math.max(0, Math.min(messages.length, result.firstKeptIndex))
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
return result;
|
|
489
|
+
});
|
|
465
490
|
}
|
|
466
491
|
async getCompactionStats(key) {
|
|
467
492
|
if (!await this.getMetadata(key)) return void 0;
|
|
@@ -470,6 +495,9 @@ var SessionStore = class {
|
|
|
470
495
|
compactionCount: boundaries.length,
|
|
471
496
|
totalTokensBefore: boundaries.reduce((sum, boundary) => sum + boundary.tokensBefore, 0),
|
|
472
497
|
totalTokensAfter: boundaries.reduce((sum, boundary) => sum + boundary.tokensAfter, 0),
|
|
498
|
+
auditPassedCount: boundaries.filter((boundary) => boundary.audit.status === "passed").length,
|
|
499
|
+
auditDegradedCount: boundaries.filter((boundary) => boundary.audit.status === "degraded").length,
|
|
500
|
+
auditMissingItemsFound: boundaries.reduce((sum, boundary) => sum + boundary.audit.missingItemsFound, 0),
|
|
473
501
|
lastCompactionAt: boundaries[0]?.createdAt
|
|
474
502
|
};
|
|
475
503
|
}
|
|
@@ -498,6 +526,10 @@ var SessionStore = class {
|
|
|
498
526
|
const q = keyword.toLowerCase();
|
|
499
527
|
return this.convertMessages(messages.filter((m) => this.extractTextContent(this.messageContent(m)).toLowerCase().includes(q)));
|
|
500
528
|
}
|
|
529
|
+
recallSession(key, query, options) {
|
|
530
|
+
requireXopcDatabase();
|
|
531
|
+
return searchSessionTranscript(key, query, options);
|
|
532
|
+
}
|
|
501
533
|
async exportSession(key, format) {
|
|
502
534
|
const metadata = await this.getMetadata(key);
|
|
503
535
|
if (!metadata) throw new Error(`Session not found: ${key}`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CompactionAudit } from './compaction-types.js';
|
|
1
2
|
import type { TranscriptStoredRow } from './session-context-for-llm.js';
|
|
2
3
|
export interface Message {
|
|
3
4
|
role: 'system' | 'user' | 'assistant' | 'tool' | 'toolResult';
|
|
@@ -174,7 +175,7 @@ export interface SessionExport {
|
|
|
174
175
|
/** Full on-disk rows (LLM + `kind: 'context'`) for audit / round-trip. */
|
|
175
176
|
transcriptRows: TranscriptStoredRow[];
|
|
176
177
|
}
|
|
177
|
-
/** Append-only context boundary produced by compaction
|
|
178
|
+
/** Append-only context boundary produced by compaction. */
|
|
178
179
|
export interface CompactionBoundarySummary {
|
|
179
180
|
id: string;
|
|
180
181
|
seq: number;
|
|
@@ -183,5 +184,5 @@ export interface CompactionBoundarySummary {
|
|
|
183
184
|
tokensBefore: number;
|
|
184
185
|
tokensAfter: number;
|
|
185
186
|
summaryPreview: string;
|
|
186
|
-
|
|
187
|
+
audit: CompactionAudit;
|
|
187
188
|
}
|
|
@@ -20,7 +20,7 @@ export { buildRelationshipPrompt, getRelationshipSettings, isProactiveSupportAll
|
|
|
20
20
|
export { buildDefaultSessionMetadata, type SessionMetadataSeed, } from './session-metadata.js';
|
|
21
21
|
export { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow, type SessionConfigRow, type SessionRow, type TranscriptEntryRow, } from './row-mappers.js';
|
|
22
22
|
export { deleteSessionRecord, ensureSessionRecord, getCurrentSessionId, getGlobalSessionStats, findSessionKeyBySessionId, getSessionPersistedLevels, getSessionMetadata, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord, resolveSessionAgentId, updateSessionStats, } from './session-repository.js';
|
|
23
|
-
export {
|
|
23
|
+
export { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, loadCompactionSourceSnapshot, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript, type CompactionSourceSnapshot, type SessionTranscriptRecallMatch, type TranscriptSourceEntry, } from './transcript-repository.js';
|
|
24
24
|
export { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord, } from './notes-repository.js';
|
|
25
25
|
export { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgentContextRecord, type NoteAgentContextRecord, } from './note-agent-context-repository.js';
|
|
26
26
|
export { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryTurnFeedback, getMemoryRecord, hasUnresolvedMemoryConflict, listMemorySignals, listMemoryTraceEvents, listMemoryRecords, markMemoryRecordsConflicted, searchMemoryRecords, setMemoryRecordStatus, setMemoryProviderState, setMemoryTurnFeedback, summarizeMemoryRecallFeedback, upsertMemoryRecord, type AppendMemorySignalInput, type AppendMemoryTraceEventInput, type ListMemoryRecordsOptions, type MemoryRecallFeedbackSummary, type MemorySignalRowPayload, type MemoryFeedback, type MemoryFeedbackRating, type MemoryTraceEventPayload, type SearchMemoryRecordsOptions, type SetMemoryTurnFeedbackInput, type UpsertMemoryRecordInput, } from './memory-records-repository.js';
|
|
@@ -21,7 +21,7 @@ import { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages,
|
|
|
21
21
|
import { deleteSessionRecord, ensureSessionRecord, findSessionKeyBySessionId, getCurrentSessionId, getGlobalSessionStats, getSessionMetadata, getSessionPersistedLevels, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord, resolveSessionAgentId, updateSessionStats } from "./session-repository.js";
|
|
22
22
|
import { getSessionTaskPlan, setSessionTaskPlan } from "./session-task-plan-repository.js";
|
|
23
23
|
import { buildRelationshipPrompt, getRelationshipSettings, isProactiveSupportAllowed, updateRelationshipSettings } from "./relationship-settings-repository.js";
|
|
24
|
-
import {
|
|
24
|
+
import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "./transcript-repository.js";
|
|
25
25
|
import { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord } from "./notes-repository.js";
|
|
26
26
|
import { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgentContextRecord } from "./note-agent-context-repository.js";
|
|
27
27
|
import { attachMemoryEvidence, claimKnowledgeSourceItems, completeKnowledgeSourceItemSynthesis, deleteMemoryEvidenceForRecord, finishKnowledgeSyncRun, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listMemoryEvidence, pruneBoundedKnowledgeSourceItems, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, startKnowledgeSyncRun, upsertKnowledgeSourceItems } from "./knowledge-repository.js";
|
|
@@ -32,4 +32,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
|
|
|
32
32
|
import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
|
|
33
33
|
import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
|
|
34
34
|
import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
|
|
35
|
-
export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention,
|
|
35
|
+
export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendMemorySignal, appendMemoryTraceEvent, appendTranscriptEntry, applyPendingMigrations, attachMemoryEvidence, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeConnectorApproval, consumeContextConsent, createCollaborationRule, createConnectorApproval, createContextEvidence, createEndpointPrincipal, createObjectLinkRecord, createUnderstanding, decideConnectorApproval, decideContextConsent, deleteCollaborationRule, deleteConnectorConnection, deleteConnectorInstallation, deleteMemoryEvidenceForRecord, deleteMemoryRecord, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, deleteUnderstanding, discoverSqlMigrations, enqueueConnectorLearningJob, ensureContextConsent, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextConsolidationRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActivityEventRecord, getCachedConnectorCatalogEntry, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextConsolidationRun, getCurrentSessionId, getEndpointPrincipal, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getMemoryProviderState, getMemoryRecord, getMemoryTurnFeedback, getNoteAgentContextRecord, getNoteRecord, getRelationshipSettings, getSessionConfig, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getTurnPersonalization, getUnderstanding, getUserProfile, getUserTrustPolicy, getXopcDatabase, hasContextConsent, hasSessionConfig, hasUnresolvedMemoryConflict, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isUnderstandingSuppressed, isXopcDatabaseOpen, linkUnderstandingEvidence, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextConsolidationDecisions, listContextConsolidationRuns, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listMemoryEvidence, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listUnderstandingEvidence, listUnderstandings, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, markMemoryRecordsConflicted, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recordContextConsolidationDecision, recordContextFeedback, recordContextRun, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, rejectUnderstanding, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceTranscriptRows, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, reviseCollaborationRule, reviseUnderstanding, revokeEndpointPrincipal, runSqliteWriteTransaction, searchMemoryRecords, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setMemoryProviderState, setMemoryRecordStatus, setMemoryTurnFeedback, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUnderstandingStatus, setUserTrustPolicy, startContextConsolidationRun, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeMemoryRecallFeedback, summarizeUserUnderstandingQuality, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserProfile, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertMemoryRecord, upsertNoteAgentContextRecord, upsertNoteRecord };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
ALTER TABLE automations ADD COLUMN conversation_mode TEXT NOT NULL DEFAULT 'new_session'
|
|
2
|
+
CHECK (conversation_mode IN ('new_session', 'continuous'));
|
|
3
|
+
ALTER TABLE automations ADD COLUMN notification_policy TEXT NOT NULL DEFAULT 'attention'
|
|
4
|
+
CHECK (notification_policy IN ('attention', 'all', 'none'));
|
|
5
|
+
ALTER TABLE automations ADD COLUMN completion_webhook_url TEXT;
|
|
6
|
+
|
|
7
|
+
UPDATE automations
|
|
8
|
+
SET completion_webhook_url = json_extract(after_run_json, '$.url')
|
|
9
|
+
WHERE json_extract(after_run_json, '$.kind') = 'webhook';
|
|
10
|
+
|
|
11
|
+
ALTER TABLE automations DROP COLUMN after_run_json;
|
|
12
|
+
|
|
13
|
+
UPDATE automation_runs
|
|
14
|
+
SET current_phase = 'completion_hook'
|
|
15
|
+
WHERE current_phase = 'after_run';
|
|
16
|
+
|
|
17
|
+
UPDATE automation_run_events
|
|
18
|
+
SET type = replace(type, 'after_run.', 'completion_hook.'),
|
|
19
|
+
message = replace(message, 'After-run webhook', 'Completion webhook')
|
|
20
|
+
WHERE type LIKE 'after_run.%';
|
|
21
|
+
|
|
22
|
+
ALTER TABLE automation_runs ADD COLUMN read_at_ms INTEGER;
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_automation_runs_unread_created
|
|
24
|
+
ON automation_runs(read_at_ms, created_at_ms DESC);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
UPDATE sessions
|
|
2
|
+
SET project_id = (
|
|
3
|
+
SELECT a.project_id
|
|
4
|
+
FROM automation_runs r
|
|
5
|
+
JOIN automations a ON a.automation_id = r.automation_id
|
|
6
|
+
WHERE r.session_key = sessions.session_key
|
|
7
|
+
AND a.project_id IS NOT NULL
|
|
8
|
+
ORDER BY r.created_at_ms DESC
|
|
9
|
+
LIMIT 1
|
|
10
|
+
)
|
|
11
|
+
WHERE project_id IS NULL
|
|
12
|
+
AND EXISTS (
|
|
13
|
+
SELECT 1
|
|
14
|
+
FROM automation_runs r
|
|
15
|
+
JOIN automations a ON a.automation_id = r.automation_id
|
|
16
|
+
WHERE r.session_key = sessions.session_key
|
|
17
|
+
AND a.project_id IS NOT NULL
|
|
18
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
DELETE FROM transcript_fts
|
|
2
|
+
WHERE entry_id IN (
|
|
3
|
+
SELECT entry_id
|
|
4
|
+
FROM transcript_entries
|
|
5
|
+
WHERE entry_kind = 'compaction'
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
DELETE FROM transcript_entries
|
|
9
|
+
WHERE entry_kind = 'compaction';
|
|
10
|
+
|
|
11
|
+
UPDATE sessions
|
|
12
|
+
SET
|
|
13
|
+
compacted_count = 0,
|
|
14
|
+
message_count = (
|
|
15
|
+
SELECT COUNT(*)
|
|
16
|
+
FROM transcript_entries e
|
|
17
|
+
WHERE e.session_id = sessions.session_id
|
|
18
|
+
AND e.entry_kind = 'message'
|
|
19
|
+
),
|
|
20
|
+
estimated_tokens = (
|
|
21
|
+
SELECT COALESCE(SUM((length(COALESCE(json_extract(e.payload_json, '$.content'), '')) + 3) / 4), 0)
|
|
22
|
+
FROM transcript_entries e
|
|
23
|
+
WHERE e.session_id = sessions.session_id
|
|
24
|
+
AND e.entry_kind = 'message'
|
|
25
|
+
);
|
|
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
|
|
|
3
3
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
4
4
|
export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
5
5
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
6
|
-
export declare const XOPC_DB_SCHEMA_VERSION =
|
|
6
|
+
export declare const XOPC_DB_SCHEMA_VERSION = 123;
|
|
7
7
|
export declare function resolveMigrationsDir(override?: string): string;
|
|
8
8
|
/**
|
|
9
9
|
* Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
|
|
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
|
|
|
12
12
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
13
13
|
const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
14
14
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
15
|
-
const XOPC_DB_SCHEMA_VERSION =
|
|
15
|
+
const XOPC_DB_SCHEMA_VERSION = 123;
|
|
16
16
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
function backupBeforeTaskCutover(db, databasePath) {
|
|
18
18
|
db.exec("PRAGMA wal_checkpoint(FULL)");
|
|
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
|
|
|
57
57
|
* Each step runs in its own transaction and updates schema_meta on success.
|
|
58
58
|
*/
|
|
59
59
|
function applyPendingMigrations(db, options = {}) {
|
|
60
|
-
const targetVersion = options.targetVersion ??
|
|
60
|
+
const targetVersion = options.targetVersion ?? 123;
|
|
61
61
|
let currentVersion = readSchemaVersion(db);
|
|
62
62
|
if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
|
|
63
63
|
if (currentVersion >= targetVersion) return currentVersion;
|
|
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
|
|
|
94
94
|
}
|
|
95
95
|
/** Inspect schema version without mutating the database. */
|
|
96
96
|
function inspectSchemaMigrationStatus(db, options = {}) {
|
|
97
|
-
const appVersion = options.targetVersion ??
|
|
97
|
+
const appVersion = options.targetVersion ?? 123;
|
|
98
98
|
const dbVersion = readSchemaVersion(db);
|
|
99
99
|
if (dbVersion > appVersion) return {
|
|
100
100
|
dbVersion,
|
|
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
|
|
|
19
19
|
export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
20
20
|
|
|
21
21
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
22
|
-
export const XOPC_DB_SCHEMA_VERSION =
|
|
22
|
+
export const XOPC_DB_SCHEMA_VERSION = 123;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
|
@@ -2,11 +2,34 @@ import type { AgentMessage } from '@earendil-works/pi-agent-core';
|
|
|
2
2
|
import type { CompactionBoundarySummary } from '../../session/types.js';
|
|
3
3
|
import { type TranscriptStoredRow, type XopcTranscriptCompactionEntry } from '../../session/session-context-for-llm.js';
|
|
4
4
|
import { type TranscriptEntryRow } from './row-mappers.js';
|
|
5
|
+
export interface TranscriptSourceEntry {
|
|
6
|
+
entryId: string;
|
|
7
|
+
seq: number;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
row: TranscriptStoredRow;
|
|
10
|
+
}
|
|
11
|
+
export interface CompactionSourceSnapshot {
|
|
12
|
+
sessionId: string;
|
|
13
|
+
lastSeq: number;
|
|
14
|
+
entries: TranscriptSourceEntry[];
|
|
15
|
+
}
|
|
16
|
+
export interface SessionTranscriptRecallMatch {
|
|
17
|
+
entryId: string;
|
|
18
|
+
seq: number;
|
|
19
|
+
role: string | null;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
content: string;
|
|
22
|
+
}
|
|
5
23
|
export declare function appendTranscriptEntry(sessionKey: string, row: TranscriptStoredRow, opts?: {
|
|
6
24
|
sessionId?: string;
|
|
7
25
|
tokenDelta?: number;
|
|
8
26
|
}): TranscriptEntryRow;
|
|
9
|
-
export declare function
|
|
27
|
+
export declare function appendCompactionBoundaryIfUnchanged(sessionKey: string, expected: Pick<CompactionSourceSnapshot, 'sessionId' | 'lastSeq'>, row: Omit<XopcTranscriptCompactionEntry, 'baseSeq'>): TranscriptEntryRow | null;
|
|
28
|
+
export declare function loadCompactionSourceSnapshot(sessionKey: string): CompactionSourceSnapshot | null;
|
|
29
|
+
export declare function searchSessionTranscript(sessionKey: string, query: string, options?: {
|
|
30
|
+
limit?: number;
|
|
31
|
+
beforeSeq?: number;
|
|
32
|
+
}): SessionTranscriptRecallMatch[];
|
|
10
33
|
export declare function loadTranscriptRowsForSession(sessionKey: string): TranscriptStoredRow[];
|
|
11
34
|
export declare function loadTranscriptHistoryRowsForSession(sessionKey: string): TranscriptStoredRow[];
|
|
12
35
|
export declare function loadTranscriptRows(sessionId: string): TranscriptStoredRow[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
2
|
import { buildSessionContextForLlm, isRuntimeOnlyTranscriptMessage } from "../../session/session-context-for-llm.js";
|
|
3
3
|
import { classifyStoredRow, estimateTokensFromMessages, extractFtsContent, transcriptEntryRowToStoredRow } from "./row-mappers.js";
|
|
4
|
+
import { escapeFts5Query } from "./fts.js";
|
|
4
5
|
import { getCurrentSessionId, readCurrentSessionId } from "./session-repository.js";
|
|
5
6
|
import { randomUUID } from "node:crypto";
|
|
6
7
|
//#region src/storage/sqlite/transcript-repository.ts
|
|
@@ -58,13 +59,15 @@ function appendTranscriptEntry(sessionKey, row, opts) {
|
|
|
58
59
|
return inserted;
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
|
-
function
|
|
62
|
+
function appendCompactionBoundaryIfUnchanged(sessionKey, expected, row) {
|
|
62
63
|
return runSqliteWriteTransaction((db) => {
|
|
63
64
|
const sessionId = readCurrentSessionId(db, sessionKey);
|
|
64
65
|
if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
|
|
66
|
+
if (sessionId !== expected.sessionId) return null;
|
|
67
|
+
if (nextSeq(db, sessionId) - 1 !== expected.lastSeq) return null;
|
|
65
68
|
const boundary = {
|
|
66
69
|
...row,
|
|
67
|
-
baseSeq:
|
|
70
|
+
baseSeq: expected.lastSeq
|
|
68
71
|
};
|
|
69
72
|
const inserted = insertEntry(db, {
|
|
70
73
|
sessionId,
|
|
@@ -83,6 +86,65 @@ function appendCompactionBoundary(sessionKey, row) {
|
|
|
83
86
|
return inserted;
|
|
84
87
|
});
|
|
85
88
|
}
|
|
89
|
+
function loadCompactionSourceSnapshot(sessionKey) {
|
|
90
|
+
const db = getSqliteDatabase();
|
|
91
|
+
const sessionId = getCurrentSessionId(sessionKey);
|
|
92
|
+
if (!sessionId) return null;
|
|
93
|
+
const rows = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
|
|
94
|
+
FROM transcript_entries
|
|
95
|
+
WHERE session_id = ?
|
|
96
|
+
ORDER BY seq ASC`).all(sessionId);
|
|
97
|
+
return {
|
|
98
|
+
sessionId,
|
|
99
|
+
lastSeq: rows.at(-1)?.seq ?? 0,
|
|
100
|
+
entries: rows.map((entry) => ({
|
|
101
|
+
entryId: entry.entry_id,
|
|
102
|
+
seq: entry.seq,
|
|
103
|
+
createdAt: entry.created_at,
|
|
104
|
+
row: transcriptEntryRowToStoredRow(entry)
|
|
105
|
+
}))
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function searchSessionTranscript(sessionKey, query, options = {}) {
|
|
109
|
+
const sessionId = getCurrentSessionId(sessionKey);
|
|
110
|
+
const normalized = query.trim();
|
|
111
|
+
if (!sessionId || !normalized) return [];
|
|
112
|
+
const limit = Math.min(20, Math.max(1, options.limit ?? 8));
|
|
113
|
+
const beforeSeq = options.beforeSeq ?? Number.MAX_SAFE_INTEGER;
|
|
114
|
+
const db = getSqliteDatabase();
|
|
115
|
+
const ftsRows = db.prepare(`SELECT e.entry_id, e.seq, e.role, e.created_at, f.content
|
|
116
|
+
FROM transcript_fts f
|
|
117
|
+
JOIN transcript_entries e
|
|
118
|
+
ON e.session_id = f.session_id AND e.entry_id = f.entry_id
|
|
119
|
+
WHERE transcript_fts MATCH ?
|
|
120
|
+
AND f.session_id = ?
|
|
121
|
+
AND e.entry_kind <> 'compaction'
|
|
122
|
+
AND e.seq < ?
|
|
123
|
+
ORDER BY bm25(transcript_fts), e.seq DESC
|
|
124
|
+
LIMIT ?`).all(escapeFts5Query(normalized), sessionId, beforeSeq, limit);
|
|
125
|
+
const escapedLike = normalized.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
|
|
126
|
+
const literalRows = db.prepare(`SELECT entry_id, seq, role, created_at, payload_json AS content
|
|
127
|
+
FROM transcript_entries
|
|
128
|
+
WHERE session_id = ?
|
|
129
|
+
AND entry_kind <> 'compaction'
|
|
130
|
+
AND seq < ?
|
|
131
|
+
AND payload_json LIKE ? ESCAPE '\\'
|
|
132
|
+
ORDER BY seq DESC
|
|
133
|
+
LIMIT ?`).all(sessionId, beforeSeq, `%${escapedLike}%`, limit);
|
|
134
|
+
const seen = /* @__PURE__ */ new Set();
|
|
135
|
+
return [...ftsRows, ...literalRows].flatMap((row) => {
|
|
136
|
+
const result = row;
|
|
137
|
+
if (seen.has(result.entry_id)) return [];
|
|
138
|
+
seen.add(result.entry_id);
|
|
139
|
+
return [{
|
|
140
|
+
entryId: result.entry_id,
|
|
141
|
+
seq: result.seq,
|
|
142
|
+
role: result.role,
|
|
143
|
+
createdAt: result.created_at,
|
|
144
|
+
content: result.content
|
|
145
|
+
}];
|
|
146
|
+
}).slice(0, limit);
|
|
147
|
+
}
|
|
86
148
|
function loadTranscriptRowsForSession(sessionKey) {
|
|
87
149
|
const sessionId = getCurrentSessionId(sessionKey);
|
|
88
150
|
if (!sessionId) return [];
|
|
@@ -210,7 +272,7 @@ function listCompactionBoundaries(sessionKey) {
|
|
|
210
272
|
tokensBefore: payload.tokensBefore,
|
|
211
273
|
tokensAfter: payload.tokensAfter,
|
|
212
274
|
summaryPreview: payload.summary.slice(0, 500),
|
|
213
|
-
|
|
275
|
+
audit: payload.audit
|
|
214
276
|
};
|
|
215
277
|
});
|
|
216
278
|
}
|
|
@@ -221,42 +283,29 @@ function restoreBeforeCompactionBoundary(sessionKey, compactionId) {
|
|
|
221
283
|
const boundary = db.prepare(`SELECT seq FROM transcript_entries
|
|
222
284
|
WHERE session_id = ? AND entry_id = ? AND entry_kind = 'compaction'`).get(sessionId, compactionId);
|
|
223
285
|
if (!boundary) throw new Error(`Compaction boundary not found: ${compactionId}`);
|
|
224
|
-
const
|
|
286
|
+
const removedEntryIds = db.prepare(`SELECT entry_id
|
|
287
|
+
FROM transcript_entries
|
|
288
|
+
WHERE session_id = ? AND seq >= ?`).all(sessionId, boundary.seq);
|
|
289
|
+
for (const entry of removedEntryIds) db.prepare(`DELETE FROM transcript_fts WHERE entry_id = ?`).run(entry.entry_id);
|
|
290
|
+
db.prepare(`DELETE FROM transcript_entries WHERE session_id = ? AND seq >= ?`).run(sessionId, boundary.seq);
|
|
291
|
+
const remainingEntries = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
|
|
225
292
|
FROM transcript_entries
|
|
226
|
-
WHERE session_id = ?
|
|
227
|
-
ORDER BY seq ASC`).all(sessionId
|
|
293
|
+
WHERE session_id = ?
|
|
294
|
+
ORDER BY seq ASC`).all(sessionId);
|
|
295
|
+
const restoredMessages = buildSessionContextForLlm(remainingEntries.map(transcriptEntryRowToStoredRow));
|
|
228
296
|
if (restoredMessages.length === 0) throw new Error(`No restorable context exists before compaction boundary: ${compactionId}`);
|
|
229
|
-
const current = db.prepare(`SELECT estimated_tokens FROM sessions WHERE session_key = ?`).get(sessionKey);
|
|
230
297
|
const tokensAfter = estimateTokensFromMessages(restoredMessages);
|
|
231
|
-
const
|
|
232
|
-
insertEntry(db, {
|
|
233
|
-
sessionId,
|
|
234
|
-
sessionKey,
|
|
235
|
-
row: {
|
|
236
|
-
type: "compaction",
|
|
237
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
238
|
-
baseSeq,
|
|
239
|
-
plannerVersion: 2,
|
|
240
|
-
summaryModelRef: "logical-restore",
|
|
241
|
-
qualityAudit: "disabled",
|
|
242
|
-
summary: `Restored the effective context that existed before compaction boundary ${compactionId}.`,
|
|
243
|
-
messages: restoredMessages,
|
|
244
|
-
firstKeptIndex: 0,
|
|
245
|
-
tokensBefore: current.estimated_tokens,
|
|
246
|
-
tokensAfter,
|
|
247
|
-
restoredFromCompactionId: compactionId
|
|
248
|
-
}
|
|
249
|
-
});
|
|
298
|
+
const compactedCount = remainingEntries.filter((entry) => entry.entry_kind === "compaction").length;
|
|
250
299
|
const now = Date.now();
|
|
251
300
|
db.prepare(`UPDATE sessions SET
|
|
252
301
|
message_count = ?,
|
|
253
302
|
estimated_tokens = ?,
|
|
254
|
-
compacted_count =
|
|
303
|
+
compacted_count = ?,
|
|
255
304
|
updated_at = ?,
|
|
256
305
|
last_accessed_at = ?,
|
|
257
306
|
last_interaction_at = ?
|
|
258
|
-
WHERE session_key = ?`).run(restoredMessages.length, tokensAfter, now, now, now, sessionKey);
|
|
307
|
+
WHERE session_key = ?`).run(restoredMessages.length, tokensAfter, compactedCount, now, now, now, sessionKey);
|
|
259
308
|
});
|
|
260
309
|
}
|
|
261
310
|
//#endregion
|
|
262
|
-
export {
|
|
311
|
+
export { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript };
|