pybao-cli 1.5.23 → 1.5.25

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 (162) hide show
  1. package/dist/REPL-AWUJ6DTI.js +51 -0
  2. package/dist/{acp-5G7LPADD.js → acp-3G6FUTMV.js} +32 -31
  3. package/dist/{acp-5G7LPADD.js.map → acp-3G6FUTMV.js.map} +1 -1
  4. package/dist/{agentsValidate-BIRAVXBL.js → agentsValidate-7J62UR4G.js} +7 -7
  5. package/dist/{ask-XQZT6WIO.js → ask-DPX5KTMK.js} +31 -30
  6. package/dist/{ask-XQZT6WIO.js.map → ask-DPX5KTMK.js.map} +1 -1
  7. package/dist/{autoUpdater-DDJAJPKA.js → autoUpdater-7CK6CMUK.js} +3 -3
  8. package/dist/{chunk-XEVB4WON.js → chunk-2JSYG54Z.js} +15 -15
  9. package/dist/{chunk-GU4XA76N.js → chunk-3COHIXJE.js} +3 -3
  10. package/dist/{chunk-W7VIESST.js → chunk-3JZI3ZBU.js} +3 -3
  11. package/dist/{chunk-5B7UCAYL.js → chunk-3RKGBZUV.js} +1 -1
  12. package/dist/{chunk-ABJT5MG2.js → chunk-6PW6SJXE.js} +1 -1
  13. package/dist/{chunk-N7GEPTZB.js → chunk-6UGNUC4K.js} +3 -3
  14. package/dist/{chunk-4ZZYPG6P.js → chunk-BDHA3QOT.js} +4 -4
  15. package/dist/{chunk-MN77HNBB.js → chunk-BOOTTYGZ.js} +4 -4
  16. package/dist/{chunk-CNMNKSWQ.js → chunk-CVPWG3IX.js} +3 -3
  17. package/dist/{chunk-6QGIRDZS.js → chunk-FXUTVJRS.js} +1 -1
  18. package/dist/{chunk-2GHNW642.js → chunk-HL6ARNBJ.js} +1 -1
  19. package/dist/{chunk-MMW6MLFR.js → chunk-HSAO34GP.js} +2 -2
  20. package/dist/{chunk-KQZAS4DO.js → chunk-I377E5OW.js} +17 -25
  21. package/dist/chunk-I377E5OW.js.map +7 -0
  22. package/dist/{chunk-QSMZLK7K.js → chunk-IBRK4QMC.js} +3 -3
  23. package/dist/{chunk-2SVUNNJB.js → chunk-K3DSRWYV.js} +2 -2
  24. package/dist/chunk-KFEHHKZ2.js +145 -0
  25. package/dist/chunk-KFEHHKZ2.js.map +7 -0
  26. package/dist/{chunk-76BOJQUE.js → chunk-KNPPPVBG.js} +1 -1
  27. package/dist/{chunk-7SYDIES4.js → chunk-KP3LQCMR.js} +5 -1
  28. package/dist/chunk-KP3LQCMR.js.map +7 -0
  29. package/dist/{chunk-V22PQM4W.js → chunk-LGQJPZKC.js} +3 -3
  30. package/dist/{chunk-S65MIABQ.js → chunk-NSPYODPF.js} +4 -4
  31. package/dist/{chunk-A6QEPK5J.js → chunk-OZBYDL7N.js} +2 -2
  32. package/dist/{chunk-C2GNLGBM.js → chunk-RBLKS6FX.js} +1 -1
  33. package/dist/{chunk-G5MP72ZL.js → chunk-RVTZE6UF.js} +181 -15
  34. package/dist/chunk-RVTZE6UF.js.map +7 -0
  35. package/dist/{chunk-M7FEUIHO.js → chunk-SAVBIJ5O.js} +2 -2
  36. package/dist/{chunk-CT7LWVB7.js → chunk-SVRRQBLT.js} +1 -1
  37. package/dist/{chunk-VVXC3SNP.js → chunk-THSULC47.js} +35 -167
  38. package/dist/chunk-THSULC47.js.map +7 -0
  39. package/dist/{chunk-PUPDIRI6.js → chunk-TO2NPV6U.js} +2 -2
  40. package/dist/{chunk-652OMXEE.js → chunk-V4UJI656.js} +2 -2
  41. package/dist/{chunk-QCI5HPTA.js → chunk-VGFXCETY.js} +1 -1
  42. package/dist/{chunk-ZB3ZWD2K.js → chunk-VJFKQQTV.js} +2 -2
  43. package/dist/{chunk-ZB3ZWD2K.js.map → chunk-VJFKQQTV.js.map} +2 -2
  44. package/dist/{chunk-O7LWCCRJ.js → chunk-WIQFF44D.js} +3 -3
  45. package/dist/{chunk-LBDLSBXN.js → chunk-WLEPTDKU.js} +1 -1
  46. package/dist/{chunk-3CC7QXCN.js → chunk-Z75SOPJ5.js} +165 -40
  47. package/dist/{chunk-3CC7QXCN.js.map → chunk-Z75SOPJ5.js.map} +3 -3
  48. package/dist/{cli-YIANCHDD.js → cli-2DWH2RIO.js} +92 -91
  49. package/dist/{cli-YIANCHDD.js.map → cli-2DWH2RIO.js.map} +1 -1
  50. package/dist/commands-OXOLWX75.js +55 -0
  51. package/dist/{config-QVH3VNUQ.js → config-MDAX3T7G.js} +4 -4
  52. package/dist/{context-5VXEWH3G.js → context-S4ASBZ3O.js} +7 -6
  53. package/dist/{conversationPersistence-INUNJHOV.js → conversationPersistence-WIBFJR62.js} +3 -3
  54. package/dist/{conversationTracker-H25IOHBE.js → conversationTracker-X53D6RLQ.js} +4 -4
  55. package/dist/{customCommands-7RZHKH2K.js → customCommands-S3CSA3GB.js} +4 -4
  56. package/dist/{env-DPJTGHMP.js → env-P2GOYAXV.js} +2 -2
  57. package/dist/{file-D7W2FBZP.js → file-HUPYIU7Y.js} +4 -4
  58. package/dist/index.js +3 -3
  59. package/dist/{llm-TOU5REY5.js → llm-KOMOHPJY.js} +108 -39
  60. package/dist/llm-KOMOHPJY.js.map +7 -0
  61. package/dist/{llmLazy-HSKKIGLC.js → llmLazy-MXAQT2DG.js} +1 -1
  62. package/dist/{loader-YUP6OJTJ.js → loader-CFPDXJTQ.js} +4 -4
  63. package/dist/{lsp-7QKC4DVK.js → lsp-XR7JCI4Q.js} +6 -6
  64. package/dist/{lspAnchor-LCRZ23GA.js → lspAnchor-CY46EOLW.js} +6 -6
  65. package/dist/{mcp-KK6BOD6I.js → mcp-MACS532E.js} +7 -7
  66. package/dist/{mentionProcessor-V6JH6HUD.js → mentionProcessor-WT7DIUO6.js} +5 -5
  67. package/dist/{messages-7NVTXWIJ.js → messages-TQAKPPWM.js} +1 -1
  68. package/dist/{model-QSDSUJDB.js → model-R7YMMBAR.js} +5 -5
  69. package/dist/{openai-JC3KJN3H.js → openai-BISFRGPN.js} +5 -5
  70. package/dist/{outputStyles-TPH3CCB4.js → outputStyles-HLA3OEH2.js} +4 -4
  71. package/dist/{pluginRuntime-7EK4LQDD.js → pluginRuntime-LD6VPBWN.js} +6 -6
  72. package/dist/{pluginValidation-BJWCS55I.js → pluginValidation-MQFVM3M5.js} +6 -6
  73. package/dist/prompts-BFS3LOCS.js +57 -0
  74. package/dist/{pybAgentSessionLoad-V3IAJJPS.js → pybAgentSessionLoad-BQJ2JPPT.js} +5 -4
  75. package/dist/{pybAgentSessionResume-WE7ET356.js → pybAgentSessionResume-BBX6KVFN.js} +5 -4
  76. package/dist/{pybAgentStreamJsonSession-VWDYV4XL.js → pybAgentStreamJsonSession-N2AYCHRN.js} +1 -1
  77. package/dist/{pybHooks-UV7BTIVT.js → pybHooks-U4ATAT57.js} +4 -4
  78. package/dist/query-PZKEVMJY.js +55 -0
  79. package/dist/{registry-FK6UGJPV.js → registry-G2FLVWSF.js} +5 -5
  80. package/dist/{ripgrep-CXJ4DFPU.js → ripgrep-NPYGQPV3.js} +3 -3
  81. package/dist/{skillMarketplace-QUJXDKZK.js → skillMarketplace-H5P3PRHJ.js} +3 -3
  82. package/dist/{state-GC3XELIE.js → state-RM2QGI3K.js} +2 -2
  83. package/dist/{theme-24PLJSPD.js → theme-6GGT3D7J.js} +5 -5
  84. package/dist/{toolPermissionSettings-S6NJPBKT.js → toolPermissionSettings-IC6ELOVR.js} +6 -6
  85. package/dist/tools-F4GLOVTV.js +56 -0
  86. package/dist/{userInput-4VZSNII7.js → userInput-O26M5EYX.js} +33 -32
  87. package/dist/{userInput-4VZSNII7.js.map → userInput-O26M5EYX.js.map} +1 -1
  88. package/package.json +5 -1
  89. package/scripts/protected-tool-names-gate.mjs +102 -0
  90. package/scripts/session-project-gate.mjs +95 -0
  91. package/dist/REPL-CI5ET6VF.js +0 -50
  92. package/dist/chunk-7SYDIES4.js.map +0 -7
  93. package/dist/chunk-G5MP72ZL.js.map +0 -7
  94. package/dist/chunk-KQZAS4DO.js.map +0 -7
  95. package/dist/chunk-VVXC3SNP.js.map +0 -7
  96. package/dist/commands-4YMZW52K.js +0 -54
  97. package/dist/llm-TOU5REY5.js.map +0 -7
  98. package/dist/prompts-KQNPPEOG.js +0 -56
  99. package/dist/query-KAZY5LOW.js +0 -54
  100. package/dist/tools-NC5R4I6F.js +0 -55
  101. /package/dist/{REPL-CI5ET6VF.js.map → REPL-AWUJ6DTI.js.map} +0 -0
  102. /package/dist/{agentsValidate-BIRAVXBL.js.map → agentsValidate-7J62UR4G.js.map} +0 -0
  103. /package/dist/{autoUpdater-DDJAJPKA.js.map → autoUpdater-7CK6CMUK.js.map} +0 -0
  104. /package/dist/{chunk-XEVB4WON.js.map → chunk-2JSYG54Z.js.map} +0 -0
  105. /package/dist/{chunk-GU4XA76N.js.map → chunk-3COHIXJE.js.map} +0 -0
  106. /package/dist/{chunk-W7VIESST.js.map → chunk-3JZI3ZBU.js.map} +0 -0
  107. /package/dist/{chunk-5B7UCAYL.js.map → chunk-3RKGBZUV.js.map} +0 -0
  108. /package/dist/{chunk-ABJT5MG2.js.map → chunk-6PW6SJXE.js.map} +0 -0
  109. /package/dist/{chunk-N7GEPTZB.js.map → chunk-6UGNUC4K.js.map} +0 -0
  110. /package/dist/{chunk-4ZZYPG6P.js.map → chunk-BDHA3QOT.js.map} +0 -0
  111. /package/dist/{chunk-MN77HNBB.js.map → chunk-BOOTTYGZ.js.map} +0 -0
  112. /package/dist/{chunk-CNMNKSWQ.js.map → chunk-CVPWG3IX.js.map} +0 -0
  113. /package/dist/{chunk-6QGIRDZS.js.map → chunk-FXUTVJRS.js.map} +0 -0
  114. /package/dist/{chunk-2GHNW642.js.map → chunk-HL6ARNBJ.js.map} +0 -0
  115. /package/dist/{chunk-MMW6MLFR.js.map → chunk-HSAO34GP.js.map} +0 -0
  116. /package/dist/{chunk-QSMZLK7K.js.map → chunk-IBRK4QMC.js.map} +0 -0
  117. /package/dist/{chunk-2SVUNNJB.js.map → chunk-K3DSRWYV.js.map} +0 -0
  118. /package/dist/{chunk-76BOJQUE.js.map → chunk-KNPPPVBG.js.map} +0 -0
  119. /package/dist/{chunk-V22PQM4W.js.map → chunk-LGQJPZKC.js.map} +0 -0
  120. /package/dist/{chunk-S65MIABQ.js.map → chunk-NSPYODPF.js.map} +0 -0
  121. /package/dist/{chunk-A6QEPK5J.js.map → chunk-OZBYDL7N.js.map} +0 -0
  122. /package/dist/{chunk-C2GNLGBM.js.map → chunk-RBLKS6FX.js.map} +0 -0
  123. /package/dist/{chunk-M7FEUIHO.js.map → chunk-SAVBIJ5O.js.map} +0 -0
  124. /package/dist/{chunk-CT7LWVB7.js.map → chunk-SVRRQBLT.js.map} +0 -0
  125. /package/dist/{chunk-PUPDIRI6.js.map → chunk-TO2NPV6U.js.map} +0 -0
  126. /package/dist/{chunk-652OMXEE.js.map → chunk-V4UJI656.js.map} +0 -0
  127. /package/dist/{chunk-QCI5HPTA.js.map → chunk-VGFXCETY.js.map} +0 -0
  128. /package/dist/{chunk-O7LWCCRJ.js.map → chunk-WIQFF44D.js.map} +0 -0
  129. /package/dist/{chunk-LBDLSBXN.js.map → chunk-WLEPTDKU.js.map} +0 -0
  130. /package/dist/{commands-4YMZW52K.js.map → commands-OXOLWX75.js.map} +0 -0
  131. /package/dist/{config-QVH3VNUQ.js.map → config-MDAX3T7G.js.map} +0 -0
  132. /package/dist/{context-5VXEWH3G.js.map → context-S4ASBZ3O.js.map} +0 -0
  133. /package/dist/{conversationPersistence-INUNJHOV.js.map → conversationPersistence-WIBFJR62.js.map} +0 -0
  134. /package/dist/{conversationTracker-H25IOHBE.js.map → conversationTracker-X53D6RLQ.js.map} +0 -0
  135. /package/dist/{customCommands-7RZHKH2K.js.map → customCommands-S3CSA3GB.js.map} +0 -0
  136. /package/dist/{env-DPJTGHMP.js.map → env-P2GOYAXV.js.map} +0 -0
  137. /package/dist/{file-D7W2FBZP.js.map → file-HUPYIU7Y.js.map} +0 -0
  138. /package/dist/{llmLazy-HSKKIGLC.js.map → llmLazy-MXAQT2DG.js.map} +0 -0
  139. /package/dist/{loader-YUP6OJTJ.js.map → loader-CFPDXJTQ.js.map} +0 -0
  140. /package/dist/{lsp-7QKC4DVK.js.map → lsp-XR7JCI4Q.js.map} +0 -0
  141. /package/dist/{lspAnchor-LCRZ23GA.js.map → lspAnchor-CY46EOLW.js.map} +0 -0
  142. /package/dist/{mcp-KK6BOD6I.js.map → mcp-MACS532E.js.map} +0 -0
  143. /package/dist/{mentionProcessor-V6JH6HUD.js.map → mentionProcessor-WT7DIUO6.js.map} +0 -0
  144. /package/dist/{messages-7NVTXWIJ.js.map → messages-TQAKPPWM.js.map} +0 -0
  145. /package/dist/{model-QSDSUJDB.js.map → model-R7YMMBAR.js.map} +0 -0
  146. /package/dist/{openai-JC3KJN3H.js.map → openai-BISFRGPN.js.map} +0 -0
  147. /package/dist/{outputStyles-TPH3CCB4.js.map → outputStyles-HLA3OEH2.js.map} +0 -0
  148. /package/dist/{pluginRuntime-7EK4LQDD.js.map → pluginRuntime-LD6VPBWN.js.map} +0 -0
  149. /package/dist/{pluginValidation-BJWCS55I.js.map → pluginValidation-MQFVM3M5.js.map} +0 -0
  150. /package/dist/{prompts-KQNPPEOG.js.map → prompts-BFS3LOCS.js.map} +0 -0
  151. /package/dist/{pybAgentSessionLoad-V3IAJJPS.js.map → pybAgentSessionLoad-BQJ2JPPT.js.map} +0 -0
  152. /package/dist/{pybAgentSessionResume-WE7ET356.js.map → pybAgentSessionResume-BBX6KVFN.js.map} +0 -0
  153. /package/dist/{pybAgentStreamJsonSession-VWDYV4XL.js.map → pybAgentStreamJsonSession-N2AYCHRN.js.map} +0 -0
  154. /package/dist/{pybHooks-UV7BTIVT.js.map → pybHooks-U4ATAT57.js.map} +0 -0
  155. /package/dist/{query-KAZY5LOW.js.map → query-PZKEVMJY.js.map} +0 -0
  156. /package/dist/{registry-FK6UGJPV.js.map → registry-G2FLVWSF.js.map} +0 -0
  157. /package/dist/{ripgrep-CXJ4DFPU.js.map → ripgrep-NPYGQPV3.js.map} +0 -0
  158. /package/dist/{skillMarketplace-QUJXDKZK.js.map → skillMarketplace-H5P3PRHJ.js.map} +0 -0
  159. /package/dist/{state-GC3XELIE.js.map → state-RM2QGI3K.js.map} +0 -0
  160. /package/dist/{theme-24PLJSPD.js.map → theme-6GGT3D7J.js.map} +0 -0
  161. /package/dist/{toolPermissionSettings-S6NJPBKT.js.map → toolPermissionSettings-IC6ELOVR.js.map} +0 -0
  162. /package/dist/{tools-NC5R4I6F.js.map → tools-F4GLOVTV.js.map} +0 -0
@@ -0,0 +1,145 @@
1
+ import { createRequire as __pybCreateRequire } from "node:module";
2
+ const require = __pybCreateRequire(import.meta.url);
3
+
4
+ // src/utils/config/projectInstructions.ts
5
+ import { existsSync, readFileSync } from "fs";
6
+ import { dirname, join, parse, relative, resolve, sep } from "path";
7
+ var DEFAULT_PROJECT_DOC_MAX_BYTES = 32 * 1024;
8
+ function isRegularFile(path) {
9
+ try {
10
+ return existsSync(path);
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+ function findGitRoot(startDir) {
16
+ let currentDir = resolve(startDir);
17
+ const fsRoot = parse(currentDir).root;
18
+ while (true) {
19
+ const dotGitPath = join(currentDir, ".git");
20
+ if (existsSync(dotGitPath)) {
21
+ return currentDir;
22
+ }
23
+ if (currentDir === fsRoot) {
24
+ return null;
25
+ }
26
+ currentDir = dirname(currentDir);
27
+ }
28
+ }
29
+ function getDirsFromGitRootToCwd(gitRoot, cwd) {
30
+ const absoluteGitRoot = resolve(gitRoot);
31
+ const absoluteCwd = resolve(cwd);
32
+ const rel = relative(absoluteGitRoot, absoluteCwd);
33
+ if (!rel || rel === ".") {
34
+ return [absoluteGitRoot];
35
+ }
36
+ const parts = rel.split(sep).filter(Boolean);
37
+ const dirs = [absoluteGitRoot];
38
+ for (let i = 0; i < parts.length; i++) {
39
+ dirs.push(join(absoluteGitRoot, ...parts.slice(0, i + 1)));
40
+ }
41
+ return dirs;
42
+ }
43
+ function getProjectInstructionFiles(cwd) {
44
+ const gitRoot = findGitRoot(cwd);
45
+ const root = gitRoot ?? resolve(cwd);
46
+ const dirs = getDirsFromGitRootToCwd(root, cwd);
47
+ const results = [];
48
+ for (const dir of dirs) {
49
+ const overridePath = join(dir, "AGENTS.override.md");
50
+ const agentsPath = join(dir, "AGENTS.md");
51
+ if (isRegularFile(overridePath)) {
52
+ results.push({
53
+ absolutePath: overridePath,
54
+ relativePathFromGitRoot: relative(root, overridePath) || "AGENTS.override.md",
55
+ filename: "AGENTS.override.md"
56
+ });
57
+ continue;
58
+ }
59
+ if (isRegularFile(agentsPath)) {
60
+ results.push({
61
+ absolutePath: agentsPath,
62
+ relativePathFromGitRoot: relative(root, agentsPath) || "AGENTS.md",
63
+ filename: "AGENTS.md"
64
+ });
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ function getProjectDocMaxBytes() {
70
+ const raw = process.env.PYB_PROJECT_DOC_MAX_BYTES;
71
+ if (!raw) return DEFAULT_PROJECT_DOC_MAX_BYTES;
72
+ const parsed = Number.parseInt(raw, 10);
73
+ if (!Number.isFinite(parsed) || parsed <= 0)
74
+ return DEFAULT_PROJECT_DOC_MAX_BYTES;
75
+ return parsed;
76
+ }
77
+ function readAndConcatProjectInstructionFiles(files, {
78
+ maxBytes = getProjectDocMaxBytes(),
79
+ includeHeadings = true
80
+ } = {}) {
81
+ let totalBytes = 0;
82
+ let truncated = false;
83
+ const parts = [];
84
+ const truncateUtf8ToBytes = (value, bytes) => {
85
+ const buf = Buffer.from(value, "utf8");
86
+ if (buf.length <= bytes) return value;
87
+ return buf.subarray(0, Math.max(0, bytes)).toString("utf8");
88
+ };
89
+ for (const file of files) {
90
+ if (totalBytes >= maxBytes) {
91
+ truncated = true;
92
+ break;
93
+ }
94
+ let raw;
95
+ try {
96
+ raw = readFileSync(file.absolutePath, "utf-8");
97
+ } catch {
98
+ continue;
99
+ }
100
+ if (!raw.trim()) continue;
101
+ const separator = parts.length > 0 ? "\n\n" : "";
102
+ const separatorBytes = Buffer.byteLength(separator, "utf8");
103
+ const remainingAfterSeparator = maxBytes - totalBytes - separatorBytes;
104
+ if (remainingAfterSeparator <= 0) {
105
+ truncated = true;
106
+ break;
107
+ }
108
+ const heading = includeHeadings ? `# ${file.filename}
109
+
110
+ _Path: ${file.relativePathFromGitRoot}_
111
+
112
+ ` : "";
113
+ const block = `${heading}${raw}`.trimEnd();
114
+ const blockBytes = Buffer.byteLength(block, "utf8");
115
+ if (blockBytes <= remainingAfterSeparator) {
116
+ parts.push(`${separator}${block}`);
117
+ totalBytes += separatorBytes + blockBytes;
118
+ continue;
119
+ }
120
+ truncated = true;
121
+ const suffix = `
122
+
123
+ ... (truncated: project instruction files exceeded ${maxBytes} bytes)`;
124
+ const suffixBytes = Buffer.byteLength(suffix, "utf8");
125
+ let finalBlock = "";
126
+ if (suffixBytes >= remainingAfterSeparator) {
127
+ finalBlock = truncateUtf8ToBytes(suffix, remainingAfterSeparator);
128
+ } else {
129
+ const prefixBudget = remainingAfterSeparator - suffixBytes;
130
+ const prefix = truncateUtf8ToBytes(block, prefixBudget);
131
+ finalBlock = `${prefix}${suffix}`;
132
+ }
133
+ parts.push(`${separator}${finalBlock}`);
134
+ totalBytes += separatorBytes + Buffer.byteLength(finalBlock, "utf8");
135
+ break;
136
+ }
137
+ return { content: parts.join(""), truncated };
138
+ }
139
+
140
+ export {
141
+ findGitRoot,
142
+ getDirsFromGitRootToCwd,
143
+ getProjectInstructionFiles,
144
+ readAndConcatProjectInstructionFiles
145
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/utils/config/projectInstructions.ts"],
4
+ "sourcesContent": ["import { existsSync, readFileSync } from 'fs'\nimport { dirname, join, parse, relative, resolve, sep } from 'path'\n\nexport type ProjectInstructionFile = {\n absolutePath: string\n relativePathFromGitRoot: string\n filename: 'AGENTS.override.md' | 'AGENTS.md'\n}\n\nconst DEFAULT_PROJECT_DOC_MAX_BYTES = 32 * 1024\n\nfunction isRegularFile(path: string): boolean {\n try {\n return existsSync(path)\n } catch {\n return false\n }\n}\n\nexport function findGitRoot(startDir: string): string | null {\n let currentDir = resolve(startDir)\n const fsRoot = parse(currentDir).root\n\n while (true) {\n const dotGitPath = join(currentDir, '.git')\n if (existsSync(dotGitPath)) {\n return currentDir\n }\n if (currentDir === fsRoot) {\n return null\n }\n currentDir = dirname(currentDir)\n }\n}\n\nexport function getDirsFromGitRootToCwd(gitRoot: string, cwd: string): string[] {\n const absoluteGitRoot = resolve(gitRoot)\n const absoluteCwd = resolve(cwd)\n\n const rel = relative(absoluteGitRoot, absoluteCwd)\n if (!rel || rel === '.') {\n return [absoluteGitRoot]\n }\n\n const parts = rel.split(sep).filter(Boolean)\n const dirs: string[] = [absoluteGitRoot]\n for (let i = 0; i < parts.length; i++) {\n dirs.push(join(absoluteGitRoot, ...parts.slice(0, i + 1)))\n }\n return dirs\n}\n\nexport function getProjectInstructionFiles(\n cwd: string,\n): ProjectInstructionFile[] {\n const gitRoot = findGitRoot(cwd)\n const root = gitRoot ?? resolve(cwd)\n const dirs = getDirsFromGitRootToCwd(root, cwd)\n\n const results: ProjectInstructionFile[] = []\n for (const dir of dirs) {\n const overridePath = join(dir, 'AGENTS.override.md')\n const agentsPath = join(dir, 'AGENTS.md')\n\n if (isRegularFile(overridePath)) {\n results.push({\n absolutePath: overridePath,\n relativePathFromGitRoot:\n relative(root, overridePath) || 'AGENTS.override.md',\n filename: 'AGENTS.override.md',\n })\n continue\n }\n\n if (isRegularFile(agentsPath)) {\n results.push({\n absolutePath: agentsPath,\n relativePathFromGitRoot: relative(root, agentsPath) || 'AGENTS.md',\n filename: 'AGENTS.md',\n })\n }\n }\n\n return results\n}\n\nexport function getProjectDocMaxBytes(): number {\n const raw = process.env.PYB_PROJECT_DOC_MAX_BYTES\n if (!raw) return DEFAULT_PROJECT_DOC_MAX_BYTES\n const parsed = Number.parseInt(raw, 10)\n if (!Number.isFinite(parsed) || parsed <= 0)\n return DEFAULT_PROJECT_DOC_MAX_BYTES\n return parsed\n}\n\nexport function readAndConcatProjectInstructionFiles(\n files: ProjectInstructionFile[],\n {\n maxBytes = getProjectDocMaxBytes(),\n includeHeadings = true,\n }: { maxBytes?: number; includeHeadings?: boolean } = {},\n): { content: string; truncated: boolean } {\n let totalBytes = 0\n let truncated = false\n\n const parts: string[] = []\n\n const truncateUtf8ToBytes = (value: string, bytes: number): string => {\n const buf = Buffer.from(value, 'utf8')\n if (buf.length <= bytes) return value\n return buf.subarray(0, Math.max(0, bytes)).toString('utf8')\n }\n\n for (const file of files) {\n if (totalBytes >= maxBytes) {\n truncated = true\n break\n }\n\n let raw: string\n try {\n raw = readFileSync(file.absolutePath, 'utf-8')\n } catch {\n continue\n }\n\n if (!raw.trim()) continue\n\n const separator = parts.length > 0 ? '\\n\\n' : ''\n const separatorBytes = Buffer.byteLength(separator, 'utf8')\n const remainingAfterSeparator = maxBytes - totalBytes - separatorBytes\n if (remainingAfterSeparator <= 0) {\n truncated = true\n break\n }\n\n const heading = includeHeadings\n ? `# ${file.filename}\\n\\n_Path: ${file.relativePathFromGitRoot}_\\n\\n`\n : ''\n\n const block = `${heading}${raw}`.trimEnd()\n const blockBytes = Buffer.byteLength(block, 'utf8')\n\n if (blockBytes <= remainingAfterSeparator) {\n parts.push(`${separator}${block}`)\n totalBytes += separatorBytes + blockBytes\n continue\n }\n\n truncated = true\n const suffix = `\\n\\n... (truncated: project instruction files exceeded ${maxBytes} bytes)`\n const suffixBytes = Buffer.byteLength(suffix, 'utf8')\n\n let finalBlock = ''\n if (suffixBytes >= remainingAfterSeparator) {\n finalBlock = truncateUtf8ToBytes(suffix, remainingAfterSeparator)\n } else {\n const prefixBudget = remainingAfterSeparator - suffixBytes\n const prefix = truncateUtf8ToBytes(block, prefixBudget)\n finalBlock = `${prefix}${suffix}`\n }\n\n parts.push(`${separator}${finalBlock}`)\n totalBytes += separatorBytes + Buffer.byteLength(finalBlock, 'utf8')\n break\n }\n\n return { content: parts.join(''), truncated }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -4,7 +4,7 @@ import {
4
4
  BunShell,
5
5
  execFileNoThrow,
6
6
  logError
7
- } from "./chunk-LBDLSBXN.js";
7
+ } from "./chunk-WLEPTDKU.js";
8
8
 
9
9
  // src/utils/system/ripgrep.ts
10
10
  import { findActualExecutable } from "spawn-rx";
@@ -4,7 +4,7 @@ const require = __pybCreateRequire(import.meta.url);
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "pybao-cli",
7
- version: "1.5.23",
7
+ version: "1.5.25",
8
8
  bin: {
9
9
  pyb: "cli.js",
10
10
  "pyb-acp": "cli-acp.js"
@@ -47,6 +47,8 @@ var package_default = {
47
47
  "scripts/typed-part-performance-gate.mjs",
48
48
  "scripts/session-contract-gate.mjs",
49
49
  "scripts/session-behavior-invariant-gate.mjs",
50
+ "scripts/session-project-gate.mjs",
51
+ "scripts/protected-tool-names-gate.mjs",
50
52
  ".npmrc",
51
53
  "resources/**/*"
52
54
  ],
@@ -79,6 +81,8 @@ var package_default = {
79
81
  "gate:query-adapter-boundary": "node scripts/query-adapter-boundary-gate.mjs",
80
82
  "gate:session-contract": "node scripts/session-contract-gate.mjs",
81
83
  "gate:session-behavior-invariant": "node scripts/session-behavior-invariant-gate.mjs",
84
+ "gate:session-project": "node scripts/session-project-gate.mjs",
85
+ "gate:protected-tool-names": "node scripts/protected-tool-names-gate.mjs",
82
86
  "plan:typed-compat-retirement": "node scripts/typed-compat-retirement-plan.mjs",
83
87
  "enforce:typed-compat-retirement": "node scripts/typed-compat-retirement-enforce.mjs",
84
88
  "gate:typed-sql-release": "node scripts/typed-sql-release-gate.mjs",
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../package.json", "../src/constants/macros.ts"],
4
+ "sourcesContent": ["{\n \"name\": \"pybao-cli\",\n \"version\": \"1.5.25\",\n \"bin\": {\n \"pyb\": \"cli.js\",\n \"pyb-acp\": \"cli-acp.js\"\n },\n \"engines\": {\n \"node\": \">=20.18.1\"\n },\n \"main\": \"cli.js\",\n \"author\": \"PYB-XC\",\n \"license\": \"MIT\",\n \"description\": \"PYB-CLI - Minimal AI Agent with multi-model support and CLI interface\",\n \"keywords\": [\n \"ai\",\n \"agent\",\n \"minimal\",\n \"claude\"\n ],\n \"homepage\": \"https://github.com/pyb-xc/pyb-ts\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/pyb-xc/pyb-ts.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/pyb-xc/pyb-ts/issues\"\n },\n \"files\": [\n \"cli.js\",\n \"cli-acp.js\",\n \"yoga.wasm\",\n \"dist/**/*\",\n \"scripts/binary-utils.cjs\",\n \"scripts/cli-wrapper.cjs\",\n \"scripts/cli-acp-wrapper.cjs\",\n \"scripts/postinstall.js\",\n \"scripts/typed-sql-release-gate.mjs\",\n \"scripts/typed-sql-schema-guard.mjs\",\n \"scripts/typed-sql-install-smoke.mjs\",\n \"scripts/typed-sql-no-fallback-gate.mjs\",\n \"scripts/typed-part-baseline-benchmark.mjs\",\n \"scripts/typed-part-performance-gate.mjs\",\n \"scripts/session-contract-gate.mjs\",\n \"scripts/session-behavior-invariant-gate.mjs\",\n \"scripts/session-project-gate.mjs\",\n \"scripts/protected-tool-names-gate.mjs\",\n \".npmrc\",\n \"resources/**/*\"\n ],\n \"scripts\": {\n \"dev\": \"bun run ./src/entrypoints/cli.tsx --verbose\",\n \"build:npm\": \"bun scripts/build.mjs\",\n \"build\": \"npm run build:npm\",\n \"build:binary\": \"node scripts/build-binary.mjs\",\n \"build:native-lock\": \"node scripts/build-native-lock.mjs\",\n \"clean\": \"node scripts/clean.mjs\",\n \"prepublishOnly\": \"npm run build:npm && node scripts/prepublish-check.js\",\n \"postinstall\": \"node scripts/postinstall.js || true\",\n \"format\": \"prettier --write \\\"src/**/*.{ts,tsx,js,jsx,json}\\\" \\\"tests/**/*.{ts,tsx,js,jsx,json}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{ts,tsx,js,jsx,json}\\\" \\\"tests/**/*.{ts,tsx,js,jsx,json}\\\"\",\n \"lint\": \"eslint . --ext .ts,.tsx,.js --max-warnings 0\",\n \"lint:fix\": \"eslint . --ext .ts,.tsx,.js --fix\",\n \"test\": \"bun test\",\n \"test:unit\": \"bun test --preload ./tests/setup/native-lock-test-setup.ts tests/unit\",\n \"test:integration\": \"bun test tests/integration\",\n \"test:e2e\": \"bun test tests/e2e\",\n \"gate:runtime-assets\": \"bun run scripts/runtime-assets-gate-check.mjs\",\n \"preflight:runtime-assets\": \"node scripts/runtime-assets-preflight.mjs\",\n \"verify:runtime-assets\": \"node scripts/runtime-assets-verify.mjs\",\n \"validate:runtime-assets-contract\": \"node scripts/runtime-assets-schema-validate.mjs\",\n \"gate:runtime-assets-threshold\": \"node scripts/runtime-assets-threshold-gate.mjs\",\n \"gate:runtime-assets-trend-store\": \"node scripts/runtime-assets-trend-store.mjs\",\n \"gate:runtime-assets-trend\": \"node scripts/runtime-assets-trend-gate.mjs\",\n \"report:runtime-assets-trend\": \"node scripts/runtime-assets-trend-report.mjs\",\n \"gate:typed-compat-retirement\": \"node scripts/typed-compat-retirement-gate.mjs\",\n \"gate:query-adapter-boundary\": \"node scripts/query-adapter-boundary-gate.mjs\",\n \"gate:session-contract\": \"node scripts/session-contract-gate.mjs\",\n \"gate:session-behavior-invariant\": \"node scripts/session-behavior-invariant-gate.mjs\",\n \"gate:session-project\": \"node scripts/session-project-gate.mjs\",\n \"gate:protected-tool-names\": \"node scripts/protected-tool-names-gate.mjs\",\n \"plan:typed-compat-retirement\": \"node scripts/typed-compat-retirement-plan.mjs\",\n \"enforce:typed-compat-retirement\": \"node scripts/typed-compat-retirement-enforce.mjs\",\n \"gate:typed-sql-release\": \"node scripts/typed-sql-release-gate.mjs\",\n \"gate:typed-sql-schema\": \"node scripts/typed-sql-schema-guard.mjs\",\n \"smoke:typed-sql-install\": \"node scripts/typed-sql-install-smoke.mjs\",\n \"gate:typed-sql-no-fallback\": \"node scripts/typed-sql-no-fallback-gate.mjs\",\n \"benchmark:typed-part-baseline\": \"bun scripts/typed-part-baseline-benchmark.mjs\",\n \"gate:typed-part-performance\": \"node scripts/typed-part-performance-gate.mjs\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepare\": \"bun run scripts/install-hooks.mjs\",\n \"sync:native-lock\": \"node scripts/sync-native-lock-versions.mjs\",\n \"publish:native-lock\": \"node scripts/publish-native-lock.mjs\",\n \"verify:native-lock\": \"node scripts/verify-native-lock.mjs\",\n \"publish:dev\": \"bun run scripts/publish-dev.js\",\n \"publish:release\": \"bun run scripts/publish-release.js\"\n },\n \"dependencies\": {\n \"@anthropic-ai/bedrock-sdk\": \"^0.12.6\",\n \"@anthropic-ai/sdk\": \"^0.39.0\",\n \"@anthropic-ai/vertex-sdk\": \"^0.7.0\",\n \"@astrojs/language-server\": \"2.16.2\",\n \"@aws-sdk/client-bedrock-runtime\": \"3.797.0\",\n \"@commander-js/extra-typings\": \"^13.1.0\",\n \"@inkjs/ui\": \"^2.0.0\",\n \"@modelcontextprotocol/sdk\": \"^1.15.1\",\n \"@prisma/language-server\": \"31.3.4\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/react\": \"^19.1.8\",\n \"@vscode/ripgrep\": \"^1.17.0\",\n \"@vue/language-server\": \"3.2.2\",\n \"ajv\": \"^8.17.1\",\n \"ansi-escapes\": \"^7.0.0\",\n \"bash-language-server\": \"5.6.0\",\n \"chalk\": \"^5.4.1\",\n \"cli-highlight\": \"^2.1.11\",\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^13.1.0\",\n \"debug\": \"^4.4.1\",\n \"diff\": \"^7.0.0\",\n \"dockerfile-language-server-nodejs\": \"0.15.0\",\n \"dotenv\": \"^16.6.1\",\n \"env-paths\": \"^3.0.0\",\n \"fflate\": \"^0.8.2\",\n \"figures\": \"^6.1.0\",\n \"glob\": \"^11.0.3\",\n \"graphql-language-service-cli\": \"3.5.0\",\n \"gray-matter\": \"^4.0.3\",\n \"highlight.js\": \"^11.11.1\",\n \"ignore\": \"^7.0.5\",\n \"ink\": \"5.2.1\",\n \"ink-link\": \"^4.1.0\",\n \"ink-select-input\": \"^6.2.0\",\n \"ink-text-input\": \"^6.0.0\",\n \"intelephense\": \"1.16.3\",\n \"js-yaml\": \"^4.1.1\",\n \"lodash-es\": \"^4.17.21\",\n \"lru-cache\": \"^11.1.0\",\n \"marked\": \"^15.0.12\",\n \"minimatch\": \"^10.1.1\",\n \"nanoid\": \"^5.1.5\",\n \"node-html-parser\": \"^7.0.1\",\n \"openai\": \"4.104.0\",\n \"pyright\": \"1.1.408\",\n \"react\": \"18.3.1\",\n \"semver\": \"^7.7.2\",\n \"shell-quote\": \"1.8.3\",\n \"spawn-rx\": \"^5.1.2\",\n \"string-width\": \"^7.2.0\",\n \"strip-ansi\": \"^7.1.0\",\n \"svelte-language-server\": \"0.17.23\",\n \"tsx\": \"^4.20.3\",\n \"typescript-language-server\": \"5.1.3\",\n \"undici\": \"^7.11.0\",\n \"vscode-jsonrpc\": \"8.2.1\",\n \"vscode-langservers-extracted\": \"4.10.0\",\n \"web-tree-sitter\": \"0.25.10\",\n \"which\": \"^6.0.0\",\n \"wrap-ansi\": \"^9.0.0\",\n \"yaml-language-server\": \"1.19.2\",\n \"zod\": \"^3.25.76\",\n \"zod-to-json-schema\": \"^3.24.6\"\n },\n \"devDependencies\": {\n \"@types/bun\": \"latest\",\n \"@types/jest\": \"^30.0.0\",\n \"@types/node\": \"^24.1.0\",\n \"@types/which\": \"^3.0.4\",\n \"@typescript-eslint/eslint-plugin\": \"^8.50.1\",\n \"@typescript-eslint/parser\": \"^8.50.1\",\n \"abort-controller\": \"3.0.0\",\n \"bun-types\": \"latest\",\n \"cheerio\": \"1.1.2\",\n \"esbuild\": \"^0.25.9\",\n \"eslint\": \"8.57.0\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"ink-testing-library\": \"4.0.0\",\n \"node-fetch\": \"3.3.2\",\n \"prettier\": \"^3.6.2\",\n \"react-devtools-core\": \"^7.0.1\",\n \"tree-sitter-bash\": \"0.25.1\",\n \"tree-sitter-c-sharp\": \"0.23.1\",\n \"tree-sitter-clojure\": \"0.4.0\",\n \"tree-sitter-cpp\": \"0.23.4\",\n \"tree-sitter-go\": \"0.25.0\",\n \"tree-sitter-haskell\": \"0.23.1\",\n \"tree-sitter-java\": \"0.23.5\",\n \"tree-sitter-julia\": \"0.23.1\",\n \"tree-sitter-nix\": \"0.0.2\",\n \"tree-sitter-ocaml\": \"0.24.2\",\n \"tree-sitter-python\": \"0.25.0\",\n \"tree-sitter-rust\": \"0.24.0\",\n \"tree-sitter-scala\": \"0.24.0\",\n \"tree-sitter-swift\": \"0.7.1\",\n \"tree-sitter-typescript\": \"0.23.2\",\n \"turndown\": \"7.2.2\",\n \"typescript\": \"^5.9.2\"\n },\n \"overrides\": {\n \"@aws-sdk/client-bedrock-runtime\": \"3.797.0\",\n \"@smithy/smithy-client\": \"2.5.1\",\n \"parse5-htmlparser2-tree-adapter\": \"6.0.1\"\n },\n \"optionalDependencies\": {\n \"@puyib-cli/lock-win32-x64-msvc\": \"1.4.55\",\n \"@puyib-cli/lock-win32-arm64-msvc\": \"1.4.56\",\n \"@puyib-cli/lock-linux-x64-gnu\": \"1.4.56\",\n \"@puyib-cli/lock-linux-x64-musl\": \"1.4.56\",\n \"@puyib-cli/lock-linux-arm64-gnu\": \"1.4.56\",\n \"@puyib-cli/lock-linux-armv7-gnueabihf\": \"1.4.56\",\n \"@puyib-cli/lock-darwin-x64\": \"1.4.56\",\n \"@puyib-cli/lock-darwin-arm64\": \"1.4.56\"\n },\n \"pybNativeLockPlatforms\": [\n \"win32-x64-msvc\",\n \"win32-arm64-msvc\",\n \"linux-x64-gnu\",\n \"linux-x64-musl\",\n \"linux-arm64-gnu\",\n \"linux-armv7-gnueabihf\",\n \"darwin-x64\",\n \"darwin-arm64\"\n ]\n}\n", "import pkg from '../../package.json'\n\nexport const MACRO = {\n VERSION: pkg.version,\n README_URL: 'https://github.com/pyb-xc/pyb-ts#readme',\n PACKAGE_URL: 'pybao-cli',\n ISSUES_EXPLAINER:\n 'report the issue at https://github.com/pyb-xc/pyb-ts/issues',\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -5,13 +5,13 @@ import {
5
5
  } from "./chunk-RQVLBMP7.js";
6
6
  import {
7
7
  debug
8
- } from "./chunk-5B7UCAYL.js";
8
+ } from "./chunk-3RKGBZUV.js";
9
9
  import {
10
10
  getCwd,
11
11
  getGlobalConfigFilePath,
12
12
  getLegacyGlobalConfigFilePath,
13
13
  logError
14
- } from "./chunk-LBDLSBXN.js";
14
+ } from "./chunk-WLEPTDKU.js";
15
15
 
16
16
  // src/core/config/schema.ts
17
17
  function isAutoUpdaterStatus(value) {
@@ -688,7 +688,7 @@ function setModelPointer(pointer, modelName) {
688
688
  }
689
689
  };
690
690
  saveGlobalConfig(updatedConfig);
691
- import("./model-QSDSUJDB.js").then(({ reloadModelManager }) => {
691
+ import("./model-R7YMMBAR.js").then(({ reloadModelManager }) => {
692
692
  reloadModelManager();
693
693
  });
694
694
  }
@@ -3,7 +3,7 @@ const require = __pybCreateRequire(import.meta.url);
3
3
 
4
4
  // src/services/ai/llmLazy.ts
5
5
  async function queryLLM(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
6
- const { queryLLM: inner } = await import("./llm-TOU5REY5.js");
6
+ const { queryLLM: inner } = await import("./llm-KOMOHPJY.js");
7
7
  return inner(
8
8
  messages,
9
9
  systemPrompt,
@@ -14,15 +14,15 @@ async function queryLLM(messages, systemPrompt, maxThinkingTokens, tools, signal
14
14
  );
15
15
  }
16
16
  async function queryQuick(args) {
17
- const { queryQuick: inner } = await import("./llm-TOU5REY5.js");
17
+ const { queryQuick: inner } = await import("./llm-KOMOHPJY.js");
18
18
  return inner(args);
19
19
  }
20
20
  async function verifyApiKey(apiKey, baseURL, provider) {
21
- const { verifyApiKey: inner } = await import("./llm-TOU5REY5.js");
21
+ const { verifyApiKey: inner } = await import("./llm-KOMOHPJY.js");
22
22
  return inner(apiKey, baseURL, provider);
23
23
  }
24
24
  async function fetchAnthropicModels(apiKey, baseURL) {
25
- const { fetchAnthropicModels: inner } = await import("./llm-TOU5REY5.js");
25
+ const { fetchAnthropicModels: inner } = await import("./llm-KOMOHPJY.js");
26
26
  return inner(apiKey, baseURL);
27
27
  }
28
28
 
@@ -6,12 +6,12 @@ import {
6
6
  } from "./chunk-XKYHFZEC.js";
7
7
  import {
8
8
  getGlobalConfig
9
- } from "./chunk-V22PQM4W.js";
9
+ } from "./chunk-LGQJPZKC.js";
10
10
  import {
11
11
  debug,
12
12
  getCurrentRequest,
13
13
  logAPIError
14
- } from "./chunk-5B7UCAYL.js";
14
+ } from "./chunk-3RKGBZUV.js";
15
15
 
16
16
  // src/services/ai/openai.ts
17
17
  import { ProxyAgent, fetch } from "undici";
@@ -2,7 +2,7 @@ import { createRequire as __pybCreateRequire } from "node:module";
2
2
  const require = __pybCreateRequire(import.meta.url);
3
3
  import {
4
4
  getGlobalConfig
5
- } from "./chunk-V22PQM4W.js";
5
+ } from "./chunk-LGQJPZKC.js";
6
6
 
7
7
  // src/utils/theme/index.ts
8
8
  var lightTheme = {
@@ -1,8 +1,11 @@
1
1
  import { createRequire as __pybCreateRequire } from "node:module";
2
2
  const require = __pybCreateRequire(import.meta.url);
3
+ import {
4
+ findGitRoot
5
+ } from "./chunk-KFEHHKZ2.js";
3
6
  import {
4
7
  resolveXdgDataPath
5
- } from "./chunk-LBDLSBXN.js";
8
+ } from "./chunk-WLEPTDKU.js";
6
9
 
7
10
  // src/utils/session/sessionSqlStore.ts
8
11
  import { createRequire } from "node:module";
@@ -25,11 +28,7 @@ function getSessionStoreFlags() {
25
28
  process.env.PYB_SESSION_STORE_SQL_WRITE,
26
29
  true
27
30
  ),
28
- sqlReadEnabled: parseBooleanFlag(process.env.PYB_SESSION_STORE_SQL_READ, true),
29
- jsonlWriteEnabled: parseBooleanFlag(
30
- process.env.PYB_SESSION_STORE_JSONL_WRITE,
31
- false
32
- )
31
+ sqlReadEnabled: parseBooleanFlag(process.env.PYB_SESSION_STORE_SQL_READ, true)
33
32
  };
34
33
  return cachedFlags;
35
34
  }
@@ -40,7 +39,7 @@ function getSessionStoreDbPath() {
40
39
  }
41
40
 
42
41
  // src/utils/session/sessionStoreSchema.ts
43
- var SESSION_STORE_SCHEMA_VERSION = 1;
42
+ var SESSION_STORE_SCHEMA_VERSION = 2;
44
43
  function applyRuntimePragmas(db) {
45
44
  db.exec(`PRAGMA journal_mode=WAL;`);
46
45
  db.exec(`PRAGMA synchronous=NORMAL;`);
@@ -56,9 +55,25 @@ function ensureSessionStoreSchema(db) {
56
55
  updated_at INTEGER NOT NULL
57
56
  );
58
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
+ `);
59
73
  db.exec(`
60
74
  CREATE TABLE IF NOT EXISTS session (
61
75
  id TEXT PRIMARY KEY,
76
+ project_id TEXT,
62
77
  cwd TEXT,
63
78
  slug TEXT,
64
79
  git_branch TEXT,
@@ -67,6 +82,10 @@ function ensureSessionStoreSchema(db) {
67
82
  updated_at INTEGER NOT NULL
68
83
  );
69
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
+ }
70
89
  db.exec(`
71
90
  CREATE TABLE IF NOT EXISTS message (
72
91
  uuid TEXT PRIMARY KEY,
@@ -143,6 +162,10 @@ function ensureSessionStoreSchema(db) {
143
162
  CREATE INDEX IF NOT EXISTS idx_meta_event_session_time
144
163
  ON session_meta_event(session_id, time_created);
145
164
  `);
165
+ db.exec(`
166
+ CREATE INDEX IF NOT EXISTS idx_session_project_updated
167
+ ON session(project_id, updated_at, id);
168
+ `);
146
169
  const now = Date.now();
147
170
  db.prepare(
148
171
  `
@@ -155,6 +178,75 @@ function ensureSessionStoreSchema(db) {
155
178
  ).run("session_store", SESSION_STORE_SCHEMA_VERSION, now);
156
179
  }
157
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
+
158
250
  // src/utils/session/sessionSqlStore.ts
159
251
  var requireForSqlite = createRequire(import.meta.url);
160
252
  var cachedDatabaseCtor;
@@ -187,6 +279,10 @@ function asNullableText(value) {
187
279
  function asRole(value) {
188
280
  return value === "assistant" || value === "progress" ? value : "user";
189
281
  }
282
+ function asProjectCwd(value) {
283
+ const text = String(value ?? "").trim();
284
+ return text ? text : null;
285
+ }
190
286
  function createSessionSqlStore(options) {
191
287
  const dbFilePath = options?.dbFilePath ?? getSessionStoreDbPath();
192
288
  if (!existsSync(dirname(dbFilePath))) {
@@ -195,10 +291,22 @@ function createSessionSqlStore(options) {
195
291
  const Database = getDatabaseCtorOrThrow();
196
292
  const db = new Database(dbFilePath, { create: true });
197
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
+ `);
198
304
  const upsertSession = db.prepare(`
199
- INSERT INTO session (id, created_at, updated_at)
200
- VALUES (?1, ?2, ?3)
305
+ INSERT INTO session (id, project_id, cwd, created_at, updated_at)
306
+ VALUES (?1, ?2, ?3, ?4, ?5)
201
307
  ON CONFLICT(id) DO UPDATE SET
308
+ project_id = COALESCE(excluded.project_id, session.project_id),
309
+ cwd = COALESCE(excluded.cwd, session.cwd),
202
310
  updated_at = excluded.updated_at
203
311
  `);
204
312
  const upsertMessage = db.prepare(`
@@ -270,6 +378,26 @@ function createSessionSqlStore(options) {
270
378
  time_created = excluded.time_created,
271
379
  updated_at = excluded.updated_at
272
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
+ };
273
401
  const appendMessages = (messages) => {
274
402
  if (!Array.isArray(messages) || messages.length === 0) return 0;
275
403
  const now = Date.now();
@@ -279,7 +407,9 @@ function createSessionSqlStore(options) {
279
407
  const uuid = String(item.uuid ?? "").trim();
280
408
  if (!sessionId || !uuid) continue;
281
409
  const timeCreated = Number(item.timeCreated) || now;
282
- upsertSession.run(sessionId, timeCreated, now);
410
+ const projectCwd = asProjectCwd(item.projectCwd);
411
+ const projectId = resolveProjectId(projectCwd, timeCreated, now);
412
+ upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
283
413
  upsertMessage.run(
284
414
  uuid,
285
415
  sessionId,
@@ -308,7 +438,9 @@ function createSessionSqlStore(options) {
308
438
  const sessionId = String(item.sessionId ?? "").trim();
309
439
  if (!id || !messageUuid || !sessionId) continue;
310
440
  const timeCreated = Number(item.timeCreated) || now;
311
- upsertSession.run(sessionId, timeCreated, now);
441
+ const projectCwd = asProjectCwd(item.projectCwd);
442
+ const projectId = resolveProjectId(projectCwd, timeCreated, now);
443
+ upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
312
444
  upsertPart.run(
313
445
  id,
314
446
  messageUuid,
@@ -333,7 +465,9 @@ function createSessionSqlStore(options) {
333
465
  const sessionId = String(item.sessionId ?? "").trim();
334
466
  if (!id || !sessionId) continue;
335
467
  const timeCreated = Number(item.timeCreated) || now;
336
- upsertSession.run(sessionId, timeCreated, now);
468
+ const projectCwd = asProjectCwd(item.projectCwd);
469
+ const projectId = resolveProjectId(projectCwd, timeCreated, now);
470
+ upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
337
471
  upsertSummary.run(
338
472
  id,
339
473
  sessionId,
@@ -356,7 +490,9 @@ function createSessionSqlStore(options) {
356
490
  const sessionId = String(item.sessionId ?? "").trim();
357
491
  if (!id || !sessionId) continue;
358
492
  const timeCreated = Number(item.timeCreated) || now;
359
- upsertSession.run(sessionId, timeCreated, now);
493
+ const projectCwd = asProjectCwd(item.projectCwd);
494
+ const projectId = resolveProjectId(projectCwd, timeCreated, now);
495
+ upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
360
496
  upsertMetaEvent.run(
361
497
  id,
362
498
  sessionId,
@@ -379,7 +515,9 @@ function createSessionSqlStore(options) {
379
515
  const sessionId = String(item.sessionId ?? "").trim();
380
516
  if (!id || !sessionId) continue;
381
517
  const timeCreated = Number(item.timeCreated) || now;
382
- upsertSession.run(sessionId, timeCreated, now);
518
+ const projectCwd = asProjectCwd(item.projectCwd);
519
+ const projectId = resolveProjectId(projectCwd, timeCreated, now);
520
+ upsertSession.run(sessionId, projectId, projectCwd, timeCreated, now);
383
521
  upsertFileHistorySnapshot.run(
384
522
  id,
385
523
  sessionId,
@@ -479,7 +617,33 @@ function createSessionSqlStore(options) {
479
617
  timeCreated: Number(row.time_created) || 0
480
618
  }));
481
619
  };
482
- const findLatestSessionId = () => {
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
+ }
483
647
  const row = db.prepare(
484
648
  `
485
649
  SELECT session_id
@@ -511,5 +675,7 @@ function createSessionSqlStore(options) {
511
675
  export {
512
676
  getSessionStoreFlags,
513
677
  getSessionStoreDbPath,
678
+ recordSessionSqlDualWriteSuccess,
679
+ recordSessionSqlDualWriteFailure,
514
680
  createSessionSqlStore
515
681
  };