pybao-cli 1.5.22 → 1.5.24
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/REPL-K6NYKODR.js +51 -0
- package/dist/{acp-6UNV3LLZ.js → acp-5H7EXQK2.js} +33 -32
- package/dist/{acp-6UNV3LLZ.js.map → acp-5H7EXQK2.js.map} +1 -1
- package/dist/{agentsValidate-Q6TKU7TM.js → agentsValidate-QQUWQEIR.js} +7 -7
- package/dist/{ask-VKXARFSE.js → ask-2NXAGZUU.js} +32 -31
- package/dist/{ask-VKXARFSE.js.map → ask-2NXAGZUU.js.map} +1 -1
- package/dist/{autoUpdater-7EWH6KLS.js → autoUpdater-UZGQSBVX.js} +3 -3
- package/dist/{chunk-5SXLQSDA.js → chunk-2LDISGV5.js} +4 -1
- package/dist/{chunk-NHGHYVP4.js → chunk-4RFXQVAB.js} +2 -2
- package/dist/{chunk-NNLRGQH7.js → chunk-5LOOKSJJ.js} +2 -2
- package/dist/{chunk-K75Q3DNN.js → chunk-6FXN7WXV.js} +3 -3
- package/dist/{chunk-YTMIS255.js → chunk-7G3CESAX.js} +2 -2
- package/dist/{chunk-A7DBXB2F.js → chunk-7PKIDZYX.js} +3 -1
- package/dist/chunk-7PKIDZYX.js.map +7 -0
- package/dist/{chunk-3OHETUTC.js → chunk-7XKF4NS5.js} +1 -1
- package/dist/{chunk-BHQOSSZK.js → chunk-AIYDVZNU.js} +3 -3
- package/dist/{chunk-DUQMZDAG.js → chunk-AXW3EAEG.js} +3 -3
- package/dist/{chunk-P3H2FCWA.js → chunk-C5W7DK4B.js} +3 -3
- package/dist/chunk-DGOZRLG4.js +574 -0
- package/dist/chunk-DGOZRLG4.js.map +7 -0
- package/dist/{chunk-WPTE44L5.js → chunk-DQPL53A3.js} +4 -4
- package/dist/chunk-DSMH3DDQ.js +96 -0
- package/dist/chunk-DSMH3DDQ.js.map +7 -0
- package/dist/{chunk-C3FMLNZD.js → chunk-FBTRKZNM.js} +35 -167
- package/dist/chunk-FBTRKZNM.js.map +7 -0
- package/dist/{chunk-YGVF37PC.js → chunk-GTBOGB65.js} +3 -3
- package/dist/{chunk-AJ3UX6R7.js → chunk-H25IY2QB.js} +1 -1
- package/dist/{chunk-O7R3XZGO.js → chunk-H7HRAFNH.js} +15 -15
- package/dist/chunk-HHXEDAUY.js +681 -0
- package/dist/chunk-HHXEDAUY.js.map +7 -0
- package/dist/{chunk-EC3PLGG3.js → chunk-JU3X54OB.js} +2 -2
- package/dist/chunk-KFEHHKZ2.js +145 -0
- package/dist/chunk-KFEHHKZ2.js.map +7 -0
- package/dist/{chunk-JZJUCJTK.js → chunk-L6HMG5TD.js} +1 -1
- package/dist/{chunk-VXBBKE3Z.js → chunk-MVWCFCWA.js} +1 -1
- package/dist/{chunk-IZQYUXSZ.js → chunk-NNGD2UJL.js} +2 -2
- package/dist/{chunk-JUMRO5I7.js → chunk-PFHTQ2ON.js} +4 -4
- package/dist/{chunk-FCSVC7CP.js → chunk-QPX3VRTH.js} +4 -4
- package/dist/{chunk-OPAEJ3Y5.js → chunk-S7HIIXVN.js} +1 -1
- package/dist/{chunk-GSFBS4B4.js → chunk-T4BBPE5F.js} +3 -3
- package/dist/{chunk-5S2CPB42.js → chunk-T5ZQLE6E.js} +3 -3
- package/dist/{chunk-GDDO2XA3.js → chunk-UJ2SNURP.js} +1 -1
- package/dist/{chunk-7HPHH3FB.js → chunk-UOVFEY6P.js} +69 -48
- package/dist/{chunk-7HPHH3FB.js.map → chunk-UOVFEY6P.js.map} +3 -3
- package/dist/{chunk-LRKZ3RPS.js → chunk-UUM4Q5S6.js} +1 -1
- package/dist/{chunk-XSUCLDWY.js → chunk-W2DOITEM.js} +2 -2
- package/dist/{chunk-E4JH2XFM.js → chunk-XVF7DL3L.js} +1 -1
- package/dist/{cli-DFM7Z6AH.js → cli-5CKXURNM.js} +130 -102
- package/dist/cli-5CKXURNM.js.map +7 -0
- package/dist/commands-FVAUVYN5.js +55 -0
- package/dist/{config-XUPBT2EE.js → config-P6NPLNYJ.js} +4 -4
- package/dist/{context-TE7OR7RQ.js → context-KGCNIOLW.js} +7 -6
- package/dist/{conversationPersistence-24HWWB75.js → conversationPersistence-ZR5BNQEH.js} +3 -3
- package/dist/{conversationTracker-4JE7TNPU.js → conversationTracker-CWBOYHS6.js} +4 -4
- package/dist/{customCommands-OGYMS6BW.js → customCommands-FI35GWO7.js} +4 -4
- package/dist/{env-OFPQLCBS.js → env-XIHEMHIE.js} +2 -2
- package/dist/{file-X2XAPBRZ.js → file-WT4CNRBH.js} +4 -4
- package/dist/index.js +3 -3
- package/dist/{llm-6XIL53O7.js → llm-HPPHTPDB.js} +33 -32
- package/dist/{llm-6XIL53O7.js.map → llm-HPPHTPDB.js.map} +1 -1
- package/dist/{llmLazy-U2GIPU5C.js → llmLazy-76OBERV2.js} +1 -1
- package/dist/{loader-EGMA6CWF.js → loader-TS2HH5EN.js} +4 -4
- package/dist/{lsp-JMPOPT6A.js → lsp-KV7OBBMM.js} +6 -6
- package/dist/{lspAnchor-5PMHI5BV.js → lspAnchor-ZCANLR6C.js} +6 -6
- package/dist/{mcp-XSVQR6C6.js → mcp-MFOXCURO.js} +7 -7
- package/dist/{mentionProcessor-4MOOQMS7.js → mentionProcessor-4OQOE7GY.js} +5 -5
- package/dist/{messages-ZBGD2RVK.js → messages-NCRJ6QRS.js} +1 -1
- package/dist/{model-ECTUAZ5Q.js → model-QGIJDQKV.js} +5 -5
- package/dist/{openai-CRNKDQJ3.js → openai-PIMPLRHA.js} +5 -5
- package/dist/{outputStyles-Z4PB6UX5.js → outputStyles-VIR2WGDW.js} +4 -4
- package/dist/{pluginRuntime-DRDVDAUU.js → pluginRuntime-HM55RXJW.js} +6 -6
- package/dist/{pluginValidation-RHPC5SAR.js → pluginValidation-7TELFKDN.js} +6 -6
- package/dist/prompts-JUMG5DV4.js +57 -0
- package/dist/{pybAgentSessionLoad-YAEB2WL4.js → pybAgentSessionLoad-G6BSOKJV.js} +5 -6
- package/dist/{pybAgentSessionResume-C7MUM2PL.js → pybAgentSessionResume-GFO2HI4V.js} +5 -4
- package/dist/{pybAgentStreamJsonSession-3X3S5CI2.js → pybAgentStreamJsonSession-XJWWG4KQ.js} +1 -1
- package/dist/{pybHooks-DWLOM55R.js → pybHooks-MRBA3GKS.js} +4 -4
- package/dist/query-O5YZELUK.js +55 -0
- package/dist/{registry-MFGZRI5N.js → registry-VLNMWI4D.js} +5 -5
- package/dist/{ripgrep-P7LJLNZR.js → ripgrep-I4QCQBMN.js} +3 -3
- package/dist/{skillMarketplace-R5ZEB7NX.js → skillMarketplace-F3LNNAWT.js} +3 -3
- package/dist/{state-W25DUPH2.js → state-66VUERW2.js} +2 -2
- package/dist/{theme-YNA47SVG.js → theme-QGI5L27W.js} +5 -5
- package/dist/{toolPermissionSettings-IJR677NS.js → toolPermissionSettings-E4T44WBW.js} +6 -6
- package/dist/tools-4WOQWDGA.js +56 -0
- package/dist/{userInput-I2PLDULC.js → userInput-KKWPB5G6.js} +34 -33
- package/dist/{userInput-I2PLDULC.js.map → userInput-KKWPB5G6.js.map} +1 -1
- package/package.json +3 -1
- package/scripts/session-project-gate.mjs +95 -0
- package/dist/REPL-KRZBKRH2.js +0 -50
- package/dist/chunk-A7DBXB2F.js.map +0 -7
- package/dist/chunk-C3FMLNZD.js.map +0 -7
- package/dist/chunk-CDK4YHKS.js +0 -196
- package/dist/chunk-CDK4YHKS.js.map +0 -7
- package/dist/chunk-EJJSN2TT.js +0 -81
- package/dist/chunk-EJJSN2TT.js.map +0 -7
- package/dist/chunk-WHAWWM3Y.js +0 -138
- package/dist/chunk-WHAWWM3Y.js.map +0 -7
- package/dist/cli-DFM7Z6AH.js.map +0 -7
- package/dist/commands-E6P6G6RL.js +0 -54
- package/dist/prompts-XBRLSIXQ.js +0 -56
- package/dist/query-7M3GL2CM.js +0 -54
- package/dist/tools-XDOXLNVD.js +0 -55
- /package/dist/{REPL-KRZBKRH2.js.map → REPL-K6NYKODR.js.map} +0 -0
- /package/dist/{agentsValidate-Q6TKU7TM.js.map → agentsValidate-QQUWQEIR.js.map} +0 -0
- /package/dist/{autoUpdater-7EWH6KLS.js.map → autoUpdater-UZGQSBVX.js.map} +0 -0
- /package/dist/{chunk-5SXLQSDA.js.map → chunk-2LDISGV5.js.map} +0 -0
- /package/dist/{chunk-NHGHYVP4.js.map → chunk-4RFXQVAB.js.map} +0 -0
- /package/dist/{chunk-NNLRGQH7.js.map → chunk-5LOOKSJJ.js.map} +0 -0
- /package/dist/{chunk-K75Q3DNN.js.map → chunk-6FXN7WXV.js.map} +0 -0
- /package/dist/{chunk-YTMIS255.js.map → chunk-7G3CESAX.js.map} +0 -0
- /package/dist/{chunk-3OHETUTC.js.map → chunk-7XKF4NS5.js.map} +0 -0
- /package/dist/{chunk-BHQOSSZK.js.map → chunk-AIYDVZNU.js.map} +0 -0
- /package/dist/{chunk-DUQMZDAG.js.map → chunk-AXW3EAEG.js.map} +0 -0
- /package/dist/{chunk-P3H2FCWA.js.map → chunk-C5W7DK4B.js.map} +0 -0
- /package/dist/{chunk-WPTE44L5.js.map → chunk-DQPL53A3.js.map} +0 -0
- /package/dist/{chunk-YGVF37PC.js.map → chunk-GTBOGB65.js.map} +0 -0
- /package/dist/{chunk-AJ3UX6R7.js.map → chunk-H25IY2QB.js.map} +0 -0
- /package/dist/{chunk-O7R3XZGO.js.map → chunk-H7HRAFNH.js.map} +0 -0
- /package/dist/{chunk-EC3PLGG3.js.map → chunk-JU3X54OB.js.map} +0 -0
- /package/dist/{chunk-JZJUCJTK.js.map → chunk-L6HMG5TD.js.map} +0 -0
- /package/dist/{chunk-VXBBKE3Z.js.map → chunk-MVWCFCWA.js.map} +0 -0
- /package/dist/{chunk-IZQYUXSZ.js.map → chunk-NNGD2UJL.js.map} +0 -0
- /package/dist/{chunk-JUMRO5I7.js.map → chunk-PFHTQ2ON.js.map} +0 -0
- /package/dist/{chunk-FCSVC7CP.js.map → chunk-QPX3VRTH.js.map} +0 -0
- /package/dist/{chunk-OPAEJ3Y5.js.map → chunk-S7HIIXVN.js.map} +0 -0
- /package/dist/{chunk-GSFBS4B4.js.map → chunk-T4BBPE5F.js.map} +0 -0
- /package/dist/{chunk-5S2CPB42.js.map → chunk-T5ZQLE6E.js.map} +0 -0
- /package/dist/{chunk-GDDO2XA3.js.map → chunk-UJ2SNURP.js.map} +0 -0
- /package/dist/{chunk-LRKZ3RPS.js.map → chunk-UUM4Q5S6.js.map} +0 -0
- /package/dist/{chunk-XSUCLDWY.js.map → chunk-W2DOITEM.js.map} +0 -0
- /package/dist/{chunk-E4JH2XFM.js.map → chunk-XVF7DL3L.js.map} +0 -0
- /package/dist/{commands-E6P6G6RL.js.map → commands-FVAUVYN5.js.map} +0 -0
- /package/dist/{config-XUPBT2EE.js.map → config-P6NPLNYJ.js.map} +0 -0
- /package/dist/{context-TE7OR7RQ.js.map → context-KGCNIOLW.js.map} +0 -0
- /package/dist/{conversationPersistence-24HWWB75.js.map → conversationPersistence-ZR5BNQEH.js.map} +0 -0
- /package/dist/{conversationTracker-4JE7TNPU.js.map → conversationTracker-CWBOYHS6.js.map} +0 -0
- /package/dist/{customCommands-OGYMS6BW.js.map → customCommands-FI35GWO7.js.map} +0 -0
- /package/dist/{env-OFPQLCBS.js.map → env-XIHEMHIE.js.map} +0 -0
- /package/dist/{file-X2XAPBRZ.js.map → file-WT4CNRBH.js.map} +0 -0
- /package/dist/{llmLazy-U2GIPU5C.js.map → llmLazy-76OBERV2.js.map} +0 -0
- /package/dist/{loader-EGMA6CWF.js.map → loader-TS2HH5EN.js.map} +0 -0
- /package/dist/{lsp-JMPOPT6A.js.map → lsp-KV7OBBMM.js.map} +0 -0
- /package/dist/{lspAnchor-5PMHI5BV.js.map → lspAnchor-ZCANLR6C.js.map} +0 -0
- /package/dist/{mcp-XSVQR6C6.js.map → mcp-MFOXCURO.js.map} +0 -0
- /package/dist/{mentionProcessor-4MOOQMS7.js.map → mentionProcessor-4OQOE7GY.js.map} +0 -0
- /package/dist/{messages-ZBGD2RVK.js.map → messages-NCRJ6QRS.js.map} +0 -0
- /package/dist/{model-ECTUAZ5Q.js.map → model-QGIJDQKV.js.map} +0 -0
- /package/dist/{openai-CRNKDQJ3.js.map → openai-PIMPLRHA.js.map} +0 -0
- /package/dist/{outputStyles-Z4PB6UX5.js.map → outputStyles-VIR2WGDW.js.map} +0 -0
- /package/dist/{pluginRuntime-DRDVDAUU.js.map → pluginRuntime-HM55RXJW.js.map} +0 -0
- /package/dist/{pluginValidation-RHPC5SAR.js.map → pluginValidation-7TELFKDN.js.map} +0 -0
- /package/dist/{prompts-XBRLSIXQ.js.map → prompts-JUMG5DV4.js.map} +0 -0
- /package/dist/{pybAgentSessionLoad-YAEB2WL4.js.map → pybAgentSessionLoad-G6BSOKJV.js.map} +0 -0
- /package/dist/{pybAgentSessionResume-C7MUM2PL.js.map → pybAgentSessionResume-GFO2HI4V.js.map} +0 -0
- /package/dist/{pybAgentStreamJsonSession-3X3S5CI2.js.map → pybAgentStreamJsonSession-XJWWG4KQ.js.map} +0 -0
- /package/dist/{pybHooks-DWLOM55R.js.map → pybHooks-MRBA3GKS.js.map} +0 -0
- /package/dist/{query-7M3GL2CM.js.map → query-O5YZELUK.js.map} +0 -0
- /package/dist/{registry-MFGZRI5N.js.map → registry-VLNMWI4D.js.map} +0 -0
- /package/dist/{ripgrep-P7LJLNZR.js.map → ripgrep-I4QCQBMN.js.map} +0 -0
- /package/dist/{skillMarketplace-R5ZEB7NX.js.map → skillMarketplace-F3LNNAWT.js.map} +0 -0
- /package/dist/{state-W25DUPH2.js.map → state-66VUERW2.js.map} +0 -0
- /package/dist/{theme-YNA47SVG.js.map → theme-QGI5L27W.js.map} +0 -0
- /package/dist/{toolPermissionSettings-IJR677NS.js.map → toolPermissionSettings-E4T44WBW.js.map} +0 -0
- /package/dist/{tools-XDOXLNVD.js.map → tools-4WOQWDGA.js.map} +0 -0
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
import { createRequire as __pybCreateRequire } from "node:module";
|
|
2
|
+
const require = __pybCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
findGitRoot
|
|
5
|
+
} from "./chunk-KFEHHKZ2.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveXdgDataPath
|
|
8
|
+
} from "./chunk-2LDISGV5.js";
|
|
9
|
+
|
|
10
|
+
// src/utils/session/sessionSqlStore.ts
|
|
11
|
+
import { createRequire } from "node:module";
|
|
12
|
+
import { existsSync, mkdirSync } from "fs";
|
|
13
|
+
import { dirname } from "path";
|
|
14
|
+
|
|
15
|
+
// src/utils/session/sessionStoreConfig.ts
|
|
16
|
+
var cachedFlags = null;
|
|
17
|
+
function parseBooleanFlag(rawValue, defaultValue) {
|
|
18
|
+
const normalized = String(rawValue ?? "").trim().toLowerCase();
|
|
19
|
+
if (!normalized) return defaultValue;
|
|
20
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
21
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
22
|
+
return defaultValue;
|
|
23
|
+
}
|
|
24
|
+
function getSessionStoreFlags() {
|
|
25
|
+
if (cachedFlags) return cachedFlags;
|
|
26
|
+
cachedFlags = {
|
|
27
|
+
sqlWriteEnabled: parseBooleanFlag(
|
|
28
|
+
process.env.PYB_SESSION_STORE_SQL_WRITE,
|
|
29
|
+
true
|
|
30
|
+
),
|
|
31
|
+
sqlReadEnabled: parseBooleanFlag(process.env.PYB_SESSION_STORE_SQL_READ, true)
|
|
32
|
+
};
|
|
33
|
+
return cachedFlags;
|
|
34
|
+
}
|
|
35
|
+
function getSessionStoreDbPath() {
|
|
36
|
+
const override = String(process.env.PYB_SESSION_STORE_DB_PATH ?? "").trim();
|
|
37
|
+
if (override) return override;
|
|
38
|
+
return resolveXdgDataPath("sessions/session-store.db");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/utils/session/sessionStoreSchema.ts
|
|
42
|
+
var SESSION_STORE_SCHEMA_VERSION = 2;
|
|
43
|
+
function applyRuntimePragmas(db) {
|
|
44
|
+
db.exec(`PRAGMA journal_mode=WAL;`);
|
|
45
|
+
db.exec(`PRAGMA synchronous=NORMAL;`);
|
|
46
|
+
db.exec(`PRAGMA busy_timeout=5000;`);
|
|
47
|
+
db.exec(`PRAGMA foreign_keys=ON;`);
|
|
48
|
+
}
|
|
49
|
+
function ensureSessionStoreSchema(db) {
|
|
50
|
+
applyRuntimePragmas(db);
|
|
51
|
+
db.exec(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
53
|
+
name TEXT PRIMARY KEY,
|
|
54
|
+
version INTEGER NOT NULL,
|
|
55
|
+
updated_at INTEGER NOT NULL
|
|
56
|
+
);
|
|
57
|
+
`);
|
|
58
|
+
db.exec(`
|
|
59
|
+
CREATE TABLE IF NOT EXISTS project (
|
|
60
|
+
id TEXT PRIMARY KEY,
|
|
61
|
+
cwd TEXT NOT NULL,
|
|
62
|
+
normalized_cwd TEXT NOT NULL,
|
|
63
|
+
name TEXT,
|
|
64
|
+
vcs TEXT,
|
|
65
|
+
time_created INTEGER NOT NULL,
|
|
66
|
+
time_updated INTEGER NOT NULL
|
|
67
|
+
);
|
|
68
|
+
`);
|
|
69
|
+
db.exec(`
|
|
70
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_project_normalized_cwd_unique
|
|
71
|
+
ON project(normalized_cwd);
|
|
72
|
+
`);
|
|
73
|
+
db.exec(`
|
|
74
|
+
CREATE TABLE IF NOT EXISTS session (
|
|
75
|
+
id TEXT PRIMARY KEY,
|
|
76
|
+
project_id TEXT,
|
|
77
|
+
cwd TEXT,
|
|
78
|
+
slug TEXT,
|
|
79
|
+
git_branch TEXT,
|
|
80
|
+
user_type TEXT,
|
|
81
|
+
created_at INTEGER NOT NULL,
|
|
82
|
+
updated_at INTEGER NOT NULL
|
|
83
|
+
);
|
|
84
|
+
`);
|
|
85
|
+
const sessionColumns = db.prepare(`PRAGMA table_info(session)`).all();
|
|
86
|
+
if (!sessionColumns.some((col) => col.name === "project_id")) {
|
|
87
|
+
db.exec(`ALTER TABLE session ADD COLUMN project_id TEXT;`);
|
|
88
|
+
}
|
|
89
|
+
db.exec(`
|
|
90
|
+
CREATE TABLE IF NOT EXISTS message (
|
|
91
|
+
uuid TEXT PRIMARY KEY,
|
|
92
|
+
session_id TEXT NOT NULL,
|
|
93
|
+
agent_id TEXT,
|
|
94
|
+
role TEXT NOT NULL,
|
|
95
|
+
parent_uuid TEXT,
|
|
96
|
+
logical_parent_uuid TEXT,
|
|
97
|
+
request_id TEXT,
|
|
98
|
+
is_api_error INTEGER NOT NULL DEFAULT 0,
|
|
99
|
+
time_created INTEGER NOT NULL,
|
|
100
|
+
raw_message_json TEXT NOT NULL,
|
|
101
|
+
updated_at INTEGER NOT NULL,
|
|
102
|
+
FOREIGN KEY(session_id) REFERENCES session(id) ON DELETE CASCADE
|
|
103
|
+
);
|
|
104
|
+
`);
|
|
105
|
+
db.exec(`
|
|
106
|
+
CREATE TABLE IF NOT EXISTS part (
|
|
107
|
+
id TEXT PRIMARY KEY,
|
|
108
|
+
message_uuid TEXT NOT NULL,
|
|
109
|
+
session_id TEXT NOT NULL,
|
|
110
|
+
part_index INTEGER NOT NULL,
|
|
111
|
+
part_type TEXT NOT NULL,
|
|
112
|
+
raw_part_json TEXT NOT NULL,
|
|
113
|
+
time_created INTEGER NOT NULL,
|
|
114
|
+
updated_at INTEGER NOT NULL,
|
|
115
|
+
FOREIGN KEY(message_uuid) REFERENCES message(uuid) ON DELETE CASCADE,
|
|
116
|
+
FOREIGN KEY(session_id) REFERENCES session(id) ON DELETE CASCADE
|
|
117
|
+
);
|
|
118
|
+
`);
|
|
119
|
+
db.exec(`
|
|
120
|
+
CREATE TABLE IF NOT EXISTS session_meta_event (
|
|
121
|
+
id TEXT PRIMARY KEY,
|
|
122
|
+
session_id TEXT NOT NULL,
|
|
123
|
+
event_type TEXT NOT NULL,
|
|
124
|
+
payload_json TEXT NOT NULL,
|
|
125
|
+
time_created INTEGER NOT NULL,
|
|
126
|
+
updated_at INTEGER NOT NULL,
|
|
127
|
+
FOREIGN KEY(session_id) REFERENCES session(id) ON DELETE CASCADE
|
|
128
|
+
);
|
|
129
|
+
`);
|
|
130
|
+
db.exec(`
|
|
131
|
+
CREATE TABLE IF NOT EXISTS session_summary (
|
|
132
|
+
id TEXT PRIMARY KEY,
|
|
133
|
+
session_id TEXT NOT NULL,
|
|
134
|
+
leaf_uuid TEXT,
|
|
135
|
+
summary TEXT NOT NULL,
|
|
136
|
+
time_created INTEGER NOT NULL,
|
|
137
|
+
updated_at INTEGER NOT NULL,
|
|
138
|
+
FOREIGN KEY(session_id) REFERENCES session(id) ON DELETE CASCADE
|
|
139
|
+
);
|
|
140
|
+
`);
|
|
141
|
+
db.exec(`
|
|
142
|
+
CREATE TABLE IF NOT EXISTS file_history_snapshot (
|
|
143
|
+
id TEXT PRIMARY KEY,
|
|
144
|
+
session_id TEXT NOT NULL,
|
|
145
|
+
message_uuid TEXT,
|
|
146
|
+
snapshot_json TEXT NOT NULL,
|
|
147
|
+
is_update INTEGER NOT NULL DEFAULT 0,
|
|
148
|
+
time_created INTEGER NOT NULL,
|
|
149
|
+
updated_at INTEGER NOT NULL,
|
|
150
|
+
FOREIGN KEY(session_id) REFERENCES session(id) ON DELETE CASCADE
|
|
151
|
+
);
|
|
152
|
+
`);
|
|
153
|
+
db.exec(`
|
|
154
|
+
CREATE INDEX IF NOT EXISTS idx_message_session_time_uuid
|
|
155
|
+
ON message(session_id, time_created, uuid);
|
|
156
|
+
`);
|
|
157
|
+
db.exec(`
|
|
158
|
+
CREATE INDEX IF NOT EXISTS idx_part_session_message_part_index
|
|
159
|
+
ON part(session_id, message_uuid, part_index);
|
|
160
|
+
`);
|
|
161
|
+
db.exec(`
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_meta_event_session_time
|
|
163
|
+
ON session_meta_event(session_id, time_created);
|
|
164
|
+
`);
|
|
165
|
+
db.exec(`
|
|
166
|
+
CREATE INDEX IF NOT EXISTS idx_session_project_updated
|
|
167
|
+
ON session(project_id, updated_at, id);
|
|
168
|
+
`);
|
|
169
|
+
const now = Date.now();
|
|
170
|
+
db.prepare(
|
|
171
|
+
`
|
|
172
|
+
INSERT INTO schema_version (name, version, updated_at)
|
|
173
|
+
VALUES (?1, ?2, ?3)
|
|
174
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
175
|
+
version = excluded.version,
|
|
176
|
+
updated_at = excluded.updated_at
|
|
177
|
+
`
|
|
178
|
+
).run("session_store", SESSION_STORE_SCHEMA_VERSION, now);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/utils/session/sessionProjectIdentity.ts
|
|
182
|
+
import { createHash } from "crypto";
|
|
183
|
+
import { realpathSync } from "fs";
|
|
184
|
+
function defaultRealpath(inputPath) {
|
|
185
|
+
try {
|
|
186
|
+
return realpathSync(inputPath);
|
|
187
|
+
} catch {
|
|
188
|
+
return inputPath;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function normalizeSessionProjectPath(inputPath, options = {}) {
|
|
192
|
+
const platform = options.platform ?? process.platform;
|
|
193
|
+
const realpathResolver = options.realpathResolver ?? defaultRealpath;
|
|
194
|
+
const resolved = realpathResolver(inputPath);
|
|
195
|
+
let normalized = String(resolved).replace(/\\/g, "/");
|
|
196
|
+
if (normalized.length > 1) {
|
|
197
|
+
normalized = normalized.replace(/\/+$/, "");
|
|
198
|
+
}
|
|
199
|
+
if (platform === "win32") {
|
|
200
|
+
normalized = normalized.replace(
|
|
201
|
+
/^([A-Z]):/,
|
|
202
|
+
(_m, drive) => `${drive.toLowerCase()}:`
|
|
203
|
+
);
|
|
204
|
+
normalized = normalized.toLowerCase();
|
|
205
|
+
}
|
|
206
|
+
return normalized;
|
|
207
|
+
}
|
|
208
|
+
function computeSessionProjectId(normalizedCwd) {
|
|
209
|
+
return createHash("sha256").update(normalizedCwd, "utf8").digest("hex");
|
|
210
|
+
}
|
|
211
|
+
function resolveSessionProjectIdentity(cwd, options = {}) {
|
|
212
|
+
const gitRootRunner = options.findGitRoot ?? findGitRoot;
|
|
213
|
+
const repoRoot = gitRootRunner(cwd);
|
|
214
|
+
const source = repoRoot ? "repo_root" : "cwd";
|
|
215
|
+
const projectCwd = repoRoot ?? cwd;
|
|
216
|
+
const normalizedCwd = normalizeSessionProjectPath(projectCwd, options);
|
|
217
|
+
const projectId = computeSessionProjectId(normalizedCwd);
|
|
218
|
+
return {
|
|
219
|
+
source,
|
|
220
|
+
projectCwd,
|
|
221
|
+
normalizedCwd,
|
|
222
|
+
projectId
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/utils/session/sessionSqlDualWriteTelemetry.ts
|
|
227
|
+
var state = {
|
|
228
|
+
successCount: 0,
|
|
229
|
+
failCount: 0,
|
|
230
|
+
totalLatencyMs: 0,
|
|
231
|
+
lastErrorCode: null,
|
|
232
|
+
projectResolveSuccessCount: 0,
|
|
233
|
+
projectResolveFailCount: 0
|
|
234
|
+
};
|
|
235
|
+
function recordSessionSqlDualWriteSuccess(latencyMs) {
|
|
236
|
+
state.successCount += 1;
|
|
237
|
+
state.totalLatencyMs += Math.max(0, Number(latencyMs) || 0);
|
|
238
|
+
}
|
|
239
|
+
function recordSessionSqlDualWriteFailure(errorCode) {
|
|
240
|
+
state.failCount += 1;
|
|
241
|
+
state.lastErrorCode = errorCode ? String(errorCode) : "SESSION_SQL_DUALWRITE_FAILED";
|
|
242
|
+
}
|
|
243
|
+
function recordSessionProjectResolveSuccess() {
|
|
244
|
+
state.projectResolveSuccessCount += 1;
|
|
245
|
+
}
|
|
246
|
+
function recordSessionProjectResolveFailure() {
|
|
247
|
+
state.projectResolveFailCount += 1;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/utils/session/sessionSqlStore.ts
|
|
251
|
+
var requireForSqlite = createRequire(import.meta.url);
|
|
252
|
+
var cachedDatabaseCtor;
|
|
253
|
+
function getDatabaseCtor() {
|
|
254
|
+
if (cachedDatabaseCtor !== void 0) return cachedDatabaseCtor;
|
|
255
|
+
try {
|
|
256
|
+
const mod = requireForSqlite("bun:sqlite");
|
|
257
|
+
if (typeof mod?.Database === "function") {
|
|
258
|
+
cachedDatabaseCtor = mod.Database;
|
|
259
|
+
return cachedDatabaseCtor;
|
|
260
|
+
}
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
cachedDatabaseCtor = null;
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
function getDatabaseCtorOrThrow() {
|
|
267
|
+
const Database = getDatabaseCtor();
|
|
268
|
+
if (Database) return Database;
|
|
269
|
+
const error = new Error(
|
|
270
|
+
"PYB_SESSION_SQL_UNAVAILABLE: bun:sqlite is unavailable for session store"
|
|
271
|
+
);
|
|
272
|
+
error.code = "PYB_SESSION_SQL_UNAVAILABLE";
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
function asNullableText(value) {
|
|
276
|
+
const text = String(value ?? "").trim();
|
|
277
|
+
return text ? text : null;
|
|
278
|
+
}
|
|
279
|
+
function asRole(value) {
|
|
280
|
+
return value === "assistant" || value === "progress" ? value : "user";
|
|
281
|
+
}
|
|
282
|
+
function asProjectCwd(value) {
|
|
283
|
+
const text = String(value ?? "").trim();
|
|
284
|
+
return text ? text : null;
|
|
285
|
+
}
|
|
286
|
+
function createSessionSqlStore(options) {
|
|
287
|
+
const dbFilePath = options?.dbFilePath ?? getSessionStoreDbPath();
|
|
288
|
+
if (!existsSync(dirname(dbFilePath))) {
|
|
289
|
+
mkdirSync(dirname(dbFilePath), { recursive: true });
|
|
290
|
+
}
|
|
291
|
+
const Database = getDatabaseCtorOrThrow();
|
|
292
|
+
const db = new Database(dbFilePath, { create: true });
|
|
293
|
+
ensureSessionStoreSchema(db);
|
|
294
|
+
const upsertProject = db.prepare(`
|
|
295
|
+
INSERT INTO project (id, cwd, normalized_cwd, name, vcs, time_created, time_updated)
|
|
296
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
|
|
297
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
298
|
+
cwd = excluded.cwd,
|
|
299
|
+
normalized_cwd = excluded.normalized_cwd,
|
|
300
|
+
name = COALESCE(excluded.name, project.name),
|
|
301
|
+
vcs = COALESCE(excluded.vcs, project.vcs),
|
|
302
|
+
time_updated = excluded.time_updated
|
|
303
|
+
`);
|
|
304
|
+
const upsertSession = db.prepare(`
|
|
305
|
+
INSERT INTO session (id, project_id, cwd, created_at, updated_at)
|
|
306
|
+
VALUES (?1, ?2, ?3, ?4, ?5)
|
|
307
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
308
|
+
project_id = COALESCE(excluded.project_id, session.project_id),
|
|
309
|
+
cwd = COALESCE(excluded.cwd, session.cwd),
|
|
310
|
+
updated_at = excluded.updated_at
|
|
311
|
+
`);
|
|
312
|
+
const upsertMessage = db.prepare(`
|
|
313
|
+
INSERT INTO message (
|
|
314
|
+
uuid, session_id, agent_id, role, parent_uuid, logical_parent_uuid,
|
|
315
|
+
request_id, is_api_error, time_created, raw_message_json, updated_at
|
|
316
|
+
)
|
|
317
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
|
|
318
|
+
ON CONFLICT(uuid) DO UPDATE SET
|
|
319
|
+
session_id = excluded.session_id,
|
|
320
|
+
agent_id = excluded.agent_id,
|
|
321
|
+
role = excluded.role,
|
|
322
|
+
parent_uuid = excluded.parent_uuid,
|
|
323
|
+
logical_parent_uuid = excluded.logical_parent_uuid,
|
|
324
|
+
request_id = excluded.request_id,
|
|
325
|
+
is_api_error = excluded.is_api_error,
|
|
326
|
+
time_created = excluded.time_created,
|
|
327
|
+
raw_message_json = excluded.raw_message_json,
|
|
328
|
+
updated_at = excluded.updated_at
|
|
329
|
+
`);
|
|
330
|
+
const upsertPart = db.prepare(`
|
|
331
|
+
INSERT INTO part (
|
|
332
|
+
id, message_uuid, session_id, part_index, part_type, raw_part_json, time_created, updated_at
|
|
333
|
+
)
|
|
334
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)
|
|
335
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
336
|
+
message_uuid = excluded.message_uuid,
|
|
337
|
+
session_id = excluded.session_id,
|
|
338
|
+
part_index = excluded.part_index,
|
|
339
|
+
part_type = excluded.part_type,
|
|
340
|
+
raw_part_json = excluded.raw_part_json,
|
|
341
|
+
time_created = excluded.time_created,
|
|
342
|
+
updated_at = excluded.updated_at
|
|
343
|
+
`);
|
|
344
|
+
const upsertSummary = db.prepare(`
|
|
345
|
+
INSERT INTO session_summary (
|
|
346
|
+
id, session_id, leaf_uuid, summary, time_created, updated_at
|
|
347
|
+
)
|
|
348
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
|
349
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
350
|
+
session_id = excluded.session_id,
|
|
351
|
+
leaf_uuid = excluded.leaf_uuid,
|
|
352
|
+
summary = excluded.summary,
|
|
353
|
+
time_created = excluded.time_created,
|
|
354
|
+
updated_at = excluded.updated_at
|
|
355
|
+
`);
|
|
356
|
+
const upsertMetaEvent = db.prepare(`
|
|
357
|
+
INSERT INTO session_meta_event (
|
|
358
|
+
id, session_id, event_type, payload_json, time_created, updated_at
|
|
359
|
+
)
|
|
360
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
|
361
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
362
|
+
session_id = excluded.session_id,
|
|
363
|
+
event_type = excluded.event_type,
|
|
364
|
+
payload_json = excluded.payload_json,
|
|
365
|
+
time_created = excluded.time_created,
|
|
366
|
+
updated_at = excluded.updated_at
|
|
367
|
+
`);
|
|
368
|
+
const upsertFileHistorySnapshot = db.prepare(`
|
|
369
|
+
INSERT INTO file_history_snapshot (
|
|
370
|
+
id, session_id, message_uuid, snapshot_json, is_update, time_created, updated_at
|
|
371
|
+
)
|
|
372
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
|
|
373
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
374
|
+
session_id = excluded.session_id,
|
|
375
|
+
message_uuid = excluded.message_uuid,
|
|
376
|
+
snapshot_json = excluded.snapshot_json,
|
|
377
|
+
is_update = excluded.is_update,
|
|
378
|
+
time_created = excluded.time_created,
|
|
379
|
+
updated_at = excluded.updated_at
|
|
380
|
+
`);
|
|
381
|
+
const resolveProjectId = (projectCwd, timeCreated, now) => {
|
|
382
|
+
if (!projectCwd) return null;
|
|
383
|
+
try {
|
|
384
|
+
const identity = resolveSessionProjectIdentity(projectCwd);
|
|
385
|
+
upsertProject.run(
|
|
386
|
+
identity.projectId,
|
|
387
|
+
identity.projectCwd,
|
|
388
|
+
identity.normalizedCwd,
|
|
389
|
+
null,
|
|
390
|
+
null,
|
|
391
|
+
timeCreated,
|
|
392
|
+
now
|
|
393
|
+
);
|
|
394
|
+
recordSessionProjectResolveSuccess();
|
|
395
|
+
return identity.projectId;
|
|
396
|
+
} catch {
|
|
397
|
+
recordSessionProjectResolveFailure();
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const appendMessages = (messages) => {
|
|
402
|
+
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
403
|
+
const now = Date.now();
|
|
404
|
+
const tx = db.transaction((list) => {
|
|
405
|
+
for (const item of list) {
|
|
406
|
+
const sessionId = String(item.sessionId ?? "").trim();
|
|
407
|
+
const uuid = String(item.uuid ?? "").trim();
|
|
408
|
+
if (!sessionId || !uuid) continue;
|
|
409
|
+
const timeCreated = Number(item.timeCreated) || now;
|
|
410
|
+
const projectCwd = asProjectCwd(item.projectCwd);
|
|
411
|
+
const projectId = resolveProjectId(projectCwd, timeCreated, now);
|
|
412
|
+
upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
|
|
413
|
+
upsertMessage.run(
|
|
414
|
+
uuid,
|
|
415
|
+
sessionId,
|
|
416
|
+
asNullableText(item.agentId),
|
|
417
|
+
asRole(item.role),
|
|
418
|
+
asNullableText(item.parentUuid),
|
|
419
|
+
asNullableText(item.logicalParentUuid),
|
|
420
|
+
asNullableText(item.requestId),
|
|
421
|
+
item.isApiError ? 1 : 0,
|
|
422
|
+
timeCreated,
|
|
423
|
+
JSON.stringify(item.rawMessage ?? {}),
|
|
424
|
+
now
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
tx(messages);
|
|
429
|
+
return messages.length;
|
|
430
|
+
};
|
|
431
|
+
const appendParts = (parts) => {
|
|
432
|
+
if (!Array.isArray(parts) || parts.length === 0) return 0;
|
|
433
|
+
const now = Date.now();
|
|
434
|
+
const tx = db.transaction((list) => {
|
|
435
|
+
for (const item of list) {
|
|
436
|
+
const id = String(item.id ?? "").trim();
|
|
437
|
+
const messageUuid = String(item.messageUuid ?? "").trim();
|
|
438
|
+
const sessionId = String(item.sessionId ?? "").trim();
|
|
439
|
+
if (!id || !messageUuid || !sessionId) continue;
|
|
440
|
+
const timeCreated = Number(item.timeCreated) || now;
|
|
441
|
+
const projectCwd = asProjectCwd(item.projectCwd);
|
|
442
|
+
const projectId = resolveProjectId(projectCwd, timeCreated, now);
|
|
443
|
+
upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
|
|
444
|
+
upsertPart.run(
|
|
445
|
+
id,
|
|
446
|
+
messageUuid,
|
|
447
|
+
sessionId,
|
|
448
|
+
Number(item.partIndex) || 0,
|
|
449
|
+
String(item.partType ?? "unknown"),
|
|
450
|
+
JSON.stringify(item.rawPart ?? {}),
|
|
451
|
+
timeCreated,
|
|
452
|
+
now
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
tx(parts);
|
|
457
|
+
return parts.length;
|
|
458
|
+
};
|
|
459
|
+
const appendSessionSummaries = (records) => {
|
|
460
|
+
if (!Array.isArray(records) || records.length === 0) return 0;
|
|
461
|
+
const now = Date.now();
|
|
462
|
+
const tx = db.transaction((list) => {
|
|
463
|
+
for (const item of list) {
|
|
464
|
+
const id = String(item.id ?? "").trim();
|
|
465
|
+
const sessionId = String(item.sessionId ?? "").trim();
|
|
466
|
+
if (!id || !sessionId) continue;
|
|
467
|
+
const timeCreated = Number(item.timeCreated) || now;
|
|
468
|
+
const projectCwd = asProjectCwd(item.projectCwd);
|
|
469
|
+
const projectId = resolveProjectId(projectCwd, timeCreated, now);
|
|
470
|
+
upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
|
|
471
|
+
upsertSummary.run(
|
|
472
|
+
id,
|
|
473
|
+
sessionId,
|
|
474
|
+
asNullableText(item.leafUuid),
|
|
475
|
+
String(item.summary ?? ""),
|
|
476
|
+
timeCreated,
|
|
477
|
+
now
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
tx(records);
|
|
482
|
+
return records.length;
|
|
483
|
+
};
|
|
484
|
+
const appendSessionMetaEvents = (records) => {
|
|
485
|
+
if (!Array.isArray(records) || records.length === 0) return 0;
|
|
486
|
+
const now = Date.now();
|
|
487
|
+
const tx = db.transaction((list) => {
|
|
488
|
+
for (const item of list) {
|
|
489
|
+
const id = String(item.id ?? "").trim();
|
|
490
|
+
const sessionId = String(item.sessionId ?? "").trim();
|
|
491
|
+
if (!id || !sessionId) continue;
|
|
492
|
+
const timeCreated = Number(item.timeCreated) || now;
|
|
493
|
+
const projectCwd = asProjectCwd(item.projectCwd);
|
|
494
|
+
const projectId = resolveProjectId(projectCwd, timeCreated, now);
|
|
495
|
+
upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
|
|
496
|
+
upsertMetaEvent.run(
|
|
497
|
+
id,
|
|
498
|
+
sessionId,
|
|
499
|
+
String(item.eventType ?? "unknown"),
|
|
500
|
+
JSON.stringify(item.payload ?? {}),
|
|
501
|
+
timeCreated,
|
|
502
|
+
now
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
tx(records);
|
|
507
|
+
return records.length;
|
|
508
|
+
};
|
|
509
|
+
const appendFileHistorySnapshots = (records) => {
|
|
510
|
+
if (!Array.isArray(records) || records.length === 0) return 0;
|
|
511
|
+
const now = Date.now();
|
|
512
|
+
const tx = db.transaction((list) => {
|
|
513
|
+
for (const item of list) {
|
|
514
|
+
const id = String(item.id ?? "").trim();
|
|
515
|
+
const sessionId = String(item.sessionId ?? "").trim();
|
|
516
|
+
if (!id || !sessionId) continue;
|
|
517
|
+
const timeCreated = Number(item.timeCreated) || now;
|
|
518
|
+
const projectCwd = asProjectCwd(item.projectCwd);
|
|
519
|
+
const projectId = resolveProjectId(projectCwd, timeCreated, now);
|
|
520
|
+
upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
|
|
521
|
+
upsertFileHistorySnapshot.run(
|
|
522
|
+
id,
|
|
523
|
+
sessionId,
|
|
524
|
+
asNullableText(item.messageUuid),
|
|
525
|
+
JSON.stringify(item.snapshot ?? {}),
|
|
526
|
+
item.isSnapshotUpdate ? 1 : 0,
|
|
527
|
+
timeCreated,
|
|
528
|
+
now
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
tx(records);
|
|
533
|
+
return records.length;
|
|
534
|
+
};
|
|
535
|
+
const loadMessages = (sessionId, options2 = {}) => {
|
|
536
|
+
const target = String(sessionId ?? "").trim();
|
|
537
|
+
if (!target) return [];
|
|
538
|
+
const fromTime = Number.isFinite(options2.fromTime) ? Number(options2.fromTime) : null;
|
|
539
|
+
const toTime = Number.isFinite(options2.toTime) ? Number(options2.toTime) : null;
|
|
540
|
+
const rows = db.prepare(
|
|
541
|
+
`
|
|
542
|
+
SELECT
|
|
543
|
+
session_id, uuid, role, time_created, raw_message_json,
|
|
544
|
+
agent_id, parent_uuid, logical_parent_uuid, request_id, is_api_error
|
|
545
|
+
FROM message
|
|
546
|
+
WHERE session_id = ?1
|
|
547
|
+
AND (?2 IS NULL OR time_created >= ?2)
|
|
548
|
+
AND (?3 IS NULL OR time_created <= ?3)
|
|
549
|
+
ORDER BY time_created ASC, uuid ASC
|
|
550
|
+
`
|
|
551
|
+
).all(target, fromTime, toTime);
|
|
552
|
+
return rows.map((row) => ({
|
|
553
|
+
sessionId: String(row.session_id),
|
|
554
|
+
uuid: String(row.uuid),
|
|
555
|
+
role: asRole(row.role),
|
|
556
|
+
timeCreated: Number(row.time_created) || 0,
|
|
557
|
+
rawMessage: JSON.parse(String(row.raw_message_json ?? "{}")),
|
|
558
|
+
agentId: asNullableText(row.agent_id),
|
|
559
|
+
parentUuid: asNullableText(row.parent_uuid),
|
|
560
|
+
logicalParentUuid: asNullableText(row.logical_parent_uuid),
|
|
561
|
+
requestId: asNullableText(row.request_id),
|
|
562
|
+
isApiError: Number(row.is_api_error ?? 0) > 0
|
|
563
|
+
}));
|
|
564
|
+
};
|
|
565
|
+
const loadSessionSummaries = (sessionId) => {
|
|
566
|
+
const target = String(sessionId ?? "").trim();
|
|
567
|
+
if (!target) return [];
|
|
568
|
+
const rows = db.prepare(
|
|
569
|
+
`
|
|
570
|
+
SELECT session_id, leaf_uuid, summary, time_created
|
|
571
|
+
FROM session_summary
|
|
572
|
+
WHERE session_id = ?1
|
|
573
|
+
ORDER BY time_created ASC, id ASC
|
|
574
|
+
`
|
|
575
|
+
).all(target);
|
|
576
|
+
return rows.map((row) => ({
|
|
577
|
+
sessionId: String(row.session_id),
|
|
578
|
+
leafUuid: asNullableText(row.leaf_uuid),
|
|
579
|
+
summary: String(row.summary ?? ""),
|
|
580
|
+
timeCreated: Number(row.time_created) || 0
|
|
581
|
+
}));
|
|
582
|
+
};
|
|
583
|
+
const loadSessionMetaEvents = (sessionId) => {
|
|
584
|
+
const target = String(sessionId ?? "").trim();
|
|
585
|
+
if (!target) return [];
|
|
586
|
+
const rows = db.prepare(
|
|
587
|
+
`
|
|
588
|
+
SELECT session_id, event_type, payload_json, time_created
|
|
589
|
+
FROM session_meta_event
|
|
590
|
+
WHERE session_id = ?1
|
|
591
|
+
ORDER BY time_created ASC, id ASC
|
|
592
|
+
`
|
|
593
|
+
).all(target);
|
|
594
|
+
return rows.map((row) => ({
|
|
595
|
+
sessionId: String(row.session_id),
|
|
596
|
+
eventType: String(row.event_type ?? ""),
|
|
597
|
+
payload: JSON.parse(String(row.payload_json ?? "{}")),
|
|
598
|
+
timeCreated: Number(row.time_created) || 0
|
|
599
|
+
}));
|
|
600
|
+
};
|
|
601
|
+
const loadFileHistorySnapshots = (sessionId) => {
|
|
602
|
+
const target = String(sessionId ?? "").trim();
|
|
603
|
+
if (!target) return [];
|
|
604
|
+
const rows = db.prepare(
|
|
605
|
+
`
|
|
606
|
+
SELECT session_id, message_uuid, snapshot_json, is_update, time_created
|
|
607
|
+
FROM file_history_snapshot
|
|
608
|
+
WHERE session_id = ?1
|
|
609
|
+
ORDER BY time_created ASC, id ASC
|
|
610
|
+
`
|
|
611
|
+
).all(target);
|
|
612
|
+
return rows.map((row) => ({
|
|
613
|
+
sessionId: String(row.session_id),
|
|
614
|
+
messageUuid: asNullableText(row.message_uuid),
|
|
615
|
+
snapshot: JSON.parse(String(row.snapshot_json ?? "{}")),
|
|
616
|
+
isSnapshotUpdate: Number(row.is_update ?? 0) > 0,
|
|
617
|
+
timeCreated: Number(row.time_created) || 0
|
|
618
|
+
}));
|
|
619
|
+
};
|
|
620
|
+
const findLatestSessionId = (cwd) => {
|
|
621
|
+
const projectScope = asProjectCwd(cwd);
|
|
622
|
+
if (projectScope) {
|
|
623
|
+
const scopeIdentity = resolveSessionProjectIdentity(projectScope);
|
|
624
|
+
const projectRow = db.prepare(
|
|
625
|
+
`
|
|
626
|
+
SELECT id
|
|
627
|
+
FROM session
|
|
628
|
+
WHERE project_id = ?1
|
|
629
|
+
ORDER BY updated_at DESC, id DESC
|
|
630
|
+
LIMIT 1
|
|
631
|
+
`
|
|
632
|
+
).get(scopeIdentity.projectId);
|
|
633
|
+
const projectScopedId = asNullableText(projectRow?.id);
|
|
634
|
+
if (projectScopedId) return projectScopedId;
|
|
635
|
+
const cwdRow = db.prepare(
|
|
636
|
+
`
|
|
637
|
+
SELECT id
|
|
638
|
+
FROM session
|
|
639
|
+
WHERE cwd = ?1
|
|
640
|
+
ORDER BY updated_at DESC, id DESC
|
|
641
|
+
LIMIT 1
|
|
642
|
+
`
|
|
643
|
+
).get(projectScope);
|
|
644
|
+
const cwdScopedId = asNullableText(cwdRow?.id);
|
|
645
|
+
if (cwdScopedId) return cwdScopedId;
|
|
646
|
+
}
|
|
647
|
+
const row = db.prepare(
|
|
648
|
+
`
|
|
649
|
+
SELECT session_id
|
|
650
|
+
FROM message
|
|
651
|
+
ORDER BY time_created DESC, uuid DESC
|
|
652
|
+
LIMIT 1
|
|
653
|
+
`
|
|
654
|
+
).get();
|
|
655
|
+
return asNullableText(row?.session_id);
|
|
656
|
+
};
|
|
657
|
+
const close = () => {
|
|
658
|
+
db.close();
|
|
659
|
+
};
|
|
660
|
+
return {
|
|
661
|
+
appendMessages,
|
|
662
|
+
appendParts,
|
|
663
|
+
appendSessionSummaries,
|
|
664
|
+
appendSessionMetaEvents,
|
|
665
|
+
appendFileHistorySnapshots,
|
|
666
|
+
loadSessionSummaries,
|
|
667
|
+
loadSessionMetaEvents,
|
|
668
|
+
loadFileHistorySnapshots,
|
|
669
|
+
loadMessages,
|
|
670
|
+
findLatestSessionId,
|
|
671
|
+
close
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
export {
|
|
676
|
+
getSessionStoreFlags,
|
|
677
|
+
getSessionStoreDbPath,
|
|
678
|
+
recordSessionSqlDualWriteSuccess,
|
|
679
|
+
recordSessionSqlDualWriteFailure,
|
|
680
|
+
createSessionSqlStore
|
|
681
|
+
};
|