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.
Files changed (165) hide show
  1. package/dist/REPL-K6NYKODR.js +51 -0
  2. package/dist/{acp-6UNV3LLZ.js → acp-5H7EXQK2.js} +33 -32
  3. package/dist/{acp-6UNV3LLZ.js.map → acp-5H7EXQK2.js.map} +1 -1
  4. package/dist/{agentsValidate-Q6TKU7TM.js → agentsValidate-QQUWQEIR.js} +7 -7
  5. package/dist/{ask-VKXARFSE.js → ask-2NXAGZUU.js} +32 -31
  6. package/dist/{ask-VKXARFSE.js.map → ask-2NXAGZUU.js.map} +1 -1
  7. package/dist/{autoUpdater-7EWH6KLS.js → autoUpdater-UZGQSBVX.js} +3 -3
  8. package/dist/{chunk-5SXLQSDA.js → chunk-2LDISGV5.js} +4 -1
  9. package/dist/{chunk-NHGHYVP4.js → chunk-4RFXQVAB.js} +2 -2
  10. package/dist/{chunk-NNLRGQH7.js → chunk-5LOOKSJJ.js} +2 -2
  11. package/dist/{chunk-K75Q3DNN.js → chunk-6FXN7WXV.js} +3 -3
  12. package/dist/{chunk-YTMIS255.js → chunk-7G3CESAX.js} +2 -2
  13. package/dist/{chunk-A7DBXB2F.js → chunk-7PKIDZYX.js} +3 -1
  14. package/dist/chunk-7PKIDZYX.js.map +7 -0
  15. package/dist/{chunk-3OHETUTC.js → chunk-7XKF4NS5.js} +1 -1
  16. package/dist/{chunk-BHQOSSZK.js → chunk-AIYDVZNU.js} +3 -3
  17. package/dist/{chunk-DUQMZDAG.js → chunk-AXW3EAEG.js} +3 -3
  18. package/dist/{chunk-P3H2FCWA.js → chunk-C5W7DK4B.js} +3 -3
  19. package/dist/chunk-DGOZRLG4.js +574 -0
  20. package/dist/chunk-DGOZRLG4.js.map +7 -0
  21. package/dist/{chunk-WPTE44L5.js → chunk-DQPL53A3.js} +4 -4
  22. package/dist/chunk-DSMH3DDQ.js +96 -0
  23. package/dist/chunk-DSMH3DDQ.js.map +7 -0
  24. package/dist/{chunk-C3FMLNZD.js → chunk-FBTRKZNM.js} +35 -167
  25. package/dist/chunk-FBTRKZNM.js.map +7 -0
  26. package/dist/{chunk-YGVF37PC.js → chunk-GTBOGB65.js} +3 -3
  27. package/dist/{chunk-AJ3UX6R7.js → chunk-H25IY2QB.js} +1 -1
  28. package/dist/{chunk-O7R3XZGO.js → chunk-H7HRAFNH.js} +15 -15
  29. package/dist/chunk-HHXEDAUY.js +681 -0
  30. package/dist/chunk-HHXEDAUY.js.map +7 -0
  31. package/dist/{chunk-EC3PLGG3.js → chunk-JU3X54OB.js} +2 -2
  32. package/dist/chunk-KFEHHKZ2.js +145 -0
  33. package/dist/chunk-KFEHHKZ2.js.map +7 -0
  34. package/dist/{chunk-JZJUCJTK.js → chunk-L6HMG5TD.js} +1 -1
  35. package/dist/{chunk-VXBBKE3Z.js → chunk-MVWCFCWA.js} +1 -1
  36. package/dist/{chunk-IZQYUXSZ.js → chunk-NNGD2UJL.js} +2 -2
  37. package/dist/{chunk-JUMRO5I7.js → chunk-PFHTQ2ON.js} +4 -4
  38. package/dist/{chunk-FCSVC7CP.js → chunk-QPX3VRTH.js} +4 -4
  39. package/dist/{chunk-OPAEJ3Y5.js → chunk-S7HIIXVN.js} +1 -1
  40. package/dist/{chunk-GSFBS4B4.js → chunk-T4BBPE5F.js} +3 -3
  41. package/dist/{chunk-5S2CPB42.js → chunk-T5ZQLE6E.js} +3 -3
  42. package/dist/{chunk-GDDO2XA3.js → chunk-UJ2SNURP.js} +1 -1
  43. package/dist/{chunk-7HPHH3FB.js → chunk-UOVFEY6P.js} +69 -48
  44. package/dist/{chunk-7HPHH3FB.js.map → chunk-UOVFEY6P.js.map} +3 -3
  45. package/dist/{chunk-LRKZ3RPS.js → chunk-UUM4Q5S6.js} +1 -1
  46. package/dist/{chunk-XSUCLDWY.js → chunk-W2DOITEM.js} +2 -2
  47. package/dist/{chunk-E4JH2XFM.js → chunk-XVF7DL3L.js} +1 -1
  48. package/dist/{cli-DFM7Z6AH.js → cli-5CKXURNM.js} +130 -102
  49. package/dist/cli-5CKXURNM.js.map +7 -0
  50. package/dist/commands-FVAUVYN5.js +55 -0
  51. package/dist/{config-XUPBT2EE.js → config-P6NPLNYJ.js} +4 -4
  52. package/dist/{context-TE7OR7RQ.js → context-KGCNIOLW.js} +7 -6
  53. package/dist/{conversationPersistence-24HWWB75.js → conversationPersistence-ZR5BNQEH.js} +3 -3
  54. package/dist/{conversationTracker-4JE7TNPU.js → conversationTracker-CWBOYHS6.js} +4 -4
  55. package/dist/{customCommands-OGYMS6BW.js → customCommands-FI35GWO7.js} +4 -4
  56. package/dist/{env-OFPQLCBS.js → env-XIHEMHIE.js} +2 -2
  57. package/dist/{file-X2XAPBRZ.js → file-WT4CNRBH.js} +4 -4
  58. package/dist/index.js +3 -3
  59. package/dist/{llm-6XIL53O7.js → llm-HPPHTPDB.js} +33 -32
  60. package/dist/{llm-6XIL53O7.js.map → llm-HPPHTPDB.js.map} +1 -1
  61. package/dist/{llmLazy-U2GIPU5C.js → llmLazy-76OBERV2.js} +1 -1
  62. package/dist/{loader-EGMA6CWF.js → loader-TS2HH5EN.js} +4 -4
  63. package/dist/{lsp-JMPOPT6A.js → lsp-KV7OBBMM.js} +6 -6
  64. package/dist/{lspAnchor-5PMHI5BV.js → lspAnchor-ZCANLR6C.js} +6 -6
  65. package/dist/{mcp-XSVQR6C6.js → mcp-MFOXCURO.js} +7 -7
  66. package/dist/{mentionProcessor-4MOOQMS7.js → mentionProcessor-4OQOE7GY.js} +5 -5
  67. package/dist/{messages-ZBGD2RVK.js → messages-NCRJ6QRS.js} +1 -1
  68. package/dist/{model-ECTUAZ5Q.js → model-QGIJDQKV.js} +5 -5
  69. package/dist/{openai-CRNKDQJ3.js → openai-PIMPLRHA.js} +5 -5
  70. package/dist/{outputStyles-Z4PB6UX5.js → outputStyles-VIR2WGDW.js} +4 -4
  71. package/dist/{pluginRuntime-DRDVDAUU.js → pluginRuntime-HM55RXJW.js} +6 -6
  72. package/dist/{pluginValidation-RHPC5SAR.js → pluginValidation-7TELFKDN.js} +6 -6
  73. package/dist/prompts-JUMG5DV4.js +57 -0
  74. package/dist/{pybAgentSessionLoad-YAEB2WL4.js → pybAgentSessionLoad-G6BSOKJV.js} +5 -6
  75. package/dist/{pybAgentSessionResume-C7MUM2PL.js → pybAgentSessionResume-GFO2HI4V.js} +5 -4
  76. package/dist/{pybAgentStreamJsonSession-3X3S5CI2.js → pybAgentStreamJsonSession-XJWWG4KQ.js} +1 -1
  77. package/dist/{pybHooks-DWLOM55R.js → pybHooks-MRBA3GKS.js} +4 -4
  78. package/dist/query-O5YZELUK.js +55 -0
  79. package/dist/{registry-MFGZRI5N.js → registry-VLNMWI4D.js} +5 -5
  80. package/dist/{ripgrep-P7LJLNZR.js → ripgrep-I4QCQBMN.js} +3 -3
  81. package/dist/{skillMarketplace-R5ZEB7NX.js → skillMarketplace-F3LNNAWT.js} +3 -3
  82. package/dist/{state-W25DUPH2.js → state-66VUERW2.js} +2 -2
  83. package/dist/{theme-YNA47SVG.js → theme-QGI5L27W.js} +5 -5
  84. package/dist/{toolPermissionSettings-IJR677NS.js → toolPermissionSettings-E4T44WBW.js} +6 -6
  85. package/dist/tools-4WOQWDGA.js +56 -0
  86. package/dist/{userInput-I2PLDULC.js → userInput-KKWPB5G6.js} +34 -33
  87. package/dist/{userInput-I2PLDULC.js.map → userInput-KKWPB5G6.js.map} +1 -1
  88. package/package.json +3 -1
  89. package/scripts/session-project-gate.mjs +95 -0
  90. package/dist/REPL-KRZBKRH2.js +0 -50
  91. package/dist/chunk-A7DBXB2F.js.map +0 -7
  92. package/dist/chunk-C3FMLNZD.js.map +0 -7
  93. package/dist/chunk-CDK4YHKS.js +0 -196
  94. package/dist/chunk-CDK4YHKS.js.map +0 -7
  95. package/dist/chunk-EJJSN2TT.js +0 -81
  96. package/dist/chunk-EJJSN2TT.js.map +0 -7
  97. package/dist/chunk-WHAWWM3Y.js +0 -138
  98. package/dist/chunk-WHAWWM3Y.js.map +0 -7
  99. package/dist/cli-DFM7Z6AH.js.map +0 -7
  100. package/dist/commands-E6P6G6RL.js +0 -54
  101. package/dist/prompts-XBRLSIXQ.js +0 -56
  102. package/dist/query-7M3GL2CM.js +0 -54
  103. package/dist/tools-XDOXLNVD.js +0 -55
  104. /package/dist/{REPL-KRZBKRH2.js.map → REPL-K6NYKODR.js.map} +0 -0
  105. /package/dist/{agentsValidate-Q6TKU7TM.js.map → agentsValidate-QQUWQEIR.js.map} +0 -0
  106. /package/dist/{autoUpdater-7EWH6KLS.js.map → autoUpdater-UZGQSBVX.js.map} +0 -0
  107. /package/dist/{chunk-5SXLQSDA.js.map → chunk-2LDISGV5.js.map} +0 -0
  108. /package/dist/{chunk-NHGHYVP4.js.map → chunk-4RFXQVAB.js.map} +0 -0
  109. /package/dist/{chunk-NNLRGQH7.js.map → chunk-5LOOKSJJ.js.map} +0 -0
  110. /package/dist/{chunk-K75Q3DNN.js.map → chunk-6FXN7WXV.js.map} +0 -0
  111. /package/dist/{chunk-YTMIS255.js.map → chunk-7G3CESAX.js.map} +0 -0
  112. /package/dist/{chunk-3OHETUTC.js.map → chunk-7XKF4NS5.js.map} +0 -0
  113. /package/dist/{chunk-BHQOSSZK.js.map → chunk-AIYDVZNU.js.map} +0 -0
  114. /package/dist/{chunk-DUQMZDAG.js.map → chunk-AXW3EAEG.js.map} +0 -0
  115. /package/dist/{chunk-P3H2FCWA.js.map → chunk-C5W7DK4B.js.map} +0 -0
  116. /package/dist/{chunk-WPTE44L5.js.map → chunk-DQPL53A3.js.map} +0 -0
  117. /package/dist/{chunk-YGVF37PC.js.map → chunk-GTBOGB65.js.map} +0 -0
  118. /package/dist/{chunk-AJ3UX6R7.js.map → chunk-H25IY2QB.js.map} +0 -0
  119. /package/dist/{chunk-O7R3XZGO.js.map → chunk-H7HRAFNH.js.map} +0 -0
  120. /package/dist/{chunk-EC3PLGG3.js.map → chunk-JU3X54OB.js.map} +0 -0
  121. /package/dist/{chunk-JZJUCJTK.js.map → chunk-L6HMG5TD.js.map} +0 -0
  122. /package/dist/{chunk-VXBBKE3Z.js.map → chunk-MVWCFCWA.js.map} +0 -0
  123. /package/dist/{chunk-IZQYUXSZ.js.map → chunk-NNGD2UJL.js.map} +0 -0
  124. /package/dist/{chunk-JUMRO5I7.js.map → chunk-PFHTQ2ON.js.map} +0 -0
  125. /package/dist/{chunk-FCSVC7CP.js.map → chunk-QPX3VRTH.js.map} +0 -0
  126. /package/dist/{chunk-OPAEJ3Y5.js.map → chunk-S7HIIXVN.js.map} +0 -0
  127. /package/dist/{chunk-GSFBS4B4.js.map → chunk-T4BBPE5F.js.map} +0 -0
  128. /package/dist/{chunk-5S2CPB42.js.map → chunk-T5ZQLE6E.js.map} +0 -0
  129. /package/dist/{chunk-GDDO2XA3.js.map → chunk-UJ2SNURP.js.map} +0 -0
  130. /package/dist/{chunk-LRKZ3RPS.js.map → chunk-UUM4Q5S6.js.map} +0 -0
  131. /package/dist/{chunk-XSUCLDWY.js.map → chunk-W2DOITEM.js.map} +0 -0
  132. /package/dist/{chunk-E4JH2XFM.js.map → chunk-XVF7DL3L.js.map} +0 -0
  133. /package/dist/{commands-E6P6G6RL.js.map → commands-FVAUVYN5.js.map} +0 -0
  134. /package/dist/{config-XUPBT2EE.js.map → config-P6NPLNYJ.js.map} +0 -0
  135. /package/dist/{context-TE7OR7RQ.js.map → context-KGCNIOLW.js.map} +0 -0
  136. /package/dist/{conversationPersistence-24HWWB75.js.map → conversationPersistence-ZR5BNQEH.js.map} +0 -0
  137. /package/dist/{conversationTracker-4JE7TNPU.js.map → conversationTracker-CWBOYHS6.js.map} +0 -0
  138. /package/dist/{customCommands-OGYMS6BW.js.map → customCommands-FI35GWO7.js.map} +0 -0
  139. /package/dist/{env-OFPQLCBS.js.map → env-XIHEMHIE.js.map} +0 -0
  140. /package/dist/{file-X2XAPBRZ.js.map → file-WT4CNRBH.js.map} +0 -0
  141. /package/dist/{llmLazy-U2GIPU5C.js.map → llmLazy-76OBERV2.js.map} +0 -0
  142. /package/dist/{loader-EGMA6CWF.js.map → loader-TS2HH5EN.js.map} +0 -0
  143. /package/dist/{lsp-JMPOPT6A.js.map → lsp-KV7OBBMM.js.map} +0 -0
  144. /package/dist/{lspAnchor-5PMHI5BV.js.map → lspAnchor-ZCANLR6C.js.map} +0 -0
  145. /package/dist/{mcp-XSVQR6C6.js.map → mcp-MFOXCURO.js.map} +0 -0
  146. /package/dist/{mentionProcessor-4MOOQMS7.js.map → mentionProcessor-4OQOE7GY.js.map} +0 -0
  147. /package/dist/{messages-ZBGD2RVK.js.map → messages-NCRJ6QRS.js.map} +0 -0
  148. /package/dist/{model-ECTUAZ5Q.js.map → model-QGIJDQKV.js.map} +0 -0
  149. /package/dist/{openai-CRNKDQJ3.js.map → openai-PIMPLRHA.js.map} +0 -0
  150. /package/dist/{outputStyles-Z4PB6UX5.js.map → outputStyles-VIR2WGDW.js.map} +0 -0
  151. /package/dist/{pluginRuntime-DRDVDAUU.js.map → pluginRuntime-HM55RXJW.js.map} +0 -0
  152. /package/dist/{pluginValidation-RHPC5SAR.js.map → pluginValidation-7TELFKDN.js.map} +0 -0
  153. /package/dist/{prompts-XBRLSIXQ.js.map → prompts-JUMG5DV4.js.map} +0 -0
  154. /package/dist/{pybAgentSessionLoad-YAEB2WL4.js.map → pybAgentSessionLoad-G6BSOKJV.js.map} +0 -0
  155. /package/dist/{pybAgentSessionResume-C7MUM2PL.js.map → pybAgentSessionResume-GFO2HI4V.js.map} +0 -0
  156. /package/dist/{pybAgentStreamJsonSession-3X3S5CI2.js.map → pybAgentStreamJsonSession-XJWWG4KQ.js.map} +0 -0
  157. /package/dist/{pybHooks-DWLOM55R.js.map → pybHooks-MRBA3GKS.js.map} +0 -0
  158. /package/dist/{query-7M3GL2CM.js.map → query-O5YZELUK.js.map} +0 -0
  159. /package/dist/{registry-MFGZRI5N.js.map → registry-VLNMWI4D.js.map} +0 -0
  160. /package/dist/{ripgrep-P7LJLNZR.js.map → ripgrep-I4QCQBMN.js.map} +0 -0
  161. /package/dist/{skillMarketplace-R5ZEB7NX.js.map → skillMarketplace-F3LNNAWT.js.map} +0 -0
  162. /package/dist/{state-W25DUPH2.js.map → state-66VUERW2.js.map} +0 -0
  163. /package/dist/{theme-YNA47SVG.js.map → theme-QGI5L27W.js.map} +0 -0
  164. /package/dist/{toolPermissionSettings-IJR677NS.js.map → toolPermissionSettings-E4T44WBW.js.map} +0 -0
  165. /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
+ };