@xopcai/xopc 0.0.134 → 0.0.136
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/Combination-HAlzriaz.js +41 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-mQ4lbZRf.js → agent-avatar-dicebear-CER17NHM.js} +1 -1
- package/dist/gateway/static/root/assets/agents-Bv5R-N8Q.js +2 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Bj2YJiQe.js → app-management-settings-panel-B3Ap_wpX.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-B93olV5Z.js → appearance-settings-3kBO22Xd.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BHYbGQcZ.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-D_yymKFJ.js → archive-plugin-D_vGeNB8.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-kfyH3HV-.js → attachment-load-hWV_8pHL.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-DyGBB2WH.js → automation-suggestion-card-DVKmVTIo.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BCTXpOBp.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BX1AXf98.js → binary-plugins-BuXIeSPc.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-D-WEVNHU.js → block-editor-C1m0u-UU.js} +39 -39
- package/dist/gateway/static/root/assets/browser-settings-page-ChUF08V5.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-B7WWYaEh.js +1 -0
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-CHExb90z.js → capability-presets-settings-panel-D_Bh1PnA.js} +1 -1
- package/dist/gateway/static/root/assets/{channel-recipient-api-RANYrzfa.js → channel-recipient-api-sV06LCht.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BI2ChQc7.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-MY4Xh4fM.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-qgvEp09M.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-BxMJlvb-.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-C3JDiXSu.js → desktop-pet-settings-DCvpDImn.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-MT71cjgl.js → directory-picker-path-field-D1nxs9PA.js} +1 -1
- package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +1 -0
- package/dist/gateway/static/root/assets/{dreaming-settings-Cfx_Qg4R.js → dreaming-settings-EAWkpOgw.js} +3 -3
- package/dist/gateway/static/root/assets/{extension-debug-page-Wp23cLkf.js → extension-debug-page-LUQ8dE8z.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B5HRNtVY.js → extension-page-B_mnhoRd.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-zPfMpsYi.js → extension-settings-page-BWQsGmvW.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-6HXXdO77.js → fetch-BWXmBizE.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CsS_3Ii6.js → gateway-config-api-M9bzPASf.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DOxh0hei.js → gateway-settings-CbgtpprN.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BE1M9fH_.js → gateway-startup-retry-BALL91S7.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-CbP4t9aM.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-DlwI-MZZ.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api--3Vzceq-.js → goals-config-api-BBhFVzBS.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-D26r7knp.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-Dg_hQNVC.js → goals-settings-DdmVG_TR.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CecoDTZJ.js → heartbeat-settings-DZW2Xq-U.js} +1 -1
- package/dist/gateway/static/root/assets/index-CPwVzi9x.css +1 -0
- package/dist/gateway/static/root/assets/index-DZOm5_ex.js +262 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BWMLAFxf.js → keyboard-shortcuts-settings-1IWd88-T.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DxoKJO7-.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-5tvDwUMS.js → markdown-split-BtdBj32h.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-RSjPG4B0.js → media-plugins-CpoPj3s8.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CQ_k8RHj.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-D1Rp__dV.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-CgR1bO2W.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-ozsnmDTV.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-DYNWfN6S.js → page-tabs-CVLqCfQB.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-B50PdIc8.js → preview-open-alternatives-CKUXJk2t.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-B4dqFAQF.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-DlRGXv4a.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-rZEYQMZV.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-DggNb0SF.js → save-bar-controls-BtGni268.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-T4ti2C8S.js → schedule-field-BDGzKVWn.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-D6wGEfEa.js → schema-form-DQJsKMCE.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DxGoCGU8.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-4e8ZQwxr.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Cgd_aLBV.js → settings-collapsible-section-c8XGd4-8.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DnDrLMWZ.js → settings-form-section-By0YiDWo.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-A2OshMK8.js → settings-loading-skeleton-SYCPY-WM.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CXMK9Vb3.js → settings-page-D9NwvnBt.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-Da_LNPDS.js → settings-page-layout-CrICyGob.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-IjK-hDxf.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BGZV-PCJ.js → share-preview-page-Dfnk9M_m.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-vQiRBra7.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BIWv778A.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-CruV215G.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-D8uzXP0Y.js → system-settings-panel-BBVbSDFD.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-DQxv2BHa.js → typed-models-lib-CwFayhxu.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BCBfSoHx.js → use-channel-catalog-BKtHOM50.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-DkZSHsIs.js → user-profile-settings-panel-_KDWzagh.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-ivGpUrZi.js → utils-BiUjIHb4.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-agJqlm4o.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-Bdw4ATCb.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-D-Dy6mTy.js +3 -0
- package/dist/gateway/static/root/assets/workflow-start-dialog-GammZ2GK.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-Cw5zrqti.js +18 -0
- package/dist/gateway/static/root/index.html +7 -8
- package/dist/package.js +1 -1
- package/dist/src/agent/image/inbound-image-handling.d.ts +1 -0
- package/dist/src/agent/image/inbound-image-handling.js +4 -1
- package/dist/src/agent/image/inbound-image-handling.js.map +1 -1
- package/dist/src/agent/image/tool-model-config.d.ts +18 -2
- package/dist/src/agent/image/tool-model-config.js +100 -14
- package/dist/src/agent/image/tool-model-config.js.map +1 -1
- package/dist/src/agent/image/vision-detection.js +4 -23
- package/dist/src/agent/image/vision-detection.js.map +1 -1
- package/dist/src/agent/inbound/attachment-pipeline.js +3 -0
- package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +5 -2
- package/dist/src/agent/messaging/command-handler.js +4 -3
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/service/btw-query.d.ts +2 -0
- package/dist/src/agent/service/btw-query.js +4 -2
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +58 -1
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.js +1 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.d.ts +2 -1
- package/dist/src/agent/session/session-inspector.js +5 -3
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/tools/factory.js +2 -1
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/image-tool.d.ts +1 -0
- package/dist/src/agent/tools/image-tool.js +4 -1
- package/dist/src/agent/tools/image-tool.js.map +1 -1
- package/dist/src/chat-commands/builtins/review.js +94 -7
- package/dist/src/chat-commands/builtins/review.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +5 -3
- package/dist/src/chat-commands/context.js +5 -2
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +12 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/gateway/agents-admin.d.ts +5 -0
- package/dist/src/gateway/agents-admin.js +6 -1
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +2 -1
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/projects.js +88 -0
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +2 -1
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +1 -0
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/image-capabilities.d.ts +7 -1
- package/dist/src/gateway/image-capabilities.js +16 -3
- package/dist/src/gateway/image-capabilities.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +1 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.js +3 -3
- package/dist/src/projects/project-loop.js +2 -2
- package/dist/src/projects/project-loop.js.map +1 -1
- package/dist/src/review/review-types.js +2 -1
- package/dist/src/review/review-types.js.map +1 -1
- package/dist/src/session/client-history.d.ts +1 -0
- package/dist/src/session/client-history.js +56 -0
- package/dist/src/session/client-history.js.map +1 -1
- package/dist/src/session/index.js +1 -1
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/store.d.ts +1 -0
- package/dist/src/session/store.js +30 -1
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/components/assistant-message.js +10 -3
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/bash-execution.d.ts +4 -0
- package/dist/src/tui/components/bash-execution.js +15 -7
- package/dist/src/tui/components/bash-execution.js.map +1 -1
- package/dist/src/tui/tool-summary.js +9 -3
- package/dist/src/tui/tool-summary.js.map +1 -1
- package/dist/src/tui/tui-submit.d.ts +3 -0
- package/dist/src/tui/tui-submit.js +24 -1
- package/dist/src/tui/tui-submit.js.map +1 -1
- package/dist/src/tui/tui.js +29 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/work-items/index.d.ts +1 -0
- package/dist/src/work-items/index.js +2 -1
- package/dist/src/work-items/work-item-workflow-judge.d.ts +8 -0
- package/dist/src/work-items/work-item-workflow-judge.js +50 -0
- package/dist/src/work-items/work-item-workflow-judge.js.map +1 -0
- package/dist/src/workflows/domain/run.d.ts +17 -0
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
- package/dist/src/workflows/service/workflow-run-service.js +67 -0
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +4 -1
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
- package/dist/src/workflows/service/workflow-session-bridge.js +45 -0
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +0 -41
- package/dist/gateway/static/root/assets/agents-BP0iRtiu.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-12_2SDFq.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-V-tw6y1o.js +0 -4
- package/dist/gateway/static/root/assets/browser-settings-page-aMPnxWXi.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-CsaY2Z8B.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-N8NujD--.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-BG_j4Ci-.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-zBJbFgnK.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-DfA-hVlt.js +0 -1
- package/dist/gateway/static/root/assets/dist-CkobR7mk.js +0 -1
- package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-BOWSTGB-.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-CCLgkqj1.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-CsfIp8Vl.js +0 -2
- package/dist/gateway/static/root/assets/index-BOme955B.js +0 -262
- package/dist/gateway/static/root/assets/index-DXUkWmeK.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-CW7AMYhN.js +0 -7
- package/dist/gateway/static/root/assets/messages-DR9ODkb8.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-mKfeyGVq.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-DYw5zPeJ.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-SPdKpvSN.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-D3yP4K3k.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B6EV45NR.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-9foX60FQ.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BReBhxWd.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DNDBN4nT.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-C8UtBMJ_.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-xXAMKlc7.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CurjHfEM.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BRR7NQkL.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-DCiECZN1.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DAel5CHH.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-2w0zj9eJ.js +0 -3
- package/dist/gateway/static/root/assets/workflow-start-dialog-B5xdDFV-.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DRhiSwuU.js +0 -18
|
@@ -6,7 +6,7 @@ import "./types.js";
|
|
|
6
6
|
import { buildSessionContextForLlm, buildSessionDisplayMessages, 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 { appendTranscriptEntry, captureCompactionCheckpoint, getCompactionCheckpointDetail, listCompactionCheckpoints, loadCheckpointRows, loadLlmMessagesForSession, loadTranscriptRowsForSession, replaceTranscriptRows, restoreCompactionCheckpoint } from "../storage/sqlite/transcript-repository.js";
|
|
9
|
+
import { appendTranscriptEntry, captureCompactionCheckpoint, getCompactionCheckpointDetail, listCompactionCheckpoints, loadCheckpointRows, loadLlmMessagesForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreCompactionCheckpoint } 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";
|
|
@@ -14,6 +14,7 @@ import { SessionCompactor } from "../agent/memory/compaction.js";
|
|
|
14
14
|
import { SlidingWindow } from "../agent/memory/window.js";
|
|
15
15
|
import { normalizeCompactionCheckpointId } from "./compaction-checkpoints.js";
|
|
16
16
|
import { isAppendOnlyLlmTranscriptMessage } from "./transcript-stats.js";
|
|
17
|
+
import { transcriptRowsToClientHistory } from "./client-history.js";
|
|
17
18
|
//#region src/session/store.ts
|
|
18
19
|
init_paths_state();
|
|
19
20
|
init_logger();
|
|
@@ -88,6 +89,34 @@ var SessionStore = class {
|
|
|
88
89
|
const offset = Math.max(0, Math.trunc(options.offset ?? 0));
|
|
89
90
|
const parsedBefore = options.before ? Number.parseInt(options.before, 10) : void 0;
|
|
90
91
|
const hasBeforeCursor = parsedBefore !== void 0 && Number.isFinite(parsedBefore);
|
|
92
|
+
if (options.includeContextRows) {
|
|
93
|
+
const page = paginateTranscriptMessages(key, {
|
|
94
|
+
limit,
|
|
95
|
+
offset: hasBeforeCursor ? void 0 : offset,
|
|
96
|
+
beforeEndIndex: hasBeforeCursor ? parsedBefore : void 0,
|
|
97
|
+
includeContext: true
|
|
98
|
+
});
|
|
99
|
+
const messages = transcriptRowsToClientHistory(page.rows);
|
|
100
|
+
const endIndex = hasBeforeCursor ? Math.min(page.total, Math.max(0, parsedBefore)) : Math.max(0, page.total - offset);
|
|
101
|
+
const startIndex = Math.max(0, endIndex - page.rows.length);
|
|
102
|
+
const session = {
|
|
103
|
+
...metadata,
|
|
104
|
+
messages,
|
|
105
|
+
...options.includeTranscriptRows ? { transcriptRows: await this.loadTranscriptRows(key) } : {}
|
|
106
|
+
};
|
|
107
|
+
const nextBeforeCursor = startIndex > 0 ? String(startIndex) : void 0;
|
|
108
|
+
return {
|
|
109
|
+
session,
|
|
110
|
+
pagination: {
|
|
111
|
+
total: page.total,
|
|
112
|
+
limit,
|
|
113
|
+
offset,
|
|
114
|
+
hasMore: hasBeforeCursor ? startIndex > 0 : offset + limit < page.total,
|
|
115
|
+
...hasBeforeCursor ? { before: String(endIndex) } : {},
|
|
116
|
+
...nextBeforeCursor ? { nextBeforeCursor } : {}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
91
120
|
const displayMessages = await this.loadDisplayMessages(key);
|
|
92
121
|
const page = this.paginateDisplayMessages(displayMessages, {
|
|
93
122
|
limit,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","names":[],"sources":["../../../src/session/store.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config } from '../config/schema.js';\nimport { resolveStateDir } from '../config/paths-state.js';\nimport { resolveEffectiveAgentProfileForSession } from '../config/agent-profile.js';\nimport { readPostCompactionContext } from '../agent/reply/post-compaction-context.js';\nimport { createLogger } from '../utils/logger.js';\nimport { SessionCompactor, type CompactionConfig, type CompactionResult } from '../agent/memory/compaction.js';\nimport { SlidingWindow, type WindowConfig } from '../agent/memory/window.js';\nimport {\n requireXopcDatabase,\n appendTranscriptEntry,\n captureCompactionCheckpoint,\n deleteSessionRecord,\n ensureSessionRecord,\n estimateTokensFromMessages,\n getCompactionCheckpointDetail,\n getGlobalSessionStats,\n getSessionMetadata,\n findSessionKeyBySessionId,\n listCompactionCheckpoints,\n listSessionMetadata,\n listSessionsByAgent,\n loadCheckpointRows,\n loadLlmMessagesForSession,\n loadTranscriptRowsForSession,\n patchSessionMetadata,\n replaceTranscriptRows,\n resetSessionRecord,\n restoreCompactionCheckpoint,\n type SessionMetadataSeed,\n} from '../storage/sqlite/index.js';\nimport type { TranscriptCompactionRecord, XopcSessionTranscriptV1 } from './transcript-format.js';\nimport {\n buildSessionDisplayMessages,\n buildSessionContextForLlm,\n mergeLlmMessagesPreservingContextRows,\n transcriptRowsFromJsonArray,\n type TranscriptStoredRow,\n type XopcTranscriptContextEntry,\n type XopcTranscriptCustomMessageEntry,\n type XopcTranscriptCustomStateEntry,\n} from './session-context-for-llm.js';\nimport { normalizeCompactionCheckpointId } from './compaction-checkpoints.js';\nimport type {\n SessionMetadata,\n SessionDetail,\n SessionListQuery,\n PaginatedResult,\n GlobalSessionStats,\n ExportFormat,\n SessionExport,\n SessionTranscriptSummary,\n CompactionCheckpointSummary,\n CompactionCheckpointDetail,\n} from './types.js';\nimport { SessionStatus } from './types.js';\nimport type { Message } from './types.js';\nimport type { SessionTranscriptUpdate } from './transcript-events.js';\nimport { isAppendOnlyLlmTranscriptMessage } from './transcript-stats.js';\n\nconst log = createLogger('SessionStore');\n\nconst INDEX_VERSION = '1.0';\n\nexport interface SessionStoreOptions {\n config: Config;\n}\n\nexport class SessionStore {\n private window: SlidingWindow;\n private compactor: SessionCompactor;\n\n constructor(\n private options: SessionStoreOptions,\n windowConfig?: Partial<WindowConfig>,\n compactionConfig?: Partial<CompactionConfig>,\n ) {\n this.window = new SlidingWindow(windowConfig);\n this.compactor = new SessionCompactor(compactionConfig);\n }\n\n private resolveWorkspaceCwd(sessionKey: string): string {\n return resolveEffectiveAgentProfileForSession(this.options.config, sessionKey).resolvedWorkspacePath;\n }\n\n private async runStoreMutation<T>(fn: () => Promise<T>): Promise<T> {\n return fn();\n }\n\n async initialize(): Promise<void> {\n requireXopcDatabase();\n log.debug('Session store initialized (SQLite)');\n }\n\n getSessionsRoot(): string {\n return resolveStateDir();\n }\n\n async resolveTranscriptPath(\n sessionKey: string,\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<{ sessionId: string; sessionKey: string }> {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n const meta = ensureSessionRecord(sessionKey, cwd, options?.metadata);\n return { sessionId: meta.sessionId!, sessionKey };\n }\n\n async appendTranscriptMessage(\n sessionKey: string,\n message: AgentMessage,\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n ensureSessionRecord(sessionKey, cwd, options?.metadata);\n appendTranscriptEntry(sessionKey, message);\n });\n }\n\n async getByAgent(agentId: string): Promise<SessionMetadata[]> {\n requireXopcDatabase();\n return listSessionsByAgent(agentId);\n }\n\n async getByAccount(accountId: string): Promise<SessionMetadata[]> {\n const { items } = await this.list({ limit: 100_000 });\n return items.filter((m) => m.routing?.accountId === accountId);\n }\n\n async getByPeer(peerKind: string, peerId: string): Promise<SessionMetadata[]> {\n const { items } = await this.list({ limit: 100_000 });\n return items.filter((m) => m.routing?.peerKind === peerKind && m.routing.peerId === peerId);\n }\n\n async getMainSession(channel: string, accountId: string): Promise<SessionMetadata | null> {\n const { items } = await this.list({ limit: 100_000 });\n return (\n items.find(\n (m) =>\n m.routing?.source === channel &&\n m.routing.accountId === accountId &&\n m.routing.peerKind === 'dm' &&\n m.routing.peerId === 'main',\n ) ?? null\n );\n }\n\n async refreshIndex(): Promise<void> {\n /* no-op: SQLite is authoritative */\n }\n\n async list(query: SessionListQuery = {}): Promise<PaginatedResult<SessionMetadata>> {\n requireXopcDatabase();\n return listSessionMetadata(query);\n }\n\n async get(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return null;\n }\n const messages = await this.loadDisplayMessages(key);\n return this.buildSessionDetail(key, metadata, messages, options);\n }\n\n async getMessagePage(\n key: string,\n options: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n } = {},\n ): Promise<{\n session: SessionDetail;\n pagination: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n before?: string;\n nextBeforeCursor?: string;\n };\n } | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return null;\n }\n\n const limit = Math.min(200, Math.max(1, Math.trunc(options.limit ?? 50)));\n const offset = Math.max(0, Math.trunc(options.offset ?? 0));\n const parsedBefore = options.before ? Number.parseInt(options.before, 10) : undefined;\n const hasBeforeCursor = parsedBefore !== undefined && Number.isFinite(parsedBefore);\n\n const displayMessages = await this.loadDisplayMessages(key);\n const page = this.paginateDisplayMessages(displayMessages, {\n limit,\n offset: hasBeforeCursor ? undefined : offset,\n beforeEndIndex: hasBeforeCursor ? parsedBefore : undefined,\n });\n\n const session = await this.buildSessionDetail(key, metadata, page.messages, options);\n const nextBeforeCursor = page.startIndex > 0 ? String(page.startIndex) : undefined;\n\n return {\n session,\n pagination: {\n total: page.total,\n limit,\n offset,\n hasMore: hasBeforeCursor ? page.startIndex > 0 : offset + limit < page.total,\n ...(hasBeforeCursor ? { before: String(page.endIndex) } : {}),\n ...(nextBeforeCursor ? { nextBeforeCursor } : {}),\n },\n };\n }\n\n private async buildSessionDetail(\n key: string,\n metadata: SessionMetadata,\n messages: AgentMessage[],\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail> {\n let transcriptSummary: SessionTranscriptSummary | undefined;\n if (options?.includeTranscriptSummary) {\n const env = await this.loadTranscriptDocument(key);\n if (env) {\n transcriptSummary = {\n id: env.id,\n version: env.version,\n createdAt: env.createdAt,\n updatedAt: env.updatedAt,\n compactionCount: env.compactions?.length ?? 0,\n };\n }\n }\n let transcriptRows: TranscriptStoredRow[] | undefined;\n if (options?.includeTranscriptRows) {\n transcriptRows = await this.loadTranscriptRows(key);\n }\n return {\n ...metadata,\n messages: this.convertMessages(messages),\n ...(transcriptSummary ? { transcriptSummary } : {}),\n ...(transcriptRows !== undefined ? { transcriptRows } : {}),\n };\n }\n\n async loadTranscriptRows(key: string): Promise<TranscriptStoredRow[]> {\n requireXopcDatabase();\n return loadTranscriptRowsForSession(key);\n }\n\n async getMetadata(key: string): Promise<SessionMetadata | null> {\n requireXopcDatabase();\n return getSessionMetadata(key);\n }\n\n async resolveKeyBySessionId(sessionId: string): Promise<string | null> {\n requireXopcDatabase();\n return findSessionKeyBySessionId(sessionId);\n }\n\n async updateMetadata(key: string, updates: Partial<SessionMetadata>): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n patchSessionMetadata(key, updates);\n log.debug({ key, updates }, 'Session metadata updated');\n });\n }\n\n async reset(key: string): Promise<{ sessionId: string; previousSessionId: string } | null> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n const outcome = resetSessionRecord(key, cwd);\n if (outcome) {\n log.info({ key, ...outcome }, 'Session reset');\n }\n return outcome;\n });\n }\n\n async delete(key: string): Promise<boolean> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const ok = deleteSessionRecord(key);\n if (ok) {\n log.info({ key }, 'Session deleted');\n }\n return ok;\n });\n }\n\n async deleteMany(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n const success: string[] = [];\n const failed: string[] = [];\n for (const key of keys) {\n try {\n if (await this.delete(key)) {\n success.push(key);\n } else {\n failed.push(key);\n }\n } catch {\n failed.push(key);\n }\n }\n return { success, failed };\n }\n\n async setStatus(key: string, status: SessionStatus): Promise<void> {\n await this.updateMetadata(key, { status });\n }\n\n async archive(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ARCHIVED);\n }\n\n async unarchive(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ACTIVE);\n }\n\n async pin(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.PINNED);\n }\n\n async unpin(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ACTIVE);\n }\n\n async loadMessages(_key: string, _options?: { fromArchive?: boolean }): Promise<AgentMessage[]> {\n requireXopcDatabase();\n return loadLlmMessagesForSession(_key);\n }\n\n async loadTranscriptDocument(key: string): Promise<XopcSessionTranscriptV1 | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata?.sessionId) {\n return null;\n }\n const rows = await this.loadTranscriptRows(key);\n const compactions: TranscriptCompactionRecord[] = [];\n for (const row of rows) {\n if ((row as { type?: string }).type === 'compaction') {\n const c = row as unknown as TranscriptCompactionRecord & { type: 'compaction' };\n compactions.push({\n at: c.at ?? new Date().toISOString(),\n summary: c.summary ?? '',\n firstKeptIndex: Number(c.firstKeptIndex ?? 0),\n tokensBefore: c.tokensBefore ?? 0,\n tokensAfter: (c as { tokensAfter?: number }).tokensAfter ?? 0,\n });\n }\n }\n return {\n type: 'xopc_session_transcript',\n version: 1,\n id: metadata.sessionId,\n createdAt: metadata.createdAt,\n updatedAt: metadata.updatedAt,\n messages: rows,\n ...(compactions.length > 0 ? { compactions } : {}),\n };\n }\n\n async syncEmbeddedTranscriptUpdate(update: SessionTranscriptUpdate): Promise<void> {\n const sessionKey = update.sessionKey?.trim();\n if (!sessionKey) {\n return;\n }\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n ensureSessionRecord(sessionKey, cwd);\n\n if (update.message && isAppendOnlyLlmTranscriptMessage(update.message)) {\n appendTranscriptEntry(sessionKey, update.message as AgentMessage);\n }\n });\n }\n\n async appendTranscriptContextEntry(\n key: string,\n entry: Omit<XopcTranscriptContextEntry, 'kind'> & Partial<Pick<XopcTranscriptContextEntry, 'kind'>>,\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptContextEntry = {\n kind: 'context',\n id: typeof entry.id === 'string' ? entry.id : undefined,\n text: typeof entry.text === 'string' ? entry.text : undefined,\n data: entry.data,\n createdAt: entry.createdAt ?? new Date().toISOString(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptLabelEntry(\n key: string,\n entry: { targetId: string; label?: string },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n appendTranscriptEntry(key, {\n type: 'label',\n targetId: entry.targetId,\n label: entry.label?.trim() || undefined,\n timestamp: new Date().toISOString(),\n });\n });\n }\n\n async appendTranscriptCustomEntry(\n key: string,\n entry: { customType: string; data?: unknown },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptCustomStateEntry = {\n type: 'custom',\n customType: entry.customType.trim(),\n data: entry.data,\n timestamp: new Date().toISOString(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptCustomMessageEntry(\n key: string,\n entry: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptCustomMessageEntry = {\n role: 'custom',\n customType: entry.customType.trim(),\n content: entry.content ?? '',\n display: entry.display ?? true,\n details: entry.details,\n timestamp: Date.now(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptBashExecutionEntry(\n key: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n appendTranscriptEntry(key, {\n role: 'bashExecution',\n command: entry.command,\n output: entry.output ?? '',\n exitCode: entry.exitCode ?? null,\n signal: entry.signal ?? null,\n excludeFromContext: entry.excludeFromContext === true,\n truncated: entry.truncated === true,\n fullOutputPath: entry.fullOutputPath,\n timestamp: Date.now(),\n });\n });\n }\n\n async saveMessages(\n key: string,\n messages: AgentMessage[],\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd, options?.metadata);\n const prev = await this.loadTranscriptRows(key);\n const merged = mergeLlmMessagesPreservingContextRows(prev, messages);\n replaceTranscriptRows(key, merged);\n });\n }\n\n getWindowStats(messages: AgentMessage[]) {\n return this.window.getStats(messages);\n }\n\n needsCompaction(key: string, messages: AgentMessage[], contextWindow: number) {\n return this.compactor.needsCompaction(messages, contextWindow);\n }\n\n prepareCompaction(key: string, messages: AgentMessage[], contextWindow: number) {\n const result = this.compactor.needsCompaction(messages, contextWindow);\n return { needsCompaction: result.needed, messages, stats: result };\n }\n\n async applyCompaction(\n key: string,\n messages: AgentMessage[],\n result: CompactionResult,\n ): Promise<AgentMessage[]> {\n const compacted = this.compactor.applyCompaction(messages, result);\n return this.runStoreMutation(async () => {\n const prev = await this.loadTranscriptRows(key);\n const merged = mergeLlmMessagesPreservingContextRows(prev, compacted);\n captureCompactionCheckpoint(key);\n replaceTranscriptRows(key, merged, {\n appendCompaction: {\n at: new Date().toISOString(),\n summary: result.summary,\n firstKeptIndex: result.firstKeptIndex,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n },\n });\n const metadata = await this.getMetadata(key);\n if (metadata) {\n await this.updateMetadata(key, { compactedCount: metadata.compactedCount + 1 });\n }\n log.info(\n { key, tokensBefore: result.tokensBefore, tokensAfter: result.tokensAfter, keptMessages: compacted.length },\n 'Session compacted',\n );\n await this.injectPostCompactionContext(key);\n return compacted;\n });\n }\n\n async compact(\n key: string,\n messages: AgentMessage[],\n contextWindow: number,\n instructions?: string,\n force?: boolean,\n ): Promise<CompactionResult> {\n void contextWindow;\n const result = await this.compactor.compact(messages, instructions, force);\n if (result.compacted) {\n await this.applyCompaction(key, messages, result);\n }\n return result;\n }\n\n async getCompactionStats(key: string) {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return undefined;\n }\n return {\n compactionCount: metadata.compactedCount,\n totalTokensBefore: 0,\n totalTokensAfter: 0,\n lastCompactionAt: undefined,\n };\n }\n\n async listCompactionCheckpoints(key: string): Promise<CompactionCheckpointSummary[]> {\n requireXopcDatabase();\n return listCompactionCheckpoints(key);\n }\n\n async getCompactionCheckpointDetail(\n key: string,\n checkpointId: string,\n ): Promise<CompactionCheckpointDetail | null> {\n requireXopcDatabase();\n const id = normalizeCompactionCheckpointId(checkpointId);\n if (!id) {\n return null;\n }\n return getCompactionCheckpointDetail(key, id);\n }\n\n async restoreCompactionCheckpoint(key: string, checkpointId: string): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const id = normalizeCompactionCheckpointId(checkpointId);\n if (!id) {\n throw new Error(`Invalid checkpoint id: ${checkpointId}`);\n }\n restoreCompactionCheckpoint(key, id);\n });\n }\n\n async deleteSession(key: string): Promise<boolean> {\n return this.delete(key);\n }\n\n async load(key: string, options?: { fromArchive?: boolean }): Promise<AgentMessage[]> {\n return this.loadMessages(key, options);\n }\n\n async estimateTokenUsage(_key: string, messages: AgentMessage[]): Promise<number> {\n return this.estimateTokens(messages);\n }\n\n async searchInSession(key: string, keyword: string): Promise<Message[]> {\n const messages = await this.loadDisplayMessages(key);\n const q = keyword.toLowerCase();\n return this.convertMessages(\n messages.filter((m) => this.extractTextContent(this.messageContent(m)).toLowerCase().includes(q)),\n );\n }\n\n async exportSession(key: string, format: ExportFormat): Promise<string> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n throw new Error(`Session not found: ${key}`);\n }\n const rows = await this.loadTranscriptRows(key);\n const messages = this.convertMessages(buildSessionContextForLlm(rows));\n const payload: SessionExport = {\n version: INDEX_VERSION,\n exportedAt: new Date().toISOString(),\n metadata,\n messages,\n transcriptRows: rows,\n };\n if (format === 'json') {\n return JSON.stringify(payload, null, 2);\n }\n const lines = [`# ${metadata.name ?? metadata.key}`, '', `Exported: ${payload.exportedAt}`, ''];\n for (const msg of messages) {\n lines.push(`## ${msg.role}`, '', typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), '');\n }\n return lines.join('\\n');\n }\n\n async importSessionExport(\n targetKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const existing = await this.getMetadata(targetKey);\n if (existing) {\n throw new Error(`Target session already exists: ${targetKey}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonContent);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n throw new Error(`Invalid session export JSON: ${errorMessage}`);\n }\n\n const record = parsed && typeof parsed === 'object' ? parsed as Record<string, unknown> : {};\n const rowsSource = Array.isArray(record.transcriptRows) ? record.transcriptRows : undefined;\n const rows = rowsSource ? transcriptRowsFromJsonArray(rowsSource) : [];\n if (rows.length === 0) {\n throw new Error('Session export contains no importable transcript rows');\n }\n\n const metadata = record.metadata && typeof record.metadata === 'object'\n ? record.metadata as Partial<SessionMetadata>\n : {};\n const cwd = this.resolveWorkspaceCwd(targetKey);\n ensureSessionRecord(targetKey, cwd, {\n sourceChannel: metadata.sourceChannel,\n sourceChatId: metadata.sourceChatId,\n sessionType: metadata.sessionType,\n routing: metadata.routing,\n customData: metadata.customData,\n });\n replaceTranscriptRows(targetKey, rows);\n\n const sourceKey = typeof metadata.key === 'string' ? metadata.key : undefined;\n const sourceName = typeof metadata.name === 'string' ? metadata.name.trim() : '';\n patchSessionMetadata(targetKey, {\n name: sourceName ? `Import of ${sourceName}` : 'Imported session',\n tags: [...new Set([...(Array.isArray(metadata.tags) ? metadata.tags.filter((tag): tag is string => typeof tag === 'string') : []), 'import'])],\n customData: {\n ...(metadata.customData && typeof metadata.customData === 'object'\n ? metadata.customData as Record<string, unknown>\n : {}),\n ...(sourceKey ? { importedFromSessionKey: sourceKey } : {}),\n importedAt: new Date().toISOString(),\n },\n });\n return { sessionKey: targetKey, rowCount: rows.length };\n });\n }\n\n async forkSession(\n sourceKey: string,\n targetKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.forkSessionRows(sourceKey, targetKey);\n }\n\n async forkSessionRows(\n sourceKey: string,\n targetKey: string,\n options: { throughRow?: number } = {},\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const sourceMetadata = await this.getMetadata(sourceKey);\n if (!sourceMetadata) {\n throw new Error(`Session not found: ${sourceKey}`);\n }\n const existing = await this.getMetadata(targetKey);\n if (existing) {\n throw new Error(`Target session already exists: ${targetKey}`);\n }\n const rows = await this.loadTranscriptRows(sourceKey);\n if (\n options.throughRow !== undefined &&\n (options.throughRow < 1 || options.throughRow > rows.length)\n ) {\n throw new Error(`Invalid fork row: ${options.throughRow}`);\n }\n const selectedRows =\n options.throughRow === undefined ? rows : rows.slice(0, Math.max(0, Math.trunc(options.throughRow)));\n const cwd = this.resolveWorkspaceCwd(targetKey);\n ensureSessionRecord(targetKey, cwd, {\n sourceChannel: sourceMetadata.sourceChannel,\n sourceChatId: sourceMetadata.sourceChatId,\n sessionType: sourceMetadata.sessionType,\n routing: sourceMetadata.routing,\n customData: sourceMetadata.customData,\n });\n replaceTranscriptRows(targetKey, selectedRows);\n const label = sourceMetadata.name?.trim() || sourceKey;\n patchSessionMetadata(targetKey, {\n name: `Fork of ${label}`,\n tags: [...new Set([...(sourceMetadata.tags ?? []), 'fork'])],\n customData: {\n ...(sourceMetadata.customData ?? {}),\n forkedFromSessionKey: sourceKey,\n forkedFromSessionId: sourceMetadata.sessionId,\n ...(options.throughRow !== undefined ? { forkedFromRow: selectedRows.length } : {}),\n forkedAt: new Date().toISOString(),\n },\n });\n return { sessionKey: targetKey, rowCount: selectedRows.length };\n });\n }\n\n async getStats(): Promise<GlobalSessionStats> {\n requireXopcDatabase();\n return getGlobalSessionStats();\n }\n\n async archiveOld(olderThanDays: number): Promise<number> {\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - olderThanDays);\n const list = await this.list({ limit: 100_000 });\n let archived = 0;\n for (const session of list.items) {\n if (session.status !== SessionStatus.ARCHIVED && session.status !== SessionStatus.PINNED) {\n const lastAccess = new Date(session.lastAccessedAt);\n if (lastAccess < cutoff) {\n await this.archive(session.key);\n archived++;\n }\n }\n }\n return archived;\n }\n\n estimateTokens(messages: AgentMessage[]): number {\n return estimateTokensFromMessages(messages);\n }\n\n private async loadDisplayMessages(key: string): Promise<AgentMessage[]> {\n requireXopcDatabase();\n const checkpoints = listCompactionCheckpoints(key);\n const rowSets: TranscriptStoredRow[][] = [];\n for (const checkpoint of [...checkpoints].reverse()) {\n rowSets.push(loadCheckpointRows(key, checkpoint.id));\n }\n rowSets.push(await this.loadTranscriptRows(key));\n\n const messages: AgentMessage[] = [];\n const seen = new Set<string>();\n for (const rows of rowSets) {\n for (const message of buildSessionDisplayMessages(rows)) {\n if (this.isCompactionSummaryMessage(message)) {\n continue;\n }\n const identity = this.displayMessageIdentity(message);\n if (seen.has(identity)) {\n continue;\n }\n seen.add(identity);\n messages.push(message);\n }\n }\n return messages;\n }\n\n private paginateDisplayMessages(\n messages: AgentMessage[],\n options: {\n offset?: number;\n limit?: number;\n beforeEndIndex?: number;\n } = {},\n ): { messages: AgentMessage[]; total: number; startIndex: number; endIndex: number } {\n const total = messages.length;\n const limit = Math.min(200, Math.max(1, Math.trunc(options.limit ?? 50)));\n const offset = Math.max(0, Math.trunc(options.offset ?? 0));\n\n let startIndex: number;\n let endIndex: number;\n if (options.beforeEndIndex !== undefined && Number.isFinite(options.beforeEndIndex)) {\n endIndex = Math.min(total, Math.max(0, Math.trunc(options.beforeEndIndex)));\n startIndex = Math.max(0, endIndex - limit);\n } else {\n endIndex = Math.max(0, total - offset);\n startIndex = Math.max(0, endIndex - limit);\n }\n\n return {\n messages: messages.slice(startIndex, endIndex),\n total,\n startIndex,\n endIndex,\n };\n }\n\n private displayMessageIdentity(message: AgentMessage): string {\n const record = message as unknown as Record<string, unknown>;\n return JSON.stringify({\n role: message.role,\n timestamp: record.timestamp,\n toolCallId: record.toolCallId ?? record.tool_call_id,\n toolName: record.toolName,\n content: this.messageContent(message),\n });\n }\n\n private messageContent(msg: AgentMessage): unknown {\n return (msg as { content?: unknown }).content;\n }\n\n private isCompactionSummaryMessage(msg: AgentMessage): boolean {\n if (msg.role !== 'user') {\n return false;\n }\n const text = this.extractTextContent(this.messageContent(msg)).trim();\n return /^\\[Previous conversation summary\\]/i.test(text);\n }\n\n private extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const item of content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) {\n continue;\n }\n const c = item as { type?: string; text?: string; name?: string };\n if (c.type === 'text' && typeof c.text === 'string') {\n parts.push(c.text);\n } else if (c.type === 'toolCall' || c.type === 'tool_use') {\n parts.push(c.name ? `[${c.name}]` : '');\n }\n }\n return parts.join('');\n }\n return '';\n }\n\n private async injectPostCompactionContext(key: string): Promise<void> {\n const contextText = readPostCompactionContext({\n cfg: this.options.config,\n sessionKey: key,\n });\n if (!contextText?.trim()) {\n return;\n }\n try {\n await this.appendTranscriptContextEntry(key, {\n id: `post-compaction-${Date.now()}`,\n text: contextText,\n createdAt: new Date().toISOString(),\n });\n } catch (err) {\n log.warn({ err, key }, 'Post-compaction context injection failed');\n }\n }\n\n private convertMessages(messages: AgentMessage[]): Message[] {\n return messages.map((m: AgentMessage & Record<string, unknown>) => {\n const c = this.messageContent(m);\n const content: string | unknown[] =\n typeof c === 'string' ? c : Array.isArray(c) ? c : this.extractTextContent(c);\n const row: Message = {\n role: m.role as Message['role'],\n content,\n timestamp: m.timestamp ? new Date(m.timestamp as string | number).toISOString() : undefined,\n tool_call_id: (m.tool_call_id as string | undefined) || (m.toolCallId as string | undefined),\n tool_calls: m.tool_calls as Message['tool_calls'],\n name: m.name as string | undefined,\n };\n if (Array.isArray(m.media) && m.media.length > 0) {\n row.media = m.media as Message['media'];\n }\n const rawUsage = m.usage as {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n totalTokens?: number;\n total?: number;\n } | undefined;\n if (rawUsage && typeof rawUsage === 'object') {\n const inputTokens = typeof rawUsage.input === 'number' ? rawUsage.input : undefined;\n const outputTokens = typeof rawUsage.output === 'number' ? rawUsage.output : undefined;\n const cacheReadTokens = typeof rawUsage.cacheRead === 'number' ? rawUsage.cacheRead : undefined;\n const cacheWriteTokens = typeof rawUsage.cacheWrite === 'number' ? rawUsage.cacheWrite : undefined;\n const totalTokens = typeof rawUsage.totalTokens === 'number'\n ? rawUsage.totalTokens\n : typeof rawUsage.total === 'number'\n ? rawUsage.total\n : undefined;\n if (\n inputTokens !== undefined ||\n outputTokens !== undefined ||\n cacheReadTokens !== undefined ||\n cacheWriteTokens !== undefined ||\n totalTokens !== undefined\n ) {\n row.usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens,\n };\n }\n }\n return row;\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;kBAG2D;aAGT;AAuDlD,MAAM,MAAM,aAAa,eAAe;AAExC,MAAM,gBAAgB;AAMtB,IAAa,eAAb,MAA0B;CACxB;CACA;CAEA,YACE,SACA,cACA,kBACA;AAHQ,OAAA,UAAA;AAIR,OAAK,SAAS,IAAI,cAAc,aAAa;AAC7C,OAAK,YAAY,IAAI,iBAAiB,iBAAiB;;CAGzD,oBAA4B,YAA4B;AACtD,SAAO,uCAAuC,KAAK,QAAQ,QAAQ,WAAW,CAAC;;CAGjF,MAAc,iBAAoB,IAAkC;AAClE,SAAO,IAAI;;CAGb,MAAM,aAA4B;AAChC,uBAAqB;AACrB,MAAI,MAAM,qCAAqC;;CAGjD,kBAA0B;AACxB,SAAO,iBAAiB;;CAG1B,MAAM,sBACJ,YACA,SACoD;AACpD,uBAAqB;AAGrB,SAAO;GAAE,WADI,oBAAoB,YADrB,KAAK,oBAAoB,WACW,EAAE,SAAS,SACnC,CAAC;GAAY;GAAY;;CAGnD,MAAM,wBACJ,YACA,SACA,SACe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,YADR,KAAK,oBAAoB,WACF,EAAE,SAAS,SAAS;AACvD,yBAAsB,YAAY,QAAQ;IAC1C;;CAGJ,MAAM,WAAW,SAA6C;AAC5D,uBAAqB;AACrB,SAAO,oBAAoB,QAAQ;;CAGrC,MAAM,aAAa,WAA+C;EAChE,MAAM,EAAE,UAAU,MAAM,KAAK,KAAK,EAAE,OAAO,KAAS,CAAC;AACrD,SAAO,MAAM,QAAQ,MAAM,EAAE,SAAS,cAAc,UAAU;;CAGhE,MAAM,UAAU,UAAkB,QAA4C;EAC5E,MAAM,EAAE,UAAU,MAAM,KAAK,KAAK,EAAE,OAAO,KAAS,CAAC;AACrD,SAAO,MAAM,QAAQ,MAAM,EAAE,SAAS,aAAa,YAAY,EAAE,QAAQ,WAAW,OAAO;;CAG7F,MAAM,eAAe,SAAiB,WAAoD;EACxF,MAAM,EAAE,UAAU,MAAM,KAAK,KAAK,EAAE,OAAO,KAAS,CAAC;AACrD,SACE,MAAM,MACH,MACC,EAAE,SAAS,WAAW,WACtB,EAAE,QAAQ,cAAc,aACxB,EAAE,QAAQ,aAAa,QACvB,EAAE,QAAQ,WAAW,OACxB,IAAI;;CAIT,MAAM,eAA8B;CAIpC,MAAM,KAAK,QAA0B,EAAE,EAA6C;AAClF,uBAAqB;AACrB,SAAO,oBAAoB,MAAM;;CAGnC,MAAM,IACJ,KACA,SAC+B;EAC/B,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,MAAI,CAAC,SACH,QAAO;EAET,MAAM,WAAW,MAAM,KAAK,oBAAoB,IAAI;AACpD,SAAO,KAAK,mBAAmB,KAAK,UAAU,UAAU,QAAQ;;CAGlE,MAAM,eACJ,KACA,UAMI,EAAE,EAWE;EACR,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,MAAI,CAAC,SACH,QAAO;EAGT,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,SAAS,GAAG,CAAC,CAAC;EACzE,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,UAAU,EAAE,CAAC;EAC3D,MAAM,eAAe,QAAQ,SAAS,OAAO,SAAS,QAAQ,QAAQ,GAAG,GAAG,KAAA;EAC5E,MAAM,kBAAkB,iBAAiB,KAAA,KAAa,OAAO,SAAS,aAAa;EAEnF,MAAM,kBAAkB,MAAM,KAAK,oBAAoB,IAAI;EAC3D,MAAM,OAAO,KAAK,wBAAwB,iBAAiB;GACzD;GACA,QAAQ,kBAAkB,KAAA,IAAY;GACtC,gBAAgB,kBAAkB,eAAe,KAAA;GAClD,CAAC;EAEF,MAAM,UAAU,MAAM,KAAK,mBAAmB,KAAK,UAAU,KAAK,UAAU,QAAQ;EACpF,MAAM,mBAAmB,KAAK,aAAa,IAAI,OAAO,KAAK,WAAW,GAAG,KAAA;AAEzE,SAAO;GACL;GACA,YAAY;IACV,OAAO,KAAK;IACZ;IACA;IACA,SAAS,kBAAkB,KAAK,aAAa,IAAI,SAAS,QAAQ,KAAK;IACvE,GAAI,kBAAkB,EAAE,QAAQ,OAAO,KAAK,SAAS,EAAE,GAAG,EAAE;IAC5D,GAAI,mBAAmB,EAAE,kBAAkB,GAAG,EAAE;IACjD;GACF;;CAGH,MAAc,mBACZ,KACA,UACA,UACA,SACwB;EACxB,IAAI;AACJ,MAAI,SAAS,0BAA0B;GACrC,MAAM,MAAM,MAAM,KAAK,uBAAuB,IAAI;AAClD,OAAI,IACF,qBAAoB;IAClB,IAAI,IAAI;IACR,SAAS,IAAI;IACb,WAAW,IAAI;IACf,WAAW,IAAI;IACf,iBAAiB,IAAI,aAAa,UAAU;IAC7C;;EAGL,IAAI;AACJ,MAAI,SAAS,sBACX,kBAAiB,MAAM,KAAK,mBAAmB,IAAI;AAErD,SAAO;GACL,GAAG;GACH,UAAU,KAAK,gBAAgB,SAAS;GACxC,GAAI,oBAAoB,EAAE,mBAAmB,GAAG,EAAE;GAClD,GAAI,mBAAmB,KAAA,IAAY,EAAE,gBAAgB,GAAG,EAAE;GAC3D;;CAGH,MAAM,mBAAmB,KAA6C;AACpE,uBAAqB;AACrB,SAAO,6BAA6B,IAAI;;CAG1C,MAAM,YAAY,KAA8C;AAC9D,uBAAqB;AACrB,SAAO,mBAAmB,IAAI;;CAGhC,MAAM,sBAAsB,WAA2C;AACrE,uBAAqB;AACrB,SAAO,0BAA0B,UAAU;;CAG7C,MAAM,eAAe,KAAa,SAAkD;AAClF,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AACrB,wBAAqB,KAAK,QAAQ;AAClC,OAAI,MAAM;IAAE;IAAK;IAAS,EAAE,2BAA2B;IACvD;;CAGJ,MAAM,MAAM,KAA+E;AACzF,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;GAErB,MAAM,UAAU,mBAAmB,KADvB,KAAK,oBAAoB,IACM,CAAC;AAC5C,OAAI,QACF,KAAI,KAAK;IAAE;IAAK,GAAG;IAAS,EAAE,gBAAgB;AAEhD,UAAO;IACP;;CAGJ,MAAM,OAAO,KAA+B;AAC1C,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;GACrB,MAAM,KAAK,oBAAoB,IAAI;AACnC,OAAI,GACF,KAAI,KAAK,EAAE,KAAK,EAAE,kBAAkB;AAEtC,UAAO;IACP;;CAGJ,MAAM,WAAW,MAAkE;EACjF,MAAM,UAAoB,EAAE;EAC5B,MAAM,SAAmB,EAAE;AAC3B,OAAK,MAAM,OAAO,KAChB,KAAI;AACF,OAAI,MAAM,KAAK,OAAO,IAAI,CACxB,SAAQ,KAAK,IAAI;OAEjB,QAAO,KAAK,IAAI;UAEZ;AACN,UAAO,KAAK,IAAI;;AAGpB,SAAO;GAAE;GAAS;GAAQ;;CAG5B,MAAM,UAAU,KAAa,QAAsC;AACjE,QAAM,KAAK,eAAe,KAAK,EAAE,QAAQ,CAAC;;CAG5C,MAAM,QAAQ,KAA4B;AACxC,QAAM,KAAK,UAAU,KAAA,WAA4B;;CAGnD,MAAM,UAAU,KAA4B;AAC1C,QAAM,KAAK,UAAU,KAAA,SAA0B;;CAGjD,MAAM,IAAI,KAA4B;AACpC,QAAM,KAAK,UAAU,KAAA,SAA0B;;CAGjD,MAAM,MAAM,KAA4B;AACtC,QAAM,KAAK,UAAU,KAAA,SAA0B;;CAGjD,MAAM,aAAa,MAAc,UAA+D;AAC9F,uBAAqB;AACrB,SAAO,0BAA0B,KAAK;;CAGxC,MAAM,uBAAuB,KAAsD;EACjF,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,MAAI,CAAC,UAAU,UACb,QAAO;EAET,MAAM,OAAO,MAAM,KAAK,mBAAmB,IAAI;EAC/C,MAAM,cAA4C,EAAE;AACpD,OAAK,MAAM,OAAO,KAChB,KAAK,IAA0B,SAAS,cAAc;GACpD,MAAM,IAAI;AACV,eAAY,KAAK;IACf,IAAI,EAAE,uBAAM,IAAI,MAAM,EAAC,aAAa;IACpC,SAAS,EAAE,WAAW;IACtB,gBAAgB,OAAO,EAAE,kBAAkB,EAAE;IAC7C,cAAc,EAAE,gBAAgB;IAChC,aAAc,EAA+B,eAAe;IAC7D,CAAC;;AAGN,SAAO;GACL,MAAM;GACN,SAAS;GACT,IAAI,SAAS;GACb,WAAW,SAAS;GACpB,WAAW,SAAS;GACpB,UAAU;GACV,GAAI,YAAY,SAAS,IAAI,EAAE,aAAa,GAAG,EAAE;GAClD;;CAGH,MAAM,6BAA6B,QAAgD;EACjF,MAAM,aAAa,OAAO,YAAY,MAAM;AAC5C,MAAI,CAAC,WACH;AAEF,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,YADR,KAAK,oBAAoB,WACF,CAAC;AAEpC,OAAI,OAAO,WAAW,iCAAiC,OAAO,QAAQ,CACpE,uBAAsB,YAAY,OAAO,QAAwB;IAEnE;;CAGJ,MAAM,6BACJ,KACA,OACe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,CAAC;AAQ7B,yBAAsB,KAAK;IANzB,MAAM;IACN,IAAI,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK,KAAA;IAC9C,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,KAAA;IACpD,MAAM,MAAM;IACZ,WAAW,MAAM,8BAAa,IAAI,MAAM,EAAC,aAAa;IAE1B,CAAC;IAC/B;;CAGJ,MAAM,2BACJ,KACA,OACe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,CAAC;AAC7B,yBAAsB,KAAK;IACzB,MAAM;IACN,UAAU,MAAM;IAChB,OAAO,MAAM,OAAO,MAAM,IAAI,KAAA;IAC9B,4BAAW,IAAI,MAAM,EAAC,aAAa;IACpC,CAAC;IACF;;CAGJ,MAAM,4BACJ,KACA,OACe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,CAAC;AAO7B,yBAAsB,KAAK;IALzB,MAAM;IACN,YAAY,MAAM,WAAW,MAAM;IACnC,MAAM,MAAM;IACZ,4BAAW,IAAI,MAAM,EAAC,aAAa;IAEP,CAAC;IAC/B;;CAGJ,MAAM,mCACJ,KACA,OAMe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,CAAC;AAS7B,yBAAsB,KAAK;IAPzB,MAAM;IACN,YAAY,MAAM,WAAW,MAAM;IACnC,SAAS,MAAM,WAAW;IAC1B,SAAS,MAAM,WAAW;IAC1B,SAAS,MAAM;IACf,WAAW,KAAK,KAAK;IAEO,CAAC;IAC/B;;CAGJ,MAAM,mCACJ,KACA,OASe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,CAAC;AAC7B,yBAAsB,KAAK;IACzB,MAAM;IACN,SAAS,MAAM;IACf,QAAQ,MAAM,UAAU;IACxB,UAAU,MAAM,YAAY;IAC5B,QAAQ,MAAM,UAAU;IACxB,oBAAoB,MAAM,uBAAuB;IACjD,WAAW,MAAM,cAAc;IAC/B,gBAAgB,MAAM;IACtB,WAAW,KAAK,KAAK;IACtB,CAAC;IACF;;CAGJ,MAAM,aACJ,KACA,UACA,SACe;AACf,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,uBAAoB,KADR,KAAK,oBAAoB,IACT,EAAE,SAAS,SAAS;AAGhD,yBAAsB,KADP,sCAAsC,MADlC,KAAK,mBAAmB,IAAI,EACY,SAC1B,CAAC;IAClC;;CAGJ,eAAe,UAA0B;AACvC,SAAO,KAAK,OAAO,SAAS,SAAS;;CAGvC,gBAAgB,KAAa,UAA0B,eAAuB;AAC5E,SAAO,KAAK,UAAU,gBAAgB,UAAU,cAAc;;CAGhE,kBAAkB,KAAa,UAA0B,eAAuB;EAC9E,MAAM,SAAS,KAAK,UAAU,gBAAgB,UAAU,cAAc;AACtE,SAAO;GAAE,iBAAiB,OAAO;GAAQ;GAAU,OAAO;GAAQ;;CAGpE,MAAM,gBACJ,KACA,UACA,QACyB;EACzB,MAAM,YAAY,KAAK,UAAU,gBAAgB,UAAU,OAAO;AAClE,SAAO,KAAK,iBAAiB,YAAY;GAEvC,MAAM,SAAS,sCAAsC,MADlC,KAAK,mBAAmB,IAAI,EACY,UAAU;AACrE,+BAA4B,IAAI;AAChC,yBAAsB,KAAK,QAAQ,EACjC,kBAAkB;IAChB,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC5B,SAAS,OAAO;IAChB,gBAAgB,OAAO;IACvB,cAAc,OAAO;IACrB,aAAa,OAAO;IACrB,EACF,CAAC;GACF,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,OAAI,SACF,OAAM,KAAK,eAAe,KAAK,EAAE,gBAAgB,SAAS,iBAAiB,GAAG,CAAC;AAEjF,OAAI,KACF;IAAE;IAAK,cAAc,OAAO;IAAc,aAAa,OAAO;IAAa,cAAc,UAAU;IAAQ,EAC3G,oBACD;AACD,SAAM,KAAK,4BAA4B,IAAI;AAC3C,UAAO;IACP;;CAGJ,MAAM,QACJ,KACA,UACA,eACA,cACA,OAC2B;EAE3B,MAAM,SAAS,MAAM,KAAK,UAAU,QAAQ,UAAU,cAAc,MAAM;AAC1E,MAAI,OAAO,UACT,OAAM,KAAK,gBAAgB,KAAK,UAAU,OAAO;AAEnD,SAAO;;CAGT,MAAM,mBAAmB,KAAa;EACpC,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,MAAI,CAAC,SACH;AAEF,SAAO;GACL,iBAAiB,SAAS;GAC1B,mBAAmB;GACnB,kBAAkB;GAClB,kBAAkB,KAAA;GACnB;;CAGH,MAAM,0BAA0B,KAAqD;AACnF,uBAAqB;AACrB,SAAO,0BAA0B,IAAI;;CAGvC,MAAM,8BACJ,KACA,cAC4C;AAC5C,uBAAqB;EACrB,MAAM,KAAK,gCAAgC,aAAa;AACxD,MAAI,CAAC,GACH,QAAO;AAET,SAAO,8BAA8B,KAAK,GAAG;;CAG/C,MAAM,4BAA4B,KAAa,cAAqC;AAClF,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;GACrB,MAAM,KAAK,gCAAgC,aAAa;AACxD,OAAI,CAAC,GACH,OAAM,IAAI,MAAM,0BAA0B,eAAe;AAE3D,+BAA4B,KAAK,GAAG;IACpC;;CAGJ,MAAM,cAAc,KAA+B;AACjD,SAAO,KAAK,OAAO,IAAI;;CAGzB,MAAM,KAAK,KAAa,SAA8D;AACpF,SAAO,KAAK,aAAa,KAAK,QAAQ;;CAGxC,MAAM,mBAAmB,MAAc,UAA2C;AAChF,SAAO,KAAK,eAAe,SAAS;;CAGtC,MAAM,gBAAgB,KAAa,SAAqC;EACtE,MAAM,WAAW,MAAM,KAAK,oBAAoB,IAAI;EACpD,MAAM,IAAI,QAAQ,aAAa;AAC/B,SAAO,KAAK,gBACV,SAAS,QAAQ,MAAM,KAAK,mBAAmB,KAAK,eAAe,EAAE,CAAC,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,CAClG;;CAGH,MAAM,cAAc,KAAa,QAAuC;EACtE,MAAM,WAAW,MAAM,KAAK,YAAY,IAAI;AAC5C,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,sBAAsB,MAAM;EAE9C,MAAM,OAAO,MAAM,KAAK,mBAAmB,IAAI;EAC/C,MAAM,WAAW,KAAK,gBAAgB,0BAA0B,KAAK,CAAC;EACtE,MAAM,UAAyB;GAC7B,SAAS;GACT,6BAAY,IAAI,MAAM,EAAC,aAAa;GACpC;GACA;GACA,gBAAgB;GACjB;AACD,MAAI,WAAW,OACb,QAAO,KAAK,UAAU,SAAS,MAAM,EAAE;EAEzC,MAAM,QAAQ;GAAC,KAAK,SAAS,QAAQ,SAAS;GAAO;GAAI,aAAa,QAAQ;GAAc;GAAG;AAC/F,OAAK,MAAM,OAAO,SAChB,OAAM,KAAK,MAAM,IAAI,QAAQ,IAAI,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,KAAK,UAAU,IAAI,QAAQ,EAAE,GAAG;AAEnH,SAAO,MAAM,KAAK,KAAK;;CAGzB,MAAM,oBACJ,WACA,aACmD;AACnD,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;AAErB,OAAI,MADmB,KAAK,YAAY,UAAU,CAEhD,OAAM,IAAI,MAAM,kCAAkC,YAAY;GAGhE,IAAI;AACJ,OAAI;AACF,aAAS,KAAK,MAAM,YAAY;YACzB,KAAK;IACZ,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AACrE,UAAM,IAAI,MAAM,gCAAgC,eAAe;;GAGjE,MAAM,SAAS,UAAU,OAAO,WAAW,WAAW,SAAoC,EAAE;GAC5F,MAAM,aAAa,MAAM,QAAQ,OAAO,eAAe,GAAG,OAAO,iBAAiB,KAAA;GAClF,MAAM,OAAO,aAAa,4BAA4B,WAAW,GAAG,EAAE;AACtE,OAAI,KAAK,WAAW,EAClB,OAAM,IAAI,MAAM,wDAAwD;GAG1E,MAAM,WAAW,OAAO,YAAY,OAAO,OAAO,aAAa,WAC3D,OAAO,WACP,EAAE;AAEN,uBAAoB,WADR,KAAK,oBAAoB,UACH,EAAE;IAClC,eAAe,SAAS;IACxB,cAAc,SAAS;IACvB,aAAa,SAAS;IACtB,SAAS,SAAS;IAClB,YAAY,SAAS;IACtB,CAAC;AACF,yBAAsB,WAAW,KAAK;GAEtC,MAAM,YAAY,OAAO,SAAS,QAAQ,WAAW,SAAS,MAAM,KAAA;GACpE,MAAM,aAAa,OAAO,SAAS,SAAS,WAAW,SAAS,KAAK,MAAM,GAAG;AAC9E,wBAAqB,WAAW;IAC9B,MAAM,aAAa,aAAa,eAAe;IAC/C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAI,MAAM,QAAQ,SAAS,KAAK,GAAG,SAAS,KAAK,QAAQ,QAAuB,OAAO,QAAQ,SAAS,GAAG,EAAE,EAAG,SAAS,CAAC,CAAC;IAC9I,YAAY;KACV,GAAI,SAAS,cAAc,OAAO,SAAS,eAAe,WACtD,SAAS,aACT,EAAE;KACN,GAAI,YAAY,EAAE,wBAAwB,WAAW,GAAG,EAAE;KAC1D,6BAAY,IAAI,MAAM,EAAC,aAAa;KACrC;IACF,CAAC;AACF,UAAO;IAAE,YAAY;IAAW,UAAU,KAAK;IAAQ;IACvD;;CAGJ,MAAM,YACJ,WACA,WACmD;AACnD,SAAO,KAAK,gBAAgB,WAAW,UAAU;;CAGnD,MAAM,gBACJ,WACA,WACA,UAAmC,EAAE,EACc;AACnD,SAAO,KAAK,iBAAiB,YAAY;AACvC,wBAAqB;GACrB,MAAM,iBAAiB,MAAM,KAAK,YAAY,UAAU;AACxD,OAAI,CAAC,eACH,OAAM,IAAI,MAAM,sBAAsB,YAAY;AAGpD,OAAI,MADmB,KAAK,YAAY,UAAU,CAEhD,OAAM,IAAI,MAAM,kCAAkC,YAAY;GAEhE,MAAM,OAAO,MAAM,KAAK,mBAAmB,UAAU;AACrD,OACE,QAAQ,eAAe,KAAA,MACtB,QAAQ,aAAa,KAAK,QAAQ,aAAa,KAAK,QAErD,OAAM,IAAI,MAAM,qBAAqB,QAAQ,aAAa;GAE5D,MAAM,eACJ,QAAQ,eAAe,KAAA,IAAY,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,WAAW,CAAC,CAAC;AAEtG,uBAAoB,WADR,KAAK,oBAAoB,UACH,EAAE;IAClC,eAAe,eAAe;IAC9B,cAAc,eAAe;IAC7B,aAAa,eAAe;IAC5B,SAAS,eAAe;IACxB,YAAY,eAAe;IAC5B,CAAC;AACF,yBAAsB,WAAW,aAAa;AAE9C,wBAAqB,WAAW;IAC9B,MAAM,WAFM,eAAe,MAAM,MAAM,IAAI;IAG3C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAI,eAAe,QAAQ,EAAE,EAAG,OAAO,CAAC,CAAC;IAC5D,YAAY;KACV,GAAI,eAAe,cAAc,EAAE;KACnC,sBAAsB;KACtB,qBAAqB,eAAe;KACpC,GAAI,QAAQ,eAAe,KAAA,IAAY,EAAE,eAAe,aAAa,QAAQ,GAAG,EAAE;KAClF,2BAAU,IAAI,MAAM,EAAC,aAAa;KACnC;IACF,CAAC;AACF,UAAO;IAAE,YAAY;IAAW,UAAU,aAAa;IAAQ;IAC/D;;CAGJ,MAAM,WAAwC;AAC5C,uBAAqB;AACrB,SAAO,uBAAuB;;CAGhC,MAAM,WAAW,eAAwC;EACvD,MAAM,yBAAS,IAAI,MAAM;AACzB,SAAO,QAAQ,OAAO,SAAS,GAAG,cAAc;EAChD,MAAM,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,KAAS,CAAC;EAChD,IAAI,WAAW;AACf,OAAK,MAAM,WAAW,KAAK,MACzB,KAAI,QAAQ,WAAA,cAAqC,QAAQ,WAAA;OAEnD,IADmB,KAAK,QAAQ,eACtB,GAAG,QAAQ;AACvB,UAAM,KAAK,QAAQ,QAAQ,IAAI;AAC/B;;;AAIN,SAAO;;CAGT,eAAe,UAAkC;AAC/C,SAAO,2BAA2B,SAAS;;CAG7C,MAAc,oBAAoB,KAAsC;AACtE,uBAAqB;EACrB,MAAM,cAAc,0BAA0B,IAAI;EAClD,MAAM,UAAmC,EAAE;AAC3C,OAAK,MAAM,cAAc,CAAC,GAAG,YAAY,CAAC,SAAS,CACjD,SAAQ,KAAK,mBAAmB,KAAK,WAAW,GAAG,CAAC;AAEtD,UAAQ,KAAK,MAAM,KAAK,mBAAmB,IAAI,CAAC;EAEhD,MAAM,WAA2B,EAAE;EACnC,MAAM,uBAAO,IAAI,KAAa;AAC9B,OAAK,MAAM,QAAQ,QACjB,MAAK,MAAM,WAAW,4BAA4B,KAAK,EAAE;AACvD,OAAI,KAAK,2BAA2B,QAAQ,CAC1C;GAEF,MAAM,WAAW,KAAK,uBAAuB,QAAQ;AACrD,OAAI,KAAK,IAAI,SAAS,CACpB;AAEF,QAAK,IAAI,SAAS;AAClB,YAAS,KAAK,QAAQ;;AAG1B,SAAO;;CAGT,wBACE,UACA,UAII,EAAE,EAC6E;EACnF,MAAM,QAAQ,SAAS;EACvB,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,SAAS,GAAG,CAAC,CAAC;EACzE,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,UAAU,EAAE,CAAC;EAE3D,IAAI;EACJ,IAAI;AACJ,MAAI,QAAQ,mBAAmB,KAAA,KAAa,OAAO,SAAS,QAAQ,eAAe,EAAE;AACnF,cAAW,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,eAAe,CAAC,CAAC;AAC3E,gBAAa,KAAK,IAAI,GAAG,WAAW,MAAM;SACrC;AACL,cAAW,KAAK,IAAI,GAAG,QAAQ,OAAO;AACtC,gBAAa,KAAK,IAAI,GAAG,WAAW,MAAM;;AAG5C,SAAO;GACL,UAAU,SAAS,MAAM,YAAY,SAAS;GAC9C;GACA;GACA;GACD;;CAGH,uBAA+B,SAA+B;EAC5D,MAAM,SAAS;AACf,SAAO,KAAK,UAAU;GACpB,MAAM,QAAQ;GACd,WAAW,OAAO;GAClB,YAAY,OAAO,cAAc,OAAO;GACxC,UAAU,OAAO;GACjB,SAAS,KAAK,eAAe,QAAQ;GACtC,CAAC;;CAGJ,eAAuB,KAA4B;AACjD,SAAQ,IAA8B;;CAGxC,2BAAmC,KAA4B;AAC7D,MAAI,IAAI,SAAS,OACf,QAAO;EAET,MAAM,OAAO,KAAK,mBAAmB,KAAK,eAAe,IAAI,CAAC,CAAC,MAAM;AACrE,SAAO,sCAAsC,KAAK,KAAK;;CAGzD,mBAA2B,SAA0B;AACnD,MAAI,OAAO,YAAY,SACrB,QAAO;AAET,MAAI,MAAM,QAAQ,QAAQ,EAAE;GAC1B,MAAM,QAAkB,EAAE;AAC1B,QAAK,MAAM,QAAQ,SAAS;AAC1B,QAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,EAAE,UAAU,MAC3D;IAEF,MAAM,IAAI;AACV,QAAI,EAAE,SAAS,UAAU,OAAO,EAAE,SAAS,SACzC,OAAM,KAAK,EAAE,KAAK;aACT,EAAE,SAAS,cAAc,EAAE,SAAS,WAC7C,OAAM,KAAK,EAAE,OAAO,IAAI,EAAE,KAAK,KAAK,GAAG;;AAG3C,UAAO,MAAM,KAAK,GAAG;;AAEvB,SAAO;;CAGT,MAAc,4BAA4B,KAA4B;EACpE,MAAM,cAAc,0BAA0B;GAC5C,KAAK,KAAK,QAAQ;GAClB,YAAY;GACb,CAAC;AACF,MAAI,CAAC,aAAa,MAAM,CACtB;AAEF,MAAI;AACF,SAAM,KAAK,6BAA6B,KAAK;IAC3C,IAAI,mBAAmB,KAAK,KAAK;IACjC,MAAM;IACN,4BAAW,IAAI,MAAM,EAAC,aAAa;IACpC,CAAC;WACK,KAAK;AACZ,OAAI,KAAK;IAAE;IAAK;IAAK,EAAE,2CAA2C;;;CAItE,gBAAwB,UAAqC;AAC3D,SAAO,SAAS,KAAK,MAA8C;GACjE,MAAM,IAAI,KAAK,eAAe,EAAE;GAChC,MAAM,UACJ,OAAO,MAAM,WAAW,IAAI,MAAM,QAAQ,EAAE,GAAG,IAAI,KAAK,mBAAmB,EAAE;GAC/E,MAAM,MAAe;IACnB,MAAM,EAAE;IACR;IACA,WAAW,EAAE,YAAY,IAAI,KAAK,EAAE,UAA6B,CAAC,aAAa,GAAG,KAAA;IAClF,cAAe,EAAE,gBAAwC,EAAE;IAC3D,YAAY,EAAE;IACd,MAAM,EAAE;IACT;AACD,OAAI,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,MAAM,SAAS,EAC7C,KAAI,QAAQ,EAAE;GAEhB,MAAM,WAAW,EAAE;AAQnB,OAAI,YAAY,OAAO,aAAa,UAAU;IAC5C,MAAM,cAAc,OAAO,SAAS,UAAU,WAAW,SAAS,QAAQ,KAAA;IAC1E,MAAM,eAAe,OAAO,SAAS,WAAW,WAAW,SAAS,SAAS,KAAA;IAC7E,MAAM,kBAAkB,OAAO,SAAS,cAAc,WAAW,SAAS,YAAY,KAAA;IACtF,MAAM,mBAAmB,OAAO,SAAS,eAAe,WAAW,SAAS,aAAa,KAAA;IACzF,MAAM,cAAc,OAAO,SAAS,gBAAgB,WAChD,SAAS,cACT,OAAO,SAAS,UAAU,WACxB,SAAS,QACT,KAAA;AACN,QACE,gBAAgB,KAAA,KAChB,iBAAiB,KAAA,KACjB,oBAAoB,KAAA,KACpB,qBAAqB,KAAA,KACrB,gBAAgB,KAAA,EAEhB,KAAI,QAAQ;KACV;KACA;KACA;KACA;KACA;KACD;;AAGL,UAAO;IACP"}
|
|
1
|
+
{"version":3,"file":"store.js","names":[],"sources":["../../../src/session/store.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config } from '../config/schema.js';\nimport { resolveStateDir } from '../config/paths-state.js';\nimport { resolveEffectiveAgentProfileForSession } from '../config/agent-profile.js';\nimport { readPostCompactionContext } from '../agent/reply/post-compaction-context.js';\nimport { createLogger } from '../utils/logger.js';\nimport { SessionCompactor, type CompactionConfig, type CompactionResult } from '../agent/memory/compaction.js';\nimport { SlidingWindow, type WindowConfig } from '../agent/memory/window.js';\nimport {\n requireXopcDatabase,\n appendTranscriptEntry,\n captureCompactionCheckpoint,\n deleteSessionRecord,\n ensureSessionRecord,\n estimateTokensFromMessages,\n getCompactionCheckpointDetail,\n getGlobalSessionStats,\n getSessionMetadata,\n findSessionKeyBySessionId,\n listCompactionCheckpoints,\n listSessionMetadata,\n listSessionsByAgent,\n loadCheckpointRows,\n loadLlmMessagesForSession,\n paginateTranscriptMessages,\n loadTranscriptRowsForSession,\n patchSessionMetadata,\n replaceTranscriptRows,\n resetSessionRecord,\n restoreCompactionCheckpoint,\n type SessionMetadataSeed,\n} from '../storage/sqlite/index.js';\nimport type { TranscriptCompactionRecord, XopcSessionTranscriptV1 } from './transcript-format.js';\nimport {\n buildSessionDisplayMessages,\n buildSessionContextForLlm,\n mergeLlmMessagesPreservingContextRows,\n transcriptRowsFromJsonArray,\n type TranscriptStoredRow,\n type XopcTranscriptContextEntry,\n type XopcTranscriptCustomMessageEntry,\n type XopcTranscriptCustomStateEntry,\n} from './session-context-for-llm.js';\nimport { normalizeCompactionCheckpointId } from './compaction-checkpoints.js';\nimport type {\n SessionMetadata,\n SessionDetail,\n SessionListQuery,\n PaginatedResult,\n GlobalSessionStats,\n ExportFormat,\n SessionExport,\n SessionTranscriptSummary,\n CompactionCheckpointSummary,\n CompactionCheckpointDetail,\n} from './types.js';\nimport { SessionStatus } from './types.js';\nimport type { Message } from './types.js';\nimport type { SessionTranscriptUpdate } from './transcript-events.js';\nimport { isAppendOnlyLlmTranscriptMessage } from './transcript-stats.js';\nimport { transcriptRowsToClientHistory } from './client-history.js';\n\nconst log = createLogger('SessionStore');\n\nconst INDEX_VERSION = '1.0';\n\nexport interface SessionStoreOptions {\n config: Config;\n}\n\nexport class SessionStore {\n private window: SlidingWindow;\n private compactor: SessionCompactor;\n\n constructor(\n private options: SessionStoreOptions,\n windowConfig?: Partial<WindowConfig>,\n compactionConfig?: Partial<CompactionConfig>,\n ) {\n this.window = new SlidingWindow(windowConfig);\n this.compactor = new SessionCompactor(compactionConfig);\n }\n\n private resolveWorkspaceCwd(sessionKey: string): string {\n return resolveEffectiveAgentProfileForSession(this.options.config, sessionKey).resolvedWorkspacePath;\n }\n\n private async runStoreMutation<T>(fn: () => Promise<T>): Promise<T> {\n return fn();\n }\n\n async initialize(): Promise<void> {\n requireXopcDatabase();\n log.debug('Session store initialized (SQLite)');\n }\n\n getSessionsRoot(): string {\n return resolveStateDir();\n }\n\n async resolveTranscriptPath(\n sessionKey: string,\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<{ sessionId: string; sessionKey: string }> {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n const meta = ensureSessionRecord(sessionKey, cwd, options?.metadata);\n return { sessionId: meta.sessionId!, sessionKey };\n }\n\n async appendTranscriptMessage(\n sessionKey: string,\n message: AgentMessage,\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n ensureSessionRecord(sessionKey, cwd, options?.metadata);\n appendTranscriptEntry(sessionKey, message);\n });\n }\n\n async getByAgent(agentId: string): Promise<SessionMetadata[]> {\n requireXopcDatabase();\n return listSessionsByAgent(agentId);\n }\n\n async getByAccount(accountId: string): Promise<SessionMetadata[]> {\n const { items } = await this.list({ limit: 100_000 });\n return items.filter((m) => m.routing?.accountId === accountId);\n }\n\n async getByPeer(peerKind: string, peerId: string): Promise<SessionMetadata[]> {\n const { items } = await this.list({ limit: 100_000 });\n return items.filter((m) => m.routing?.peerKind === peerKind && m.routing.peerId === peerId);\n }\n\n async getMainSession(channel: string, accountId: string): Promise<SessionMetadata | null> {\n const { items } = await this.list({ limit: 100_000 });\n return (\n items.find(\n (m) =>\n m.routing?.source === channel &&\n m.routing.accountId === accountId &&\n m.routing.peerKind === 'dm' &&\n m.routing.peerId === 'main',\n ) ?? null\n );\n }\n\n async refreshIndex(): Promise<void> {\n /* no-op: SQLite is authoritative */\n }\n\n async list(query: SessionListQuery = {}): Promise<PaginatedResult<SessionMetadata>> {\n requireXopcDatabase();\n return listSessionMetadata(query);\n }\n\n async get(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return null;\n }\n const messages = await this.loadDisplayMessages(key);\n return this.buildSessionDetail(key, metadata, messages, options);\n }\n\n async getMessagePage(\n key: string,\n options: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n includeContextRows?: boolean;\n } = {},\n ): Promise<{\n session: SessionDetail;\n pagination: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n before?: string;\n nextBeforeCursor?: string;\n };\n } | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return null;\n }\n\n const limit = Math.min(200, Math.max(1, Math.trunc(options.limit ?? 50)));\n const offset = Math.max(0, Math.trunc(options.offset ?? 0));\n const parsedBefore = options.before ? Number.parseInt(options.before, 10) : undefined;\n const hasBeforeCursor = parsedBefore !== undefined && Number.isFinite(parsedBefore);\n\n if (options.includeContextRows) {\n const page = paginateTranscriptMessages(key, {\n limit,\n offset: hasBeforeCursor ? undefined : offset,\n beforeEndIndex: hasBeforeCursor ? parsedBefore : undefined,\n includeContext: true,\n });\n const messages = transcriptRowsToClientHistory(page.rows) as unknown as Message[];\n const endIndex = hasBeforeCursor\n ? Math.min(page.total, Math.max(0, parsedBefore!))\n : Math.max(0, page.total - offset);\n const startIndex = Math.max(0, endIndex - page.rows.length);\n const session: SessionDetail = {\n ...metadata,\n messages,\n ...(options.includeTranscriptRows ? { transcriptRows: await this.loadTranscriptRows(key) } : {}),\n };\n const nextBeforeCursor = startIndex > 0 ? String(startIndex) : undefined;\n return {\n session,\n pagination: {\n total: page.total,\n limit,\n offset,\n hasMore: hasBeforeCursor ? startIndex > 0 : offset + limit < page.total,\n ...(hasBeforeCursor ? { before: String(endIndex) } : {}),\n ...(nextBeforeCursor ? { nextBeforeCursor } : {}),\n },\n };\n }\n\n const displayMessages = await this.loadDisplayMessages(key);\n const page = this.paginateDisplayMessages(displayMessages, {\n limit,\n offset: hasBeforeCursor ? undefined : offset,\n beforeEndIndex: hasBeforeCursor ? parsedBefore : undefined,\n });\n\n const session = await this.buildSessionDetail(key, metadata, page.messages, options);\n const nextBeforeCursor = page.startIndex > 0 ? String(page.startIndex) : undefined;\n\n return {\n session,\n pagination: {\n total: page.total,\n limit,\n offset,\n hasMore: hasBeforeCursor ? page.startIndex > 0 : offset + limit < page.total,\n ...(hasBeforeCursor ? { before: String(page.endIndex) } : {}),\n ...(nextBeforeCursor ? { nextBeforeCursor } : {}),\n },\n };\n }\n\n private async buildSessionDetail(\n key: string,\n metadata: SessionMetadata,\n messages: AgentMessage[],\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail> {\n let transcriptSummary: SessionTranscriptSummary | undefined;\n if (options?.includeTranscriptSummary) {\n const env = await this.loadTranscriptDocument(key);\n if (env) {\n transcriptSummary = {\n id: env.id,\n version: env.version,\n createdAt: env.createdAt,\n updatedAt: env.updatedAt,\n compactionCount: env.compactions?.length ?? 0,\n };\n }\n }\n let transcriptRows: TranscriptStoredRow[] | undefined;\n if (options?.includeTranscriptRows) {\n transcriptRows = await this.loadTranscriptRows(key);\n }\n return {\n ...metadata,\n messages: this.convertMessages(messages),\n ...(transcriptSummary ? { transcriptSummary } : {}),\n ...(transcriptRows !== undefined ? { transcriptRows } : {}),\n };\n }\n\n async loadTranscriptRows(key: string): Promise<TranscriptStoredRow[]> {\n requireXopcDatabase();\n return loadTranscriptRowsForSession(key);\n }\n\n async getMetadata(key: string): Promise<SessionMetadata | null> {\n requireXopcDatabase();\n return getSessionMetadata(key);\n }\n\n async resolveKeyBySessionId(sessionId: string): Promise<string | null> {\n requireXopcDatabase();\n return findSessionKeyBySessionId(sessionId);\n }\n\n async updateMetadata(key: string, updates: Partial<SessionMetadata>): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n patchSessionMetadata(key, updates);\n log.debug({ key, updates }, 'Session metadata updated');\n });\n }\n\n async reset(key: string): Promise<{ sessionId: string; previousSessionId: string } | null> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n const outcome = resetSessionRecord(key, cwd);\n if (outcome) {\n log.info({ key, ...outcome }, 'Session reset');\n }\n return outcome;\n });\n }\n\n async delete(key: string): Promise<boolean> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const ok = deleteSessionRecord(key);\n if (ok) {\n log.info({ key }, 'Session deleted');\n }\n return ok;\n });\n }\n\n async deleteMany(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n const success: string[] = [];\n const failed: string[] = [];\n for (const key of keys) {\n try {\n if (await this.delete(key)) {\n success.push(key);\n } else {\n failed.push(key);\n }\n } catch {\n failed.push(key);\n }\n }\n return { success, failed };\n }\n\n async setStatus(key: string, status: SessionStatus): Promise<void> {\n await this.updateMetadata(key, { status });\n }\n\n async archive(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ARCHIVED);\n }\n\n async unarchive(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ACTIVE);\n }\n\n async pin(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.PINNED);\n }\n\n async unpin(key: string): Promise<void> {\n await this.setStatus(key, SessionStatus.ACTIVE);\n }\n\n async loadMessages(_key: string, _options?: { fromArchive?: boolean }): Promise<AgentMessage[]> {\n requireXopcDatabase();\n return loadLlmMessagesForSession(_key);\n }\n\n async loadTranscriptDocument(key: string): Promise<XopcSessionTranscriptV1 | null> {\n const metadata = await this.getMetadata(key);\n if (!metadata?.sessionId) {\n return null;\n }\n const rows = await this.loadTranscriptRows(key);\n const compactions: TranscriptCompactionRecord[] = [];\n for (const row of rows) {\n if ((row as { type?: string }).type === 'compaction') {\n const c = row as unknown as TranscriptCompactionRecord & { type: 'compaction' };\n compactions.push({\n at: c.at ?? new Date().toISOString(),\n summary: c.summary ?? '',\n firstKeptIndex: Number(c.firstKeptIndex ?? 0),\n tokensBefore: c.tokensBefore ?? 0,\n tokensAfter: (c as { tokensAfter?: number }).tokensAfter ?? 0,\n });\n }\n }\n return {\n type: 'xopc_session_transcript',\n version: 1,\n id: metadata.sessionId,\n createdAt: metadata.createdAt,\n updatedAt: metadata.updatedAt,\n messages: rows,\n ...(compactions.length > 0 ? { compactions } : {}),\n };\n }\n\n async syncEmbeddedTranscriptUpdate(update: SessionTranscriptUpdate): Promise<void> {\n const sessionKey = update.sessionKey?.trim();\n if (!sessionKey) {\n return;\n }\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(sessionKey);\n ensureSessionRecord(sessionKey, cwd);\n\n if (update.message && isAppendOnlyLlmTranscriptMessage(update.message)) {\n appendTranscriptEntry(sessionKey, update.message as AgentMessage);\n }\n });\n }\n\n async appendTranscriptContextEntry(\n key: string,\n entry: Omit<XopcTranscriptContextEntry, 'kind'> & Partial<Pick<XopcTranscriptContextEntry, 'kind'>>,\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptContextEntry = {\n kind: 'context',\n id: typeof entry.id === 'string' ? entry.id : undefined,\n text: typeof entry.text === 'string' ? entry.text : undefined,\n data: entry.data,\n createdAt: entry.createdAt ?? new Date().toISOString(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptLabelEntry(\n key: string,\n entry: { targetId: string; label?: string },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n appendTranscriptEntry(key, {\n type: 'label',\n targetId: entry.targetId,\n label: entry.label?.trim() || undefined,\n timestamp: new Date().toISOString(),\n });\n });\n }\n\n async appendTranscriptCustomEntry(\n key: string,\n entry: { customType: string; data?: unknown },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptCustomStateEntry = {\n type: 'custom',\n customType: entry.customType.trim(),\n data: entry.data,\n timestamp: new Date().toISOString(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptCustomMessageEntry(\n key: string,\n entry: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n const row: XopcTranscriptCustomMessageEntry = {\n role: 'custom',\n customType: entry.customType.trim(),\n content: entry.content ?? '',\n display: entry.display ?? true,\n details: entry.details,\n timestamp: Date.now(),\n };\n appendTranscriptEntry(key, row);\n });\n }\n\n async appendTranscriptBashExecutionEntry(\n key: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd);\n appendTranscriptEntry(key, {\n role: 'bashExecution',\n command: entry.command,\n output: entry.output ?? '',\n exitCode: entry.exitCode ?? null,\n signal: entry.signal ?? null,\n excludeFromContext: entry.excludeFromContext === true,\n truncated: entry.truncated === true,\n fullOutputPath: entry.fullOutputPath,\n timestamp: Date.now(),\n });\n });\n }\n\n async saveMessages(\n key: string,\n messages: AgentMessage[],\n options?: { metadata?: SessionMetadataSeed },\n ): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const cwd = this.resolveWorkspaceCwd(key);\n ensureSessionRecord(key, cwd, options?.metadata);\n const prev = await this.loadTranscriptRows(key);\n const merged = mergeLlmMessagesPreservingContextRows(prev, messages);\n replaceTranscriptRows(key, merged);\n });\n }\n\n getWindowStats(messages: AgentMessage[]) {\n return this.window.getStats(messages);\n }\n\n needsCompaction(key: string, messages: AgentMessage[], contextWindow: number) {\n return this.compactor.needsCompaction(messages, contextWindow);\n }\n\n prepareCompaction(key: string, messages: AgentMessage[], contextWindow: number) {\n const result = this.compactor.needsCompaction(messages, contextWindow);\n return { needsCompaction: result.needed, messages, stats: result };\n }\n\n async applyCompaction(\n key: string,\n messages: AgentMessage[],\n result: CompactionResult,\n ): Promise<AgentMessage[]> {\n const compacted = this.compactor.applyCompaction(messages, result);\n return this.runStoreMutation(async () => {\n const prev = await this.loadTranscriptRows(key);\n const merged = mergeLlmMessagesPreservingContextRows(prev, compacted);\n captureCompactionCheckpoint(key);\n replaceTranscriptRows(key, merged, {\n appendCompaction: {\n at: new Date().toISOString(),\n summary: result.summary,\n firstKeptIndex: result.firstKeptIndex,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n },\n });\n const metadata = await this.getMetadata(key);\n if (metadata) {\n await this.updateMetadata(key, { compactedCount: metadata.compactedCount + 1 });\n }\n log.info(\n { key, tokensBefore: result.tokensBefore, tokensAfter: result.tokensAfter, keptMessages: compacted.length },\n 'Session compacted',\n );\n await this.injectPostCompactionContext(key);\n return compacted;\n });\n }\n\n async compact(\n key: string,\n messages: AgentMessage[],\n contextWindow: number,\n instructions?: string,\n force?: boolean,\n ): Promise<CompactionResult> {\n void contextWindow;\n const result = await this.compactor.compact(messages, instructions, force);\n if (result.compacted) {\n await this.applyCompaction(key, messages, result);\n }\n return result;\n }\n\n async getCompactionStats(key: string) {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n return undefined;\n }\n return {\n compactionCount: metadata.compactedCount,\n totalTokensBefore: 0,\n totalTokensAfter: 0,\n lastCompactionAt: undefined,\n };\n }\n\n async listCompactionCheckpoints(key: string): Promise<CompactionCheckpointSummary[]> {\n requireXopcDatabase();\n return listCompactionCheckpoints(key);\n }\n\n async getCompactionCheckpointDetail(\n key: string,\n checkpointId: string,\n ): Promise<CompactionCheckpointDetail | null> {\n requireXopcDatabase();\n const id = normalizeCompactionCheckpointId(checkpointId);\n if (!id) {\n return null;\n }\n return getCompactionCheckpointDetail(key, id);\n }\n\n async restoreCompactionCheckpoint(key: string, checkpointId: string): Promise<void> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const id = normalizeCompactionCheckpointId(checkpointId);\n if (!id) {\n throw new Error(`Invalid checkpoint id: ${checkpointId}`);\n }\n restoreCompactionCheckpoint(key, id);\n });\n }\n\n async deleteSession(key: string): Promise<boolean> {\n return this.delete(key);\n }\n\n async load(key: string, options?: { fromArchive?: boolean }): Promise<AgentMessage[]> {\n return this.loadMessages(key, options);\n }\n\n async estimateTokenUsage(_key: string, messages: AgentMessage[]): Promise<number> {\n return this.estimateTokens(messages);\n }\n\n async searchInSession(key: string, keyword: string): Promise<Message[]> {\n const messages = await this.loadDisplayMessages(key);\n const q = keyword.toLowerCase();\n return this.convertMessages(\n messages.filter((m) => this.extractTextContent(this.messageContent(m)).toLowerCase().includes(q)),\n );\n }\n\n async exportSession(key: string, format: ExportFormat): Promise<string> {\n const metadata = await this.getMetadata(key);\n if (!metadata) {\n throw new Error(`Session not found: ${key}`);\n }\n const rows = await this.loadTranscriptRows(key);\n const messages = this.convertMessages(buildSessionContextForLlm(rows));\n const payload: SessionExport = {\n version: INDEX_VERSION,\n exportedAt: new Date().toISOString(),\n metadata,\n messages,\n transcriptRows: rows,\n };\n if (format === 'json') {\n return JSON.stringify(payload, null, 2);\n }\n const lines = [`# ${metadata.name ?? metadata.key}`, '', `Exported: ${payload.exportedAt}`, ''];\n for (const msg of messages) {\n lines.push(`## ${msg.role}`, '', typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), '');\n }\n return lines.join('\\n');\n }\n\n async importSessionExport(\n targetKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const existing = await this.getMetadata(targetKey);\n if (existing) {\n throw new Error(`Target session already exists: ${targetKey}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonContent);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n throw new Error(`Invalid session export JSON: ${errorMessage}`);\n }\n\n const record = parsed && typeof parsed === 'object' ? parsed as Record<string, unknown> : {};\n const rowsSource = Array.isArray(record.transcriptRows) ? record.transcriptRows : undefined;\n const rows = rowsSource ? transcriptRowsFromJsonArray(rowsSource) : [];\n if (rows.length === 0) {\n throw new Error('Session export contains no importable transcript rows');\n }\n\n const metadata = record.metadata && typeof record.metadata === 'object'\n ? record.metadata as Partial<SessionMetadata>\n : {};\n const cwd = this.resolveWorkspaceCwd(targetKey);\n ensureSessionRecord(targetKey, cwd, {\n sourceChannel: metadata.sourceChannel,\n sourceChatId: metadata.sourceChatId,\n sessionType: metadata.sessionType,\n routing: metadata.routing,\n customData: metadata.customData,\n });\n replaceTranscriptRows(targetKey, rows);\n\n const sourceKey = typeof metadata.key === 'string' ? metadata.key : undefined;\n const sourceName = typeof metadata.name === 'string' ? metadata.name.trim() : '';\n patchSessionMetadata(targetKey, {\n name: sourceName ? `Import of ${sourceName}` : 'Imported session',\n tags: [...new Set([...(Array.isArray(metadata.tags) ? metadata.tags.filter((tag): tag is string => typeof tag === 'string') : []), 'import'])],\n customData: {\n ...(metadata.customData && typeof metadata.customData === 'object'\n ? metadata.customData as Record<string, unknown>\n : {}),\n ...(sourceKey ? { importedFromSessionKey: sourceKey } : {}),\n importedAt: new Date().toISOString(),\n },\n });\n return { sessionKey: targetKey, rowCount: rows.length };\n });\n }\n\n async forkSession(\n sourceKey: string,\n targetKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.forkSessionRows(sourceKey, targetKey);\n }\n\n async forkSessionRows(\n sourceKey: string,\n targetKey: string,\n options: { throughRow?: number } = {},\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.runStoreMutation(async () => {\n requireXopcDatabase();\n const sourceMetadata = await this.getMetadata(sourceKey);\n if (!sourceMetadata) {\n throw new Error(`Session not found: ${sourceKey}`);\n }\n const existing = await this.getMetadata(targetKey);\n if (existing) {\n throw new Error(`Target session already exists: ${targetKey}`);\n }\n const rows = await this.loadTranscriptRows(sourceKey);\n if (\n options.throughRow !== undefined &&\n (options.throughRow < 1 || options.throughRow > rows.length)\n ) {\n throw new Error(`Invalid fork row: ${options.throughRow}`);\n }\n const selectedRows =\n options.throughRow === undefined ? rows : rows.slice(0, Math.max(0, Math.trunc(options.throughRow)));\n const cwd = this.resolveWorkspaceCwd(targetKey);\n ensureSessionRecord(targetKey, cwd, {\n sourceChannel: sourceMetadata.sourceChannel,\n sourceChatId: sourceMetadata.sourceChatId,\n sessionType: sourceMetadata.sessionType,\n routing: sourceMetadata.routing,\n customData: sourceMetadata.customData,\n });\n replaceTranscriptRows(targetKey, selectedRows);\n const label = sourceMetadata.name?.trim() || sourceKey;\n patchSessionMetadata(targetKey, {\n name: `Fork of ${label}`,\n tags: [...new Set([...(sourceMetadata.tags ?? []), 'fork'])],\n customData: {\n ...(sourceMetadata.customData ?? {}),\n forkedFromSessionKey: sourceKey,\n forkedFromSessionId: sourceMetadata.sessionId,\n ...(options.throughRow !== undefined ? { forkedFromRow: selectedRows.length } : {}),\n forkedAt: new Date().toISOString(),\n },\n });\n return { sessionKey: targetKey, rowCount: selectedRows.length };\n });\n }\n\n async getStats(): Promise<GlobalSessionStats> {\n requireXopcDatabase();\n return getGlobalSessionStats();\n }\n\n async archiveOld(olderThanDays: number): Promise<number> {\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - olderThanDays);\n const list = await this.list({ limit: 100_000 });\n let archived = 0;\n for (const session of list.items) {\n if (session.status !== SessionStatus.ARCHIVED && session.status !== SessionStatus.PINNED) {\n const lastAccess = new Date(session.lastAccessedAt);\n if (lastAccess < cutoff) {\n await this.archive(session.key);\n archived++;\n }\n }\n }\n return archived;\n }\n\n estimateTokens(messages: AgentMessage[]): number {\n return estimateTokensFromMessages(messages);\n }\n\n private async loadDisplayMessages(key: string): Promise<AgentMessage[]> {\n requireXopcDatabase();\n const checkpoints = listCompactionCheckpoints(key);\n const rowSets: TranscriptStoredRow[][] = [];\n for (const checkpoint of [...checkpoints].reverse()) {\n rowSets.push(loadCheckpointRows(key, checkpoint.id));\n }\n rowSets.push(await this.loadTranscriptRows(key));\n\n const messages: AgentMessage[] = [];\n const seen = new Set<string>();\n for (const rows of rowSets) {\n for (const message of buildSessionDisplayMessages(rows)) {\n if (this.isCompactionSummaryMessage(message)) {\n continue;\n }\n const identity = this.displayMessageIdentity(message);\n if (seen.has(identity)) {\n continue;\n }\n seen.add(identity);\n messages.push(message);\n }\n }\n return messages;\n }\n\n private paginateDisplayMessages(\n messages: AgentMessage[],\n options: {\n offset?: number;\n limit?: number;\n beforeEndIndex?: number;\n } = {},\n ): { messages: AgentMessage[]; total: number; startIndex: number; endIndex: number } {\n const total = messages.length;\n const limit = Math.min(200, Math.max(1, Math.trunc(options.limit ?? 50)));\n const offset = Math.max(0, Math.trunc(options.offset ?? 0));\n\n let startIndex: number;\n let endIndex: number;\n if (options.beforeEndIndex !== undefined && Number.isFinite(options.beforeEndIndex)) {\n endIndex = Math.min(total, Math.max(0, Math.trunc(options.beforeEndIndex)));\n startIndex = Math.max(0, endIndex - limit);\n } else {\n endIndex = Math.max(0, total - offset);\n startIndex = Math.max(0, endIndex - limit);\n }\n\n return {\n messages: messages.slice(startIndex, endIndex),\n total,\n startIndex,\n endIndex,\n };\n }\n\n private displayMessageIdentity(message: AgentMessage): string {\n const record = message as unknown as Record<string, unknown>;\n return JSON.stringify({\n role: message.role,\n timestamp: record.timestamp,\n toolCallId: record.toolCallId ?? record.tool_call_id,\n toolName: record.toolName,\n content: this.messageContent(message),\n });\n }\n\n private messageContent(msg: AgentMessage): unknown {\n return (msg as { content?: unknown }).content;\n }\n\n private isCompactionSummaryMessage(msg: AgentMessage): boolean {\n if (msg.role !== 'user') {\n return false;\n }\n const text = this.extractTextContent(this.messageContent(msg)).trim();\n return /^\\[Previous conversation summary\\]/i.test(text);\n }\n\n private extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const item of content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) {\n continue;\n }\n const c = item as { type?: string; text?: string; name?: string };\n if (c.type === 'text' && typeof c.text === 'string') {\n parts.push(c.text);\n } else if (c.type === 'toolCall' || c.type === 'tool_use') {\n parts.push(c.name ? `[${c.name}]` : '');\n }\n }\n return parts.join('');\n }\n return '';\n }\n\n private async injectPostCompactionContext(key: string): Promise<void> {\n const contextText = readPostCompactionContext({\n cfg: this.options.config,\n sessionKey: key,\n });\n if (!contextText?.trim()) {\n return;\n }\n try {\n await this.appendTranscriptContextEntry(key, {\n id: `post-compaction-${Date.now()}`,\n text: contextText,\n createdAt: new Date().toISOString(),\n });\n } catch (err) {\n log.warn({ err, key }, 'Post-compaction context injection failed');\n }\n }\n\n private convertMessages(messages: AgentMessage[]): Message[] {\n return messages.map((m: AgentMessage & Record<string, unknown>) => {\n const c = this.messageContent(m);\n const content: string | unknown[] =\n typeof c === 'string' ? c : Array.isArray(c) ? c : this.extractTextContent(c);\n const row: Message = {\n role: m.role as Message['role'],\n content,\n timestamp: m.timestamp ? new Date(m.timestamp as string | number).toISOString() : undefined,\n tool_call_id: (m.tool_call_id as string | undefined) || (m.toolCallId as string | undefined),\n tool_calls: m.tool_calls as Message['tool_calls'],\n name: m.name as string | undefined,\n };\n if (Array.isArray(m.media) && m.media.length > 0) {\n row.media = m.media as Message['media'];\n }\n const rawUsage = m.usage as {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n totalTokens?: number;\n total?: number;\n } | undefined;\n if (rawUsage && typeof rawUsage === 'object') {\n const inputTokens = typeof rawUsage.input === 'number' ? rawUsage.input : undefined;\n const outputTokens = typeof rawUsage.output === 'number' ? rawUsage.output : undefined;\n const cacheReadTokens = typeof rawUsage.cacheRead === 'number' ? rawUsage.cacheRead : undefined;\n const cacheWriteTokens = typeof rawUsage.cacheWrite === 'number' ? rawUsage.cacheWrite : undefined;\n const totalTokens = typeof rawUsage.totalTokens === 'number'\n ? rawUsage.totalTokens\n : typeof rawUsage.total === 'number'\n ? rawUsage.total\n : undefined;\n if (\n inputTokens !== undefined ||\n outputTokens !== undefined ||\n cacheReadTokens !== undefined ||\n cacheWriteTokens !== undefined ||\n totalTokens !== undefined\n ) {\n row.usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n totalTokens,\n };\n }\n }\n return row;\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -14,9 +14,9 @@ import { inferSuggestedProjectDefaultAgentId } from "../../projects/project-agen
|
|
|
14
14
|
import "../../projects/index.js";
|
|
15
15
|
import { evictEmbeddedSessionRunner } from "../../agent/embedded/session-runner.js";
|
|
16
16
|
import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
|
|
17
|
-
import { SessionIndex } from "../../session/manager.js";
|
|
18
17
|
import { buildSessionTimeline } from "../../session/transcript-outline.js";
|
|
19
18
|
import { transcriptRowsToClientHistory } from "../../session/client-history.js";
|
|
19
|
+
import { SessionIndex } from "../../session/manager.js";
|
|
20
20
|
import "../../session/index.js";
|
|
21
21
|
import { parseModelRef } from "../../agent/models/selection.js";
|
|
22
22
|
import { buildReviewContext, resolveGitRoot } from "../../review/review-git.js";
|
|
@@ -28,8 +28,16 @@ function isMechanicalToolSummaryLine(line) {
|
|
|
28
28
|
}
|
|
29
29
|
function reviewMarkdown(block) {
|
|
30
30
|
const findings = Array.isArray(block.findings) ? block.findings : [];
|
|
31
|
-
const lines = [
|
|
32
|
-
|
|
31
|
+
const lines = [
|
|
32
|
+
"<< Code review finished >>",
|
|
33
|
+
"",
|
|
34
|
+
"Code review",
|
|
35
|
+
""
|
|
36
|
+
];
|
|
37
|
+
const source = typeof block.source === "string" ? block.source : "";
|
|
38
|
+
const correctness = typeof block.overallCorrectness === "string" ? block.overallCorrectness : "unknown";
|
|
39
|
+
const modelReviewIncomplete = source === "local" && correctness === "unknown";
|
|
40
|
+
if (findings.length === 0) lines.push(modelReviewIncomplete ? "No model findings were produced." : "No findings.");
|
|
33
41
|
else {
|
|
34
42
|
lines.push("Findings:");
|
|
35
43
|
for (const item of findings) {
|
|
@@ -47,7 +55,6 @@ function reviewMarkdown(block) {
|
|
|
47
55
|
if (body) lines.push(` ${body.replace(/\n+/g, "\n ")}`);
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
|
-
const correctness = typeof block.overallCorrectness === "string" ? block.overallCorrectness : "unknown";
|
|
51
58
|
const explanation = typeof block.overallExplanation === "string" ? block.overallExplanation : "";
|
|
52
59
|
lines.push("");
|
|
53
60
|
lines.push(`Overall correctness: ${correctness}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction compactToolAdjacentText(text: string, linkedToolCall: boolean): string {\n if (!linkedToolCall) return text;\n const lines = text.split('\\n');\n const kept = lines.filter((line) => !isMechanicalToolSummaryLine(line));\n return kept.join('\\n').trim();\n}\n\nfunction isMechanicalToolSummaryLine(line: string): boolean {\n const normalized = line.trim();\n if (!normalized) return false;\n const withoutBullet = normalized.replace(/^[-*•]\\s+/, '');\n return (\n /^(Added|Deleted|Edited|Modified|Updated)\\s+.+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Edited\\s+\\d+\\s+files?\\s+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Created\\s+.+\\(\\+\\d+\\s+-0\\)\\.?$/i.test(withoutBullet) ||\n /^Removed\\s+.+\\(\\+0\\s+-\\d+\\)\\.?$/i.test(withoutBullet)\n );\n}\n\nfunction reviewMarkdown(block: ContentBlock): string {\n const findings = Array.isArray(block.findings) ? block.findings : [];\n const lines: string[] = ['Code review', ''];\n if (findings.length === 0) {\n lines.push('No findings.');\n } else {\n lines.push('Findings:');\n for (const item of findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const rec = item as Record<string, unknown>;\n const title = typeof rec.title === 'string' ? rec.title : '';\n const body = typeof rec.body === 'string' ? rec.body : '';\n const priority = typeof rec.priority === 'number' ? rec.priority : 2;\n const filePath = typeof rec.filePath === 'string' ? rec.filePath : '';\n const lineStart = typeof rec.lineStart === 'number' ? rec.lineStart : undefined;\n const lineEnd = typeof rec.lineEnd === 'number' ? rec.lineEnd : undefined;\n const loc = filePath\n ? `${filePath}${lineStart ? `:${lineStart}${lineEnd && lineEnd !== lineStart ? `-${lineEnd}` : ''}` : ''}`\n : '';\n const suffix = loc ? ` - ${loc}` : '';\n lines.push(`- [P${priority}] ${title || body.slice(0, 80)}${suffix}`);\n if (body) lines.push(` ${body.replace(/\\n+/g, '\\n ')}`);\n }\n }\n const correctness = typeof block.overallCorrectness === 'string' ? block.overallCorrectness : 'unknown';\n const explanation = typeof block.overallExplanation === 'string' ? block.overallExplanation : '';\n lines.push('');\n lines.push(`Overall correctness: ${correctness}`);\n if (explanation) lines.push(explanation);\n return lines.join('\\n');\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') {\n return compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim().length > 0;\n }\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n if (block.type === 'review') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n } else if (block.type === 'review') {\n const text = reviewMarkdown(block).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":";;;AAKA,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAS1B,SAAS,cAAc,SAAmD;CACxE,MAAM,UAAW,SAA+C;AAChE,KAAI,OAAO,YAAY,SACrB,QAAO,QAAQ,MAAM,GAAG,CAAC;EAAE,MAAM;EAAQ,MAAM;EAAS,CAAC,GAAG,EAAE;AAEhE,QAAO,MAAM,QAAQ,QAAQ,GACzB,QAAQ,QAAQ,UAAiC,CAAC,CAAC,SAAS,OAAO,UAAU,SAAS,GACtF,EAAE;;AAGR,SAAS,UAAU,OAAqB,KAAkC;CACxE,MAAM,QAAQ,MAAM;AACpB,QAAO,OAAO,UAAU,WAAW,QAAQ;;AAG7C,SAAS,wBAAwB,MAAc,gBAAiC;AAC9E,KAAI,CAAC,eAAgB,QAAO;AAG5B,QAFc,KAAK,MAAM,KACP,CAAC,QAAQ,SAAS,CAAC,4BAA4B,KAAK,CAC3D,CAAC,KAAK,KAAK,CAAC,MAAM;;AAG/B,SAAS,4BAA4B,MAAuB;CAC1D,MAAM,aAAa,KAAK,MAAM;AAC9B,KAAI,CAAC,WAAY,QAAO;CACxB,MAAM,gBAAgB,WAAW,QAAQ,aAAa,GAAG;AACzD,QACE,qEAAqE,KAAK,cAAc,IACxF,iDAAiD,KAAK,cAAc,IACpE,mCAAmC,KAAK,cAAc,IACtD,mCAAmC,KAAK,cAAc;;AAI1D,SAAS,eAAe,OAA6B;CACnD,MAAM,WAAW,MAAM,QAAQ,MAAM,SAAS,GAAG,MAAM,WAAW,EAAE;CACpE,MAAM,QAAkB,CAAC,eAAe,GAAG;AAC3C,KAAI,SAAS,WAAW,EACtB,OAAM,KAAK,eAAe;MACrB;AACL,QAAM,KAAK,YAAY;AACvB,OAAK,MAAM,QAAQ,UAAU;AAC3B,OAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAAE;GAC9D,MAAM,MAAM;GACZ,MAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;GAC1D,MAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO;GACvD,MAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;GACnE,MAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;GACnE,MAAM,YAAY,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY,KAAA;GACtE,MAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,KAAA;GAChE,MAAM,MAAM,WACR,GAAG,WAAW,YAAY,IAAI,YAAY,WAAW,YAAY,YAAY,IAAI,YAAY,OAAO,OACpG;GACJ,MAAM,SAAS,MAAM,MAAM,QAAQ;AACnC,SAAM,KAAK,OAAO,SAAS,IAAI,SAAS,KAAK,MAAM,GAAG,GAAG,GAAG,SAAS;AACrE,OAAI,KAAM,OAAM,KAAK,KAAK,KAAK,QAAQ,QAAQ,OAAO,GAAG;;;CAG7D,MAAM,cAAc,OAAO,MAAM,uBAAuB,WAAW,MAAM,qBAAqB;CAC9F,MAAM,cAAc,OAAO,MAAM,uBAAuB,WAAW,MAAM,qBAAqB;AAC9F,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,wBAAwB,cAAc;AACjD,KAAI,YAAa,OAAM,KAAK,YAAY;AACxC,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,aAAa,SAA4C;AAChE,QAAO,cAAc,QAAQ,CAAC,MAAM,UAAU,MAAM,SAAS,cAAc,MAAM,SAAS,WAAW;;AAGvG,SAAS,WAAW,SAAuD;AACzE,QAAQ,SAAiD;;AAG3D,SAAS,aAAa,SAAuD;AAC3E,QAAQ,SAAmD;;AAG7D,SAAgB,+BAA+B,MAA4B;AACzE,QAAO;EACL,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAQ;GAAM,CAAC;EACjC,WAAW,KAAK,KAAK;EACtB;;AAGH,IAAa,4BAAb,cAA+C,UAAU;CACvD,mBAAoC,IAAI,WAAW;CACnD;CACA,iBAAyB;CACzB,oBAA4B;CAC5B,sBAA8B;CAE9B,YAAY,SAAwB,UAAmC,EAAE,EAAE;AACzE,SAAO;AACP,OAAK,oBAAoB,QAAQ,qBAAqB;AACtD,OAAK,sBAAsB,QAAQ,uBAAuB;AAC1D,OAAK,SAAS,KAAK,iBAAiB;AACpC,MAAI,QACF,MAAK,cAAc,QAAQ;;CAI/B,cAAc,SAA6B;AACzC,OAAK,UAAU;AACf,OAAK,SAAS;;CAGhB,gBAAgB,UAAyB;AACvC,OAAK,iBAAiB;AACtB,OAAK,SAAS;;CAGhB,qBAAqB,MAAqB;AACxC,MAAI,KAAK,sBAAsB,KAAM;AACrC,OAAK,oBAAoB;AACzB,OAAK,SAAS;;CAGhB,uBAAuB,OAAqB;AAC1C,MAAI,KAAK,wBAAwB,MAAO;AACxC,OAAK,sBAAsB;AAC3B,OAAK,SAAS;;CAGhB,aAA4B;AAC1B,QAAM,YAAY;AAClB,OAAK,SAAS;;CAGhB,OAAgB,OAAyB;EACvC,MAAM,QAAQ,MAAM,OAAO,MAAM;AACjC,MAAI,aAAa,KAAK,QAAQ,IAAI,KAAK,kBAAkB,MAAM,WAAW,EAAG,QAAO;AACpF,QAAM,KAAK,oBAAoB,MAAM;AACrC,QAAM,MAAM,SAAS,KAAK,kBAAkB,oBAAoB,MAAM,MAAM,SAAS;AACrF,SAAO;;CAGT,UAAwB;AACtB,OAAK,iBAAiB,OAAO;EAC7B,MAAM,SAAS,cAAc,KAAK,QAAQ;EAC1C,MAAM,gBAAgB,OAAO,QAAQ,UAAU;AAC7C,OAAI,MAAM,SAAS,OACjB,QAAO,wBAAwB,UAAU,OAAO,OAAO,EAAE,KAAK,eAAe,CAAC,MAAM,CAAC,SAAS;AAEhG,OAAI,MAAM,SAAS,WAAY,QAAO,UAAU,OAAO,WAAW,CAAC,MAAM,CAAC,SAAS;AACnF,OAAI,MAAM,SAAS,WAAW,MAAM,SAAS,YAAa,QAAO;AACjE,OAAI,MAAM,SAAS,SAAU,QAAO;AACpC,UAAO;IACP;EACF,MAAM,SAAS,WAAW,KAAK,QAAQ;EACvC,MAAM,gBACJ,CAAC,aAAa,KAAK,QAAQ,IAAI,CAAC,KAAK,mBAAmB,WAAW,aAAa,WAAW;AAC7F,MAAI,cAAc,WAAW,KAAK,CAAC,cAAe;AAElD,OAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;EAC7C,IAAI,kBAAkB;AACtB,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;GACtC,MAAM,QAAQ,OAAO;AACrB,OAAI,MAAM,SAAS,QAAQ;IACzB,MAAM,OAAO,wBAAwB,UAAU,OAAO,OAAO,EAAE,KAAK,eAAe,CAAC,MAAM;AAC1F,QAAI,CAAC,KAAM;AACX,QAAI,kBAAkB,EAAG,MAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;AACtE,SAAK,iBAAiB,SACpB,IAAI,SACF,MACA,GACA,GACA,eACA,EAAE,QAAQ,SAAS,MAAM,cAAc,KAAK,EAAE,EAC9C,EAAE,4BAA4B,MAAM,CACrC,CACF;AACD;cACS,MAAM,SAAS,YAAY;IACpC,MAAM,WAAW,UAAU,OAAO,WAAW,CAAC,MAAM;AACpD,QAAI,CAAC,SAAU;AACf,QAAI,kBAAkB,EAAG,MAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;IACtE,MAAM,OAAO,KAAK,oBAAoB,KAAK,sBAAsB;AACjE,SAAK,iBAAiB,SACpB,IAAI,SACF,MACA,GACA,GACA,eACA,EAAE,QAAQ,SAAS,MAAM,IAAI,MAAM,OAAO,KAAK,CAAC,EAAE,EAClD,EAAE,4BAA4B,MAAM,CACrC,CACF;AACD;cACS,MAAM,SAAS,WAAW,MAAM,SAAS,aAAa;AAC/D,QAAI,kBAAkB,EAAG,MAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;AACtE,SAAK,iBAAiB,SAAS,IAAI,KAAK,MAAM,IAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACpE;cACS,MAAM,SAAS,UAAU;IAClC,MAAM,OAAO,eAAe,MAAM,CAAC,MAAM;AACzC,QAAI,CAAC,KAAM;AACX,QAAI,kBAAkB,EAAG,MAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;AACtE,SAAK,iBAAiB,SACpB,IAAI,SACF,MACA,GACA,GACA,eACA,EAAE,QAAQ,SAAS,MAAM,cAAc,KAAK,EAAE,EAC9C,EAAE,4BAA4B,MAAM,CACrC,CACF;AACD;;;AAIJ,MAAI,eAAe;AACjB,OAAI,kBAAkB,EAAG,MAAK,iBAAiB,SAAS,IAAI,OAAO,EAAE,CAAC;GACtE,MAAM,OACJ,WAAW,YACP,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,QAAQ,KAAK,wBAC3D,aAAa,KAAK,QAAQ,GAC1B,sBACF,UAAU,aAAa,KAAK,QAAQ,IAAI;AAC9C,QAAK,iBAAiB,SAAS,IAAI,KAAK,MAAM,MAAM,KAAK,EAAE,GAAG,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction compactToolAdjacentText(text: string, linkedToolCall: boolean): string {\n if (!linkedToolCall) return text;\n const lines = text.split('\\n');\n const kept = lines.filter((line) => !isMechanicalToolSummaryLine(line));\n return kept.join('\\n').trim();\n}\n\nfunction isMechanicalToolSummaryLine(line: string): boolean {\n const normalized = line.trim();\n if (!normalized) return false;\n const withoutBullet = normalized.replace(/^[-*•]\\s+/, '');\n return (\n /^(Added|Deleted|Edited|Modified|Updated)\\s+.+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Edited\\s+\\d+\\s+files?\\s+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Created\\s+.+\\(\\+\\d+\\s+-0\\)\\.?$/i.test(withoutBullet) ||\n /^Removed\\s+.+\\(\\+0\\s+-\\d+\\)\\.?$/i.test(withoutBullet)\n );\n}\n\nfunction reviewMarkdown(block: ContentBlock): string {\n const findings = Array.isArray(block.findings) ? block.findings : [];\n const lines: string[] = ['<< Code review finished >>', '', 'Code review', ''];\n const source = typeof block.source === 'string' ? block.source : '';\n const correctness = typeof block.overallCorrectness === 'string' ? block.overallCorrectness : 'unknown';\n const modelReviewIncomplete = source === 'local' && correctness === 'unknown';\n if (findings.length === 0) {\n lines.push(modelReviewIncomplete ? 'No model findings were produced.' : 'No findings.');\n } else {\n lines.push('Findings:');\n for (const item of findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const rec = item as Record<string, unknown>;\n const title = typeof rec.title === 'string' ? rec.title : '';\n const body = typeof rec.body === 'string' ? rec.body : '';\n const priority = typeof rec.priority === 'number' ? rec.priority : 2;\n const filePath = typeof rec.filePath === 'string' ? rec.filePath : '';\n const lineStart = typeof rec.lineStart === 'number' ? rec.lineStart : undefined;\n const lineEnd = typeof rec.lineEnd === 'number' ? rec.lineEnd : undefined;\n const loc = filePath\n ? `${filePath}${lineStart ? `:${lineStart}${lineEnd && lineEnd !== lineStart ? `-${lineEnd}` : ''}` : ''}`\n : '';\n const suffix = loc ? ` - ${loc}` : '';\n lines.push(`- [P${priority}] ${title || body.slice(0, 80)}${suffix}`);\n if (body) lines.push(` ${body.replace(/\\n+/g, '\\n ')}`);\n }\n }\n const explanation = typeof block.overallExplanation === 'string' ? block.overallExplanation : '';\n lines.push('');\n lines.push(`Overall correctness: ${correctness}`);\n if (explanation) lines.push(explanation);\n return lines.join('\\n');\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') {\n return compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim().length > 0;\n }\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n if (block.type === 'review') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n } else if (block.type === 'review') {\n const text = reviewMarkdown(block).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { Container, type KeybindingsManager, type TUI } from '@earendil-works/pi-tui';
|
|
2
2
|
/** Local `!` / `!!` shell output block (pi coding-agent–aligned). */
|
|
3
3
|
export declare class BashExecutionComponent extends Container {
|
|
4
|
+
private readonly command;
|
|
4
5
|
private readonly excludeFromContext;
|
|
5
6
|
private readonly keybindings?;
|
|
6
7
|
private readonly contentContainer;
|
|
8
|
+
private readonly header;
|
|
7
9
|
private readonly loader;
|
|
8
10
|
private outputLines;
|
|
9
11
|
private status;
|
|
10
12
|
private exitCode;
|
|
11
13
|
private expanded;
|
|
14
|
+
private readonly colorKey;
|
|
12
15
|
constructor(command: string, ui: TUI, excludeFromContext: boolean, keybindings?: KeybindingsManager);
|
|
13
16
|
setExpanded(expanded: boolean): void;
|
|
14
17
|
appendOutput(chunk: string): void;
|
|
15
18
|
setComplete(exitCode: number | null | undefined, signal: NodeJS.Signals | null): void;
|
|
16
19
|
setError(message: string): void;
|
|
17
20
|
private refreshOutput;
|
|
21
|
+
private formatHeader;
|
|
18
22
|
}
|
|
@@ -12,23 +12,26 @@ function stripAnsi(text) {
|
|
|
12
12
|
/** Local `!` / `!!` shell output block (pi coding-agent–aligned). */
|
|
13
13
|
var BashExecutionComponent = class extends Container {
|
|
14
14
|
contentContainer = new Container();
|
|
15
|
+
header;
|
|
15
16
|
loader;
|
|
16
17
|
outputLines = [];
|
|
17
18
|
status = "running";
|
|
18
19
|
exitCode;
|
|
19
20
|
expanded = false;
|
|
21
|
+
colorKey;
|
|
20
22
|
constructor(command, ui, excludeFromContext, keybindings) {
|
|
21
23
|
super();
|
|
24
|
+
this.command = command;
|
|
22
25
|
this.excludeFromContext = excludeFromContext;
|
|
23
26
|
this.keybindings = keybindings;
|
|
24
|
-
|
|
25
|
-
const borderColor = (str) => theme.fg(colorKey, str);
|
|
27
|
+
this.colorKey = excludeFromContext ? "bashExclude" : "bashMode";
|
|
28
|
+
const borderColor = (str) => theme.fg(this.colorKey, str);
|
|
26
29
|
this.addChild(new Spacer(1));
|
|
27
30
|
this.addChild(new DynamicBorder(borderColor));
|
|
28
31
|
this.addChild(this.contentContainer);
|
|
29
|
-
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
+
this.header = new Text(this.formatHeader(), 1, 0);
|
|
33
|
+
this.loader = new Loader(ui, (spinner) => theme.fg(this.colorKey, spinner), (text) => theme.dim(text), "Running…");
|
|
34
|
+
this.contentContainer.addChild(this.header);
|
|
32
35
|
this.contentContainer.addChild(this.loader);
|
|
33
36
|
this.addChild(new DynamicBorder(borderColor));
|
|
34
37
|
}
|
|
@@ -62,6 +65,7 @@ var BashExecutionComponent = class extends Container {
|
|
|
62
65
|
}
|
|
63
66
|
refreshOutput() {
|
|
64
67
|
while (this.contentContainer.children.length > 2) this.contentContainer.removeChild(this.contentContainer.children[2]);
|
|
68
|
+
this.header.setText(this.formatHeader());
|
|
65
69
|
const lines = this.outputLines.filter((l) => l.length > 0);
|
|
66
70
|
const visible = this.expanded ? lines : lines.slice(-PREVIEW_LINES);
|
|
67
71
|
const hidden = lines.length - visible.length;
|
|
@@ -70,15 +74,19 @@ var BashExecutionComponent = class extends Container {
|
|
|
70
74
|
this.contentContainer.addChild(new Text(theme.dim(`… ${hidden} more line${hidden > 1 ? "s" : ""} (${expandKey} to expand tools/output)`), 1, 0));
|
|
71
75
|
}
|
|
72
76
|
if (visible.length > 0) {
|
|
73
|
-
const outputText = visible.map((line) => theme.toolOutput(line)).join("\n");
|
|
77
|
+
const outputText = visible.map((line, index) => theme.toolOutput(`${index === 0 ? " └ " : " "}${line}`)).join("\n");
|
|
74
78
|
if (this.expanded) this.contentContainer.addChild(new Text(outputText, 1, 0));
|
|
75
79
|
else this.contentContainer.addChild(createVisualTailComponent(outputText, PREVIEW_LINES, 1));
|
|
76
|
-
}
|
|
80
|
+
} else if (this.status !== "running") this.contentContainer.addChild(new Text(theme.dim(" └ (no output)"), 1, 0));
|
|
77
81
|
if (this.status !== "running") {
|
|
78
82
|
const suffix = this.status === "error" ? `exit ${this.exitCode ?? "?"}${this.excludeFromContext ? " · excluded from agent context" : ""}` : `exit ${this.exitCode ?? 0}${this.excludeFromContext ? " · excluded from agent context" : ""}`;
|
|
79
83
|
this.contentContainer.addChild(new Text(theme.dim(suffix), 1, 0));
|
|
80
84
|
}
|
|
81
85
|
}
|
|
86
|
+
formatHeader() {
|
|
87
|
+
const verb = this.status === "running" ? "Running" : "You ran";
|
|
88
|
+
return theme.fg(this.colorKey, theme.bold(`• ${verb} ${this.command}`));
|
|
89
|
+
}
|
|
82
90
|
};
|
|
83
91
|
function createVisualTailComponent(text, maxVisualLines, paddingX) {
|
|
84
92
|
let cachedWidth;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-execution.js","names":[],"sources":["../../../../src/tui/components/bash-execution.ts"],"sourcesContent":["import {\n Container,\n type KeybindingsManager,\n Loader,\n Spacer,\n Text,\n type TUI,\n} from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport { DynamicBorder } from './dynamic-border.js';\nimport { truncateToVisualLines } from './visual-truncate.js';\n\nconst PREVIEW_LINES = 20;\nconst MAX_OUTPUT_CHARS = 40_000;\n\nfunction stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\n/** Local `!` / `!!` shell output block (pi coding-agent–aligned). */\nexport class BashExecutionComponent extends Container {\n private readonly contentContainer = new Container();\n private readonly loader: Loader;\n private outputLines: string[] = [];\n private status: 'running' | 'complete' | 'error' = 'running';\n private exitCode: number | undefined;\n private expanded = false;\n\n constructor(\n command: string,\n ui: TUI,\n private readonly excludeFromContext: boolean,\n private readonly keybindings?: KeybindingsManager,\n ) {\n super();\n
|
|
1
|
+
{"version":3,"file":"bash-execution.js","names":[],"sources":["../../../../src/tui/components/bash-execution.ts"],"sourcesContent":["import {\n Container,\n type KeybindingsManager,\n Loader,\n Spacer,\n Text,\n type TUI,\n} from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport { DynamicBorder } from './dynamic-border.js';\nimport { truncateToVisualLines } from './visual-truncate.js';\n\nconst PREVIEW_LINES = 20;\nconst MAX_OUTPUT_CHARS = 40_000;\n\nfunction stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\n/** Local `!` / `!!` shell output block (pi coding-agent–aligned). */\nexport class BashExecutionComponent extends Container {\n private readonly contentContainer = new Container();\n private readonly header: Text;\n private readonly loader: Loader;\n private outputLines: string[] = [];\n private status: 'running' | 'complete' | 'error' = 'running';\n private exitCode: number | undefined;\n private expanded = false;\n private readonly colorKey: 'bashExclude' | 'bashMode';\n\n constructor(\n private readonly command: string,\n ui: TUI,\n private readonly excludeFromContext: boolean,\n private readonly keybindings?: KeybindingsManager,\n ) {\n super();\n this.colorKey = excludeFromContext ? 'bashExclude' : 'bashMode';\n const borderColor = (str: string) => theme.fg(this.colorKey, str);\n\n this.addChild(new Spacer(1));\n this.addChild(new DynamicBorder(borderColor));\n this.addChild(this.contentContainer);\n\n this.header = new Text(this.formatHeader(), 1, 0);\n this.loader = new Loader(\n ui,\n (spinner) => theme.fg(this.colorKey, spinner),\n (text) => theme.dim(text),\n 'Running…',\n );\n this.contentContainer.addChild(this.header);\n this.contentContainer.addChild(this.loader);\n\n this.addChild(new DynamicBorder(borderColor));\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refreshOutput();\n }\n\n appendOutput(chunk: string): void {\n const clean = stripAnsi(chunk).replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n const newLines = clean.split('\\n');\n if (this.outputLines.length > 0 && newLines.length > 0) {\n this.outputLines[this.outputLines.length - 1] += newLines[0]!;\n this.outputLines.push(...newLines.slice(1));\n } else {\n this.outputLines.push(...newLines);\n }\n const joined = this.outputLines.join('\\n');\n if (joined.length > MAX_OUTPUT_CHARS) {\n this.outputLines = joined.slice(-MAX_OUTPUT_CHARS).split('\\n');\n }\n this.refreshOutput();\n }\n\n setComplete(exitCode: number | null | undefined, signal: NodeJS.Signals | null): void {\n this.loader.stop();\n if (signal) {\n this.status = 'error';\n } else if (exitCode != null && exitCode !== 0) {\n this.status = 'error';\n } else {\n this.status = 'complete';\n }\n this.exitCode = exitCode ?? undefined;\n this.refreshOutput();\n }\n\n setError(message: string): void {\n this.loader.stop();\n this.status = 'error';\n this.outputLines = [message];\n this.refreshOutput();\n }\n\n private refreshOutput(): void {\n while (this.contentContainer.children.length > 2) {\n this.contentContainer.removeChild(this.contentContainer.children[2]!);\n }\n\n this.header.setText(this.formatHeader());\n\n const lines = this.outputLines.filter((l) => l.length > 0);\n const visible = this.expanded ? lines : lines.slice(-PREVIEW_LINES);\n const hidden = lines.length - visible.length;\n\n if (hidden > 0 && !this.expanded) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n this.contentContainer.addChild(\n new Text(\n theme.dim(`… ${hidden} more line${hidden > 1 ? 's' : ''} (${expandKey} to expand tools/output)`),\n 1,\n 0,\n ),\n );\n }\n\n if (visible.length > 0) {\n const outputText = visible\n .map((line, index) => theme.toolOutput(`${index === 0 ? ' └ ' : ' '}${line}`))\n .join('\\n');\n if (this.expanded) {\n this.contentContainer.addChild(new Text(outputText, 1, 0));\n } else {\n this.contentContainer.addChild(createVisualTailComponent(outputText, PREVIEW_LINES, 1));\n }\n } else if (this.status !== 'running') {\n this.contentContainer.addChild(new Text(theme.dim(' └ (no output)'), 1, 0));\n }\n\n if (this.status !== 'running') {\n const suffix =\n this.status === 'error'\n ? `exit ${this.exitCode ?? '?'}${this.excludeFromContext ? ' · excluded from agent context' : ''}`\n : `exit ${this.exitCode ?? 0}${this.excludeFromContext ? ' · excluded from agent context' : ''}`;\n this.contentContainer.addChild(new Text(theme.dim(suffix), 1, 0));\n }\n }\n\n private formatHeader(): string {\n const verb = this.status === 'running' ? 'Running' : 'You ran';\n return theme.fg(this.colorKey, theme.bold(`• ${verb} ${this.command}`));\n }\n}\n\nfunction createVisualTailComponent(text: string, maxVisualLines: number, paddingX: number) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLines(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines = result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -28,7 +28,9 @@ function isReadStyleTool(toolName) {
|
|
|
28
28
|
return [
|
|
29
29
|
"read",
|
|
30
30
|
"read_file",
|
|
31
|
-
"memory_get"
|
|
31
|
+
"memory_get",
|
|
32
|
+
"get_code_snippet",
|
|
33
|
+
"prepare_diff"
|
|
32
34
|
].includes(base);
|
|
33
35
|
}
|
|
34
36
|
function isSearchStyleTool(toolName) {
|
|
@@ -40,7 +42,11 @@ function isSearchStyleTool(toolName) {
|
|
|
40
42
|
"ripgrep",
|
|
41
43
|
"search_code",
|
|
42
44
|
"file_search",
|
|
43
|
-
"list_files"
|
|
45
|
+
"list_files",
|
|
46
|
+
"search_graph",
|
|
47
|
+
"query_graph",
|
|
48
|
+
"trace_path",
|
|
49
|
+
"get_architecture"
|
|
44
50
|
].includes(base);
|
|
45
51
|
}
|
|
46
52
|
function isExecStyleTool(toolName) {
|
|
@@ -126,7 +132,7 @@ function commandFromArgs(args) {
|
|
|
126
132
|
return null;
|
|
127
133
|
}
|
|
128
134
|
function baseToolName(toolName) {
|
|
129
|
-
return toolName.split(
|
|
135
|
+
return toolName.split(/__|\./).pop()?.toLowerCase() ?? toolName.toLowerCase();
|
|
130
136
|
}
|
|
131
137
|
function firstFiniteNumber(...values) {
|
|
132
138
|
for (const value of values) {
|