pybao-cli 1.5.7 → 1.5.9
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-FDBOFOZN.js +50 -0
- package/dist/{acp-2LMTSBAU.js → acp-TKO6ZSSV.js} +54 -36
- package/dist/acp-TKO6ZSSV.js.map +7 -0
- package/dist/{agentsValidate-YQSHYCYC.js → agentsValidate-RDNLI7GA.js} +7 -7
- package/dist/{ask-4Z4LH5IS.js → ask-KTXMYPIA.js} +60 -34
- package/dist/ask-KTXMYPIA.js.map +7 -0
- package/dist/{autoUpdater-UTX7ZX2N.js → autoUpdater-53BZ6QWD.js} +3 -3
- package/dist/{chunk-OY6SB5B3.js → chunk-276RV4DQ.js} +4 -4
- package/dist/{chunk-7FFBXWS3.js → chunk-35X2VS4L.js} +3 -3
- package/dist/{chunk-VZDDKAL2.js → chunk-4C2CGHBI.js} +2 -2
- package/dist/{chunk-Y2RSIF7P.js → chunk-4KPVE4K7.js} +1 -1
- package/dist/{chunk-SDKYJZWD.js → chunk-57GJQMFS.js} +2 -2
- package/dist/{chunk-3JH34RBY.js → chunk-6PXEXL7C.js} +2 -2
- package/dist/{chunk-IKMMFSNJ.js → chunk-AMQ6XZOU.js} +1 -1
- package/dist/{chunk-W4PXRGP3.js → chunk-AWRDD6BG.js} +18 -1
- package/dist/chunk-AWRDD6BG.js.map +7 -0
- package/dist/{chunk-5JKCAVMI.js → chunk-BZGQQ4WZ.js} +3 -3
- package/dist/{chunk-4BFEUSKN.js → chunk-CATWZQ3R.js} +2 -2
- package/dist/{chunk-EGJRWKZ6.js → chunk-CPLMSZ63.js} +4 -4
- package/dist/{chunk-PI5RBPFA.js → chunk-DA6NJEFI.js} +2 -2
- package/dist/{chunk-IFC2PLAM.js → chunk-E35YJNX2.js} +4 -4
- package/dist/{chunk-TIMEEE5U.js → chunk-G7DKRXDS.js} +1 -4
- package/dist/{chunk-5F6IQJHF.js → chunk-HIJYNCCN.js} +1 -1
- package/dist/{chunk-F7HYDAWW.js → chunk-JE43CQYI.js} +3 -3
- package/dist/{chunk-JEAXJP2E.js → chunk-JLC2I3EY.js} +1 -1
- package/dist/chunk-JRMAK4PK.js +926 -0
- package/dist/chunk-JRMAK4PK.js.map +7 -0
- package/dist/{chunk-KLD4WAB6.js → chunk-KNLP4UO6.js} +4 -4
- package/dist/chunk-L3R7MPZU.js +81 -0
- package/dist/{chunk-ZD6NMP33.js.map → chunk-L3R7MPZU.js.map} +1 -1
- package/dist/{chunk-PMYMUSB4.js → chunk-LEYWQQ7V.js} +3 -3
- package/dist/{chunk-EN7L7JWN.js → chunk-LIOZM4KE.js} +1 -1
- package/dist/chunk-OC5CZWBQ.js.map +7 -0
- package/dist/{chunk-SWNNPHFY.js → chunk-PH6DPTO3.js} +2025 -1321
- package/dist/chunk-PH6DPTO3.js.map +7 -0
- package/dist/{chunk-CJ2YYIJN.js → chunk-PPFVOBEG.js} +144 -76
- package/dist/chunk-PPFVOBEG.js.map +7 -0
- package/dist/{chunk-4R7NUADF.js → chunk-Q5EZLUFC.js} +1 -1
- package/dist/{chunk-LYMH46VN.js → chunk-QMN64ICT.js} +3 -3
- package/dist/{chunk-VBV5RHIK.js → chunk-R4ZEH3KJ.js} +1 -1
- package/dist/{chunk-TKEWBSVM.js → chunk-SNASBZ2C.js} +3 -3
- package/dist/chunk-T7P3SSAQ.js +78 -0
- package/dist/chunk-T7P3SSAQ.js.map +7 -0
- package/dist/{chunk-T7UTA73F.js → chunk-TLZS274Y.js} +3 -3
- package/dist/{chunk-IOP3VA4X.js → chunk-YSL5H7NJ.js} +2 -2
- package/dist/{chunk-HFVRQO2J.js → chunk-YTEQEQ56.js} +48 -40
- package/dist/chunk-YTEQEQ56.js.map +7 -0
- package/dist/{cli-N3Q4D4BW.js → cli-LYWCNPC6.js} +131 -102
- package/dist/cli-LYWCNPC6.js.map +7 -0
- package/dist/commands-DYXAWJO6.js +54 -0
- package/dist/{config-GZXNPIIG.js → config-66BMMOES.js} +4 -4
- package/dist/{context-TUO5CUR3.js → context-PG7YTQCJ.js} +6 -6
- package/dist/conversationPersistence-DB6IUU2I.js +13 -0
- package/dist/{conversationTracker-APB6PR5Z.js → conversationTracker-WG3J56PX.js} +4 -3
- package/dist/{customCommands-J4DV6OI5.js → customCommands-XDKUVT73.js} +4 -4
- package/dist/{env-YBYEMHYQ.js → env-FW74XJHK.js} +2 -2
- package/dist/{file-KIBY6XZX.js → file-U2NXQ6RC.js} +4 -4
- package/dist/index.js +3 -3
- package/dist/{llm-T7C6QJWB.js → llm-6VJMMPDO.js} +416 -49
- package/dist/llm-6VJMMPDO.js.map +7 -0
- package/dist/{llmLazy-FDVUCPDQ.js → llmLazy-LYGZWC7G.js} +1 -1
- package/dist/{loader-QCHS455W.js → loader-DMZVU2XJ.js} +4 -4
- package/dist/{lsp-TE2SQ6CO.js → lsp-6LNF5DQB.js} +6 -6
- package/dist/{lspAnchor-IZ7YQJ64.js → lspAnchor-SF5Y7ZJT.js} +6 -6
- package/dist/{mcp-PLAWUZOQ.js → mcp-NLDX3RQE.js} +7 -7
- package/dist/{mentionProcessor-2O3AMZHB.js → mentionProcessor-BMX6VGRH.js} +5 -5
- package/dist/{messages-ZHFZ2OOG.js → messages-OTQ6IJM5.js} +9 -5
- package/dist/{model-GBC2PBVJ.js → model-KWGEASLY.js} +5 -5
- package/dist/{openai-2V2J23AE.js → openai-XIRWQY5H.js} +5 -5
- package/dist/{outputStyles-WD4VD4GZ.js → outputStyles-HKYM5C76.js} +4 -4
- package/dist/{pluginRuntime-WNZS26EV.js → pluginRuntime-25Y2MVIN.js} +6 -6
- package/dist/{pluginValidation-YP7MW35I.js → pluginValidation-CIJIQKGB.js} +6 -6
- package/dist/prompts-WH3VEHH6.js +56 -0
- package/dist/{pybAgentSessionLoad-YABCHELS.js → pybAgentSessionLoad-TF3BFX4S.js} +4 -4
- package/dist/{pybAgentSessionResume-C3LNSFQL.js → pybAgentSessionResume-Y5JO4GLH.js} +4 -4
- package/dist/{pybAgentStreamJsonSession-DFOGLEOB.js → pybAgentStreamJsonSession-46VLF4QN.js} +4 -3
- package/dist/pybAgentStreamJsonSession-46VLF4QN.js.map +7 -0
- package/dist/{pybHooks-LGGIB5PJ.js → pybHooks-LZPU4EF6.js} +4 -4
- package/dist/query-4B3GTPBN.js +58 -0
- package/dist/{registry-EYMCKHRG.js → registry-6LUE7ZWC.js} +5 -5
- package/dist/{ripgrep-JZN2MVSK.js → ripgrep-KVB55D22.js} +3 -3
- package/dist/{skillMarketplace-ETYXMAXF.js → skillMarketplace-2IVEPC2E.js} +3 -3
- package/dist/{state-MAVHRDNE.js → state-OGBESWFS.js} +2 -2
- package/dist/{theme-AUEZ6SNA.js → theme-QQ2SCFEK.js} +5 -5
- package/dist/{toolPermissionSettings-7JZYBUZC.js → toolPermissionSettings-ZGGPBK6S.js} +6 -6
- package/dist/tools-UXPFIHD4.js +55 -0
- package/dist/tools-UXPFIHD4.js.map +7 -0
- package/dist/{userInput-V6RU4BEQ.js → userInput-75VCTJDE.js} +76 -49
- package/dist/userInput-75VCTJDE.js.map +7 -0
- package/package.json +18 -1
- package/dist/REPL-YW6AH5YU.js +0 -49
- package/dist/acp-2LMTSBAU.js.map +0 -7
- package/dist/ask-4Z4LH5IS.js.map +0 -7
- package/dist/chunk-CJ2YYIJN.js.map +0 -7
- package/dist/chunk-HFVRQO2J.js.map +0 -7
- package/dist/chunk-O6DTZU7F.js.map +0 -7
- package/dist/chunk-SWNNPHFY.js.map +0 -7
- package/dist/chunk-W4PXRGP3.js.map +0 -7
- package/dist/chunk-YNGGZILT.js +0 -516
- package/dist/chunk-YNGGZILT.js.map +0 -7
- package/dist/chunk-ZD6NMP33.js +0 -240
- package/dist/cli-N3Q4D4BW.js.map +0 -7
- package/dist/commands-OOINF26E.js +0 -53
- package/dist/llm-T7C6QJWB.js.map +0 -7
- package/dist/prompts-QPYUI6SX.js +0 -55
- package/dist/pybAgentStreamJsonSession-DFOGLEOB.js.map +0 -7
- package/dist/query-EC6HGBDS.js +0 -57
- package/dist/tools-3JFVDDSZ.js +0 -54
- package/dist/userInput-V6RU4BEQ.js.map +0 -7
- /package/dist/{REPL-YW6AH5YU.js.map → REPL-FDBOFOZN.js.map} +0 -0
- /package/dist/{agentsValidate-YQSHYCYC.js.map → agentsValidate-RDNLI7GA.js.map} +0 -0
- /package/dist/{autoUpdater-UTX7ZX2N.js.map → autoUpdater-53BZ6QWD.js.map} +0 -0
- /package/dist/{chunk-OY6SB5B3.js.map → chunk-276RV4DQ.js.map} +0 -0
- /package/dist/{chunk-7FFBXWS3.js.map → chunk-35X2VS4L.js.map} +0 -0
- /package/dist/{chunk-VZDDKAL2.js.map → chunk-4C2CGHBI.js.map} +0 -0
- /package/dist/{chunk-Y2RSIF7P.js.map → chunk-4KPVE4K7.js.map} +0 -0
- /package/dist/{chunk-SDKYJZWD.js.map → chunk-57GJQMFS.js.map} +0 -0
- /package/dist/{chunk-3JH34RBY.js.map → chunk-6PXEXL7C.js.map} +0 -0
- /package/dist/{chunk-IKMMFSNJ.js.map → chunk-AMQ6XZOU.js.map} +0 -0
- /package/dist/{chunk-5JKCAVMI.js.map → chunk-BZGQQ4WZ.js.map} +0 -0
- /package/dist/{chunk-4BFEUSKN.js.map → chunk-CATWZQ3R.js.map} +0 -0
- /package/dist/{chunk-EGJRWKZ6.js.map → chunk-CPLMSZ63.js.map} +0 -0
- /package/dist/{chunk-PI5RBPFA.js.map → chunk-DA6NJEFI.js.map} +0 -0
- /package/dist/{chunk-IFC2PLAM.js.map → chunk-E35YJNX2.js.map} +0 -0
- /package/dist/{chunk-TIMEEE5U.js.map → chunk-G7DKRXDS.js.map} +0 -0
- /package/dist/{chunk-5F6IQJHF.js.map → chunk-HIJYNCCN.js.map} +0 -0
- /package/dist/{chunk-F7HYDAWW.js.map → chunk-JE43CQYI.js.map} +0 -0
- /package/dist/{chunk-JEAXJP2E.js.map → chunk-JLC2I3EY.js.map} +0 -0
- /package/dist/{chunk-KLD4WAB6.js.map → chunk-KNLP4UO6.js.map} +0 -0
- /package/dist/{chunk-PMYMUSB4.js.map → chunk-LEYWQQ7V.js.map} +0 -0
- /package/dist/{chunk-EN7L7JWN.js.map → chunk-LIOZM4KE.js.map} +0 -0
- /package/dist/{chunk-O6DTZU7F.js → chunk-OC5CZWBQ.js} +0 -0
- /package/dist/{chunk-4R7NUADF.js.map → chunk-Q5EZLUFC.js.map} +0 -0
- /package/dist/{chunk-LYMH46VN.js.map → chunk-QMN64ICT.js.map} +0 -0
- /package/dist/{chunk-VBV5RHIK.js.map → chunk-R4ZEH3KJ.js.map} +0 -0
- /package/dist/{chunk-TKEWBSVM.js.map → chunk-SNASBZ2C.js.map} +0 -0
- /package/dist/{chunk-T7UTA73F.js.map → chunk-TLZS274Y.js.map} +0 -0
- /package/dist/{chunk-IOP3VA4X.js.map → chunk-YSL5H7NJ.js.map} +0 -0
- /package/dist/{commands-OOINF26E.js.map → commands-DYXAWJO6.js.map} +0 -0
- /package/dist/{config-GZXNPIIG.js.map → config-66BMMOES.js.map} +0 -0
- /package/dist/{context-TUO5CUR3.js.map → context-PG7YTQCJ.js.map} +0 -0
- /package/dist/{conversationTracker-APB6PR5Z.js.map → conversationPersistence-DB6IUU2I.js.map} +0 -0
- /package/dist/{customCommands-J4DV6OI5.js.map → conversationTracker-WG3J56PX.js.map} +0 -0
- /package/dist/{env-YBYEMHYQ.js.map → customCommands-XDKUVT73.js.map} +0 -0
- /package/dist/{file-KIBY6XZX.js.map → env-FW74XJHK.js.map} +0 -0
- /package/dist/{llmLazy-FDVUCPDQ.js.map → file-U2NXQ6RC.js.map} +0 -0
- /package/dist/{loader-QCHS455W.js.map → llmLazy-LYGZWC7G.js.map} +0 -0
- /package/dist/{lsp-TE2SQ6CO.js.map → loader-DMZVU2XJ.js.map} +0 -0
- /package/dist/{mcp-PLAWUZOQ.js.map → lsp-6LNF5DQB.js.map} +0 -0
- /package/dist/{lspAnchor-IZ7YQJ64.js.map → lspAnchor-SF5Y7ZJT.js.map} +0 -0
- /package/dist/{messages-ZHFZ2OOG.js.map → mcp-NLDX3RQE.js.map} +0 -0
- /package/dist/{mentionProcessor-2O3AMZHB.js.map → mentionProcessor-BMX6VGRH.js.map} +0 -0
- /package/dist/{model-GBC2PBVJ.js.map → messages-OTQ6IJM5.js.map} +0 -0
- /package/dist/{openai-2V2J23AE.js.map → model-KWGEASLY.js.map} +0 -0
- /package/dist/{outputStyles-WD4VD4GZ.js.map → openai-XIRWQY5H.js.map} +0 -0
- /package/dist/{pluginValidation-YP7MW35I.js.map → outputStyles-HKYM5C76.js.map} +0 -0
- /package/dist/{pluginRuntime-WNZS26EV.js.map → pluginRuntime-25Y2MVIN.js.map} +0 -0
- /package/dist/{prompts-QPYUI6SX.js.map → pluginValidation-CIJIQKGB.js.map} +0 -0
- /package/dist/{pybAgentSessionLoad-YABCHELS.js.map → prompts-WH3VEHH6.js.map} +0 -0
- /package/dist/{pybAgentSessionResume-C3LNSFQL.js.map → pybAgentSessionLoad-TF3BFX4S.js.map} +0 -0
- /package/dist/{pybHooks-LGGIB5PJ.js.map → pybAgentSessionResume-Y5JO4GLH.js.map} +0 -0
- /package/dist/{query-EC6HGBDS.js.map → pybHooks-LZPU4EF6.js.map} +0 -0
- /package/dist/{registry-EYMCKHRG.js.map → query-4B3GTPBN.js.map} +0 -0
- /package/dist/{ripgrep-JZN2MVSK.js.map → registry-6LUE7ZWC.js.map} +0 -0
- /package/dist/{skillMarketplace-ETYXMAXF.js.map → ripgrep-KVB55D22.js.map} +0 -0
- /package/dist/{state-MAVHRDNE.js.map → skillMarketplace-2IVEPC2E.js.map} +0 -0
- /package/dist/{theme-AUEZ6SNA.js.map → state-OGBESWFS.js.map} +0 -0
- /package/dist/{toolPermissionSettings-7JZYBUZC.js.map → theme-QQ2SCFEK.js.map} +0 -0
- /package/dist/{tools-3JFVDDSZ.js.map → toolPermissionSettings-ZGGPBK6S.js.map} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire as __pybCreateRequire } from "node:module";
|
|
2
2
|
const require = __pybCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
} from "./chunk-
|
|
4
|
+
PERSISTENCE_VERSION
|
|
5
|
+
} from "./chunk-T7P3SSAQ.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/session/conversationMessageState.ts
|
|
8
8
|
function mapFinishReason(rawReason) {
|
|
@@ -43,74 +43,6 @@ function appendFinishState(assistantMessage, state) {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// src/utils/session/conversationPersistence.ts
|
|
47
|
-
import {
|
|
48
|
-
existsSync,
|
|
49
|
-
mkdirSync,
|
|
50
|
-
readFileSync,
|
|
51
|
-
renameSync,
|
|
52
|
-
unlinkSync,
|
|
53
|
-
writeFileSync
|
|
54
|
-
} from "fs";
|
|
55
|
-
import { join } from "path";
|
|
56
|
-
var PERSISTENCE_VERSION = 1;
|
|
57
|
-
function sanitizeSessionId(sessionId) {
|
|
58
|
-
return sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
59
|
-
}
|
|
60
|
-
function isValidPersistedCompletedQuery(value) {
|
|
61
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
62
|
-
const item = value;
|
|
63
|
-
return typeof item.queryId === "string" && typeof item.userMessageUUID === "string" && typeof item.userQuery === "string" && typeof item.summary === "string" && typeof item.completedAt === "number" && (item.finish === "end_turn" || item.finish === "tool_calls" || item.finish === "max_tokens" || item.finish === "pause_turn");
|
|
64
|
-
}
|
|
65
|
-
function isValidPersistedConversationState(value) {
|
|
66
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
67
|
-
const state = value;
|
|
68
|
-
return typeof state.version === "number" && typeof state.sessionId === "string" && Array.isArray(state.completedQueries) && state.completedQueries.every(isValidPersistedCompletedQuery) && typeof state.lastUpdatedAt === "number";
|
|
69
|
-
}
|
|
70
|
-
var FileSystemConversationPersistence = class {
|
|
71
|
-
constructor(baseDir) {
|
|
72
|
-
this.baseDir = baseDir;
|
|
73
|
-
}
|
|
74
|
-
getFilePath(sessionId) {
|
|
75
|
-
return join(this.baseDir, `${sanitizeSessionId(sessionId)}.json`);
|
|
76
|
-
}
|
|
77
|
-
saveSync(sessionId, state) {
|
|
78
|
-
const filePath = this.getFilePath(sessionId);
|
|
79
|
-
const tempPath = `${filePath}.tmp`;
|
|
80
|
-
try {
|
|
81
|
-
mkdirSync(this.baseDir, { recursive: true });
|
|
82
|
-
writeFileSync(tempPath, JSON.stringify(state, null, 2), "utf8");
|
|
83
|
-
renameSync(tempPath, filePath);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
logError(error);
|
|
86
|
-
try {
|
|
87
|
-
if (existsSync(tempPath)) unlinkSync(tempPath);
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
loadSync(sessionId) {
|
|
93
|
-
const filePath = this.getFilePath(sessionId);
|
|
94
|
-
if (!existsSync(filePath)) return null;
|
|
95
|
-
try {
|
|
96
|
-
const raw = readFileSync(filePath, "utf8");
|
|
97
|
-
const parsed = JSON.parse(raw);
|
|
98
|
-
if (!isValidPersistedConversationState(parsed)) return null;
|
|
99
|
-
return parsed;
|
|
100
|
-
} catch {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
clearSync(sessionId) {
|
|
105
|
-
const filePath = this.getFilePath(sessionId);
|
|
106
|
-
try {
|
|
107
|
-
if (existsSync(filePath)) unlinkSync(filePath);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
logError(error);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
46
|
// src/utils/session/conversationTracker.ts
|
|
115
47
|
function extractText(content) {
|
|
116
48
|
if (typeof content === "string") return content.trim();
|
|
@@ -126,9 +58,22 @@ var ConversationTracker = class {
|
|
|
126
58
|
currentQueryId = null;
|
|
127
59
|
persistence;
|
|
128
60
|
sessionId;
|
|
61
|
+
persistenceMode;
|
|
62
|
+
onPersistenceEvent;
|
|
63
|
+
persistenceEventCounts = {
|
|
64
|
+
TRACKER_PERSIST_SKIP: 0,
|
|
65
|
+
TRACKER_PERSIST_FAIL: 0,
|
|
66
|
+
TRACKER_PERSIST_SUCCESS: 0,
|
|
67
|
+
TRACKER_RESTORE_SKIP: 0,
|
|
68
|
+
TRACKER_RESTORE_FAIL: 0,
|
|
69
|
+
TRACKER_RESTORE_SUCCESS: 0,
|
|
70
|
+
TRACKER_RESTORE_INTEGRITY_CHECK: 0
|
|
71
|
+
};
|
|
129
72
|
constructor(options) {
|
|
130
73
|
this.persistence = options?.persistence;
|
|
131
74
|
this.sessionId = options?.sessionId;
|
|
75
|
+
this.persistenceMode = options?.persistenceMode ?? "optional";
|
|
76
|
+
this.onPersistenceEvent = options?.onPersistenceEvent;
|
|
132
77
|
}
|
|
133
78
|
startQuery(queryId, userMessage) {
|
|
134
79
|
if (!queryId) return false;
|
|
@@ -188,8 +133,62 @@ ${lines.join("\n")}`;
|
|
|
188
133
|
if (body.length <= maxTotalChars) return body;
|
|
189
134
|
return truncate(body, maxTotalChars);
|
|
190
135
|
}
|
|
136
|
+
emitPersistenceEvent(type, data) {
|
|
137
|
+
this.persistenceEventCounts[type] = (this.persistenceEventCounts[type] ?? 0) + 1;
|
|
138
|
+
this.onPersistenceEvent?.({
|
|
139
|
+
type,
|
|
140
|
+
mode: this.persistenceMode,
|
|
141
|
+
sessionId: this.sessionId ?? null,
|
|
142
|
+
timestamp: Date.now(),
|
|
143
|
+
reason: data?.reason,
|
|
144
|
+
errorMessage: data?.errorMessage,
|
|
145
|
+
integrity: data?.integrity
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
failWhenPersistenceRequired(message) {
|
|
149
|
+
throw new Error(message);
|
|
150
|
+
}
|
|
151
|
+
resolvePersistenceAvailability(operation) {
|
|
152
|
+
const skipEventType = operation === "persist" ? "TRACKER_PERSIST_SKIP" : "TRACKER_RESTORE_SKIP";
|
|
153
|
+
if (this.persistenceMode === "disabled") {
|
|
154
|
+
this.emitPersistenceEvent(skipEventType, { reason: "mode_disabled" });
|
|
155
|
+
return "skip";
|
|
156
|
+
}
|
|
157
|
+
if (!this.persistence || !this.sessionId) {
|
|
158
|
+
if (this.persistenceMode === "required") {
|
|
159
|
+
const message = `ConversationTracker ${operation} requires persistence and sessionId`;
|
|
160
|
+
this.emitPersistenceEvent(
|
|
161
|
+
operation === "persist" ? "TRACKER_PERSIST_FAIL" : "TRACKER_RESTORE_FAIL",
|
|
162
|
+
{
|
|
163
|
+
reason: "missing_dependency",
|
|
164
|
+
errorMessage: message
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
this.failWhenPersistenceRequired(message);
|
|
168
|
+
}
|
|
169
|
+
this.emitPersistenceEvent(skipEventType, { reason: "missing_dependency" });
|
|
170
|
+
return "skip";
|
|
171
|
+
}
|
|
172
|
+
return "ready";
|
|
173
|
+
}
|
|
174
|
+
getPersistenceEventCounts() {
|
|
175
|
+
return { ...this.persistenceEventCounts };
|
|
176
|
+
}
|
|
177
|
+
createSnapshot() {
|
|
178
|
+
return {
|
|
179
|
+
completedQueries: this.getCompletedQueries().map((item) => ({ ...item })),
|
|
180
|
+
currentQueryId: this.currentQueryId
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
restoreSnapshot(snapshot) {
|
|
184
|
+
this.completedQueries.clear();
|
|
185
|
+
for (const item of snapshot.completedQueries) {
|
|
186
|
+
this.completedQueries.set(item.queryId, { ...item });
|
|
187
|
+
}
|
|
188
|
+
this.currentQueryId = snapshot.currentQueryId;
|
|
189
|
+
}
|
|
191
190
|
persist() {
|
|
192
|
-
if (
|
|
191
|
+
if (this.resolvePersistenceAvailability("persist") !== "ready") return false;
|
|
193
192
|
try {
|
|
194
193
|
const state = {
|
|
195
194
|
version: PERSISTENCE_VERSION,
|
|
@@ -205,20 +204,48 @@ ${lines.join("\n")}`;
|
|
|
205
204
|
lastUpdatedAt: Date.now()
|
|
206
205
|
};
|
|
207
206
|
this.persistence.saveSync(this.sessionId, state);
|
|
207
|
+
this.emitPersistenceEvent("TRACKER_PERSIST_SUCCESS");
|
|
208
208
|
return true;
|
|
209
|
-
} catch {
|
|
209
|
+
} catch (error) {
|
|
210
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
211
|
+
this.emitPersistenceEvent("TRACKER_PERSIST_FAIL", {
|
|
212
|
+
reason: "exception",
|
|
213
|
+
errorMessage: message
|
|
214
|
+
});
|
|
215
|
+
if (this.persistenceMode === "required") {
|
|
216
|
+
this.failWhenPersistenceRequired(`ConversationTracker persist failed: ${message}`);
|
|
217
|
+
}
|
|
210
218
|
return false;
|
|
211
219
|
}
|
|
212
220
|
}
|
|
213
221
|
restore() {
|
|
214
|
-
if (
|
|
222
|
+
if (this.resolvePersistenceAvailability("restore") !== "ready") return false;
|
|
215
223
|
try {
|
|
216
224
|
const state = this.persistence.loadSync(this.sessionId);
|
|
217
|
-
if (!state
|
|
225
|
+
if (!state) {
|
|
226
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_SKIP", {
|
|
227
|
+
reason: "empty_state"
|
|
228
|
+
});
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
if (state.version !== PERSISTENCE_VERSION) {
|
|
232
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_FAIL", {
|
|
233
|
+
reason: "invalid_state"
|
|
234
|
+
});
|
|
235
|
+
if (this.persistenceMode === "required") {
|
|
236
|
+
this.failWhenPersistenceRequired(
|
|
237
|
+
"ConversationTracker restore failed: invalid persistence state"
|
|
238
|
+
);
|
|
239
|
+
}
|
|
218
240
|
return false;
|
|
219
241
|
}
|
|
220
242
|
this.completedQueries.clear();
|
|
221
243
|
const list = Array.isArray(state.completedQueries) ? state.completedQueries : [];
|
|
244
|
+
const seen = /* @__PURE__ */ new Set();
|
|
245
|
+
let dropped = 0;
|
|
246
|
+
let duplicateQueryIdCount = 0;
|
|
247
|
+
let emptyQueryIdCount = 0;
|
|
248
|
+
const duplicateQueryIdSamples = [];
|
|
222
249
|
for (const item of list) {
|
|
223
250
|
const normalized = {
|
|
224
251
|
queryId: String(item.queryId),
|
|
@@ -228,11 +255,53 @@ ${lines.join("\n")}`;
|
|
|
228
255
|
completedAt: Number(item.completedAt ?? Date.now()),
|
|
229
256
|
finish: item.finish
|
|
230
257
|
};
|
|
258
|
+
if (!normalized.queryId) {
|
|
259
|
+
dropped += 1;
|
|
260
|
+
emptyQueryIdCount += 1;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (seen.has(normalized.queryId)) {
|
|
264
|
+
dropped += 1;
|
|
265
|
+
duplicateQueryIdCount += 1;
|
|
266
|
+
if (duplicateQueryIdSamples.length < 5) {
|
|
267
|
+
duplicateQueryIdSamples.push(normalized.queryId);
|
|
268
|
+
}
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
seen.add(normalized.queryId);
|
|
231
272
|
this.completedQueries.set(normalized.queryId, normalized);
|
|
232
273
|
}
|
|
233
274
|
this.currentQueryId = null;
|
|
275
|
+
const integrity = {
|
|
276
|
+
sourceCount: list.length,
|
|
277
|
+
restoredCount: this.completedQueries.size,
|
|
278
|
+
droppedCount: dropped,
|
|
279
|
+
duplicateQueryIdCount,
|
|
280
|
+
emptyQueryIdCount,
|
|
281
|
+
duplicateQueryIdSamples,
|
|
282
|
+
isConsistent: dropped === 0
|
|
283
|
+
};
|
|
284
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_INTEGRITY_CHECK", {
|
|
285
|
+
reason: integrity.isConsistent ? "ok" : "integrity_partial",
|
|
286
|
+
integrity
|
|
287
|
+
});
|
|
288
|
+
if (dropped > 0) {
|
|
289
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_FAIL", {
|
|
290
|
+
reason: "integrity_partial",
|
|
291
|
+
errorMessage: `Dropped ${dropped} invalid or duplicated restored queries`
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_SUCCESS");
|
|
234
295
|
return true;
|
|
235
|
-
} catch {
|
|
296
|
+
} catch (error) {
|
|
297
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
298
|
+
this.emitPersistenceEvent("TRACKER_RESTORE_FAIL", {
|
|
299
|
+
reason: "exception",
|
|
300
|
+
errorMessage: message
|
|
301
|
+
});
|
|
302
|
+
if (this.persistenceMode === "required") {
|
|
303
|
+
this.failWhenPersistenceRequired(`ConversationTracker restore failed: ${message}`);
|
|
304
|
+
}
|
|
236
305
|
return false;
|
|
237
306
|
}
|
|
238
307
|
}
|
|
@@ -254,7 +323,6 @@ export {
|
|
|
254
323
|
isFinishComplete,
|
|
255
324
|
findNaturalUserMessageForParent,
|
|
256
325
|
appendFinishState,
|
|
257
|
-
FileSystemConversationPersistence,
|
|
258
326
|
ConversationTracker,
|
|
259
327
|
conversationTracker,
|
|
260
328
|
getConversationTrackerForContext,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/utils/session/conversationMessageState.ts", "../src/utils/session/conversationTracker.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AssistantMessage, Message, UserMessage } from '@query'\n\nexport type ConversationFinishReason =\n | 'end_turn'\n | 'tool_calls'\n | 'max_tokens'\n | 'pause_turn'\n\nexport function mapFinishReason(rawReason?: string | null): ConversationFinishReason {\n const reason = String(rawReason ?? '')\n .trim()\n .toLowerCase()\n if (!reason) return 'end_turn'\n if (reason === 'tool_use' || reason === 'tool_calls') return 'tool_calls'\n if (reason === 'max_tokens' || reason === 'length') return 'max_tokens'\n if (reason === 'pause_turn') return 'pause_turn'\n if (reason === 'end_turn' || reason === 'stop' || reason === 'stop_sequence') {\n return 'end_turn'\n }\n return 'end_turn'\n}\n\nexport function isFinishComplete(finish: ConversationFinishReason): boolean {\n return finish === 'end_turn'\n}\n\nexport function isToolResultUserMessage(message: UserMessage): boolean {\n if (!Array.isArray(message.message.content)) return false\n return message.message.content.some(\n block => block && typeof block === 'object' && (block as any).type === 'tool_result',\n )\n}\n\nexport function findNaturalUserMessageForParent(\n messages: Message[],\n): UserMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (!msg || msg.type !== 'user') continue\n if (isToolResultUserMessage(msg)) continue\n return msg\n }\n return undefined\n}\n\nexport function appendFinishState(\n assistantMessage: AssistantMessage,\n state: {\n finish: ConversationFinishReason\n parentID: string\n completedAt?: number\n },\n): AssistantMessage {\n return {\n ...assistantMessage,\n finish: state.finish,\n parentID: state.parentID,\n ...(typeof state.completedAt === 'number'\n ? { completedAt: state.completedAt }\n : {}),\n }\n}\n\nexport function isCompactionMessage(message: Message): boolean {\n return (\n message.type === 'assistant' &&\n !!(message as AssistantMessage).compaction &&\n (message as AssistantMessage).compaction?.type === 'compaction'\n )\n}\n\nexport function getCompactedQueryIds(messages: Message[]): string[] {\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (!isCompactionMessage(message)) continue\n const ids = (message as AssistantMessage).compaction?.compactedQueryIds\n if (Array.isArray(ids)) return ids\n }\n return []\n}\n\nexport function getCompactionReplayTarget(\n messages: Message[],\n queryId: string,\n): {\n found: boolean\n queryId: string\n requestId: string | null\n partIds: string[]\n} {\n const normalizedQueryId = String(queryId ?? '').trim()\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (!isCompactionMessage(message)) continue\n const entries = (message as AssistantMessage).compaction?.index?.entries\n if (!Array.isArray(entries)) continue\n const matched = entries.find(\n item => String((item as any)?.queryId ?? '').trim() === normalizedQueryId,\n ) as any\n if (!matched) continue\n return {\n found: true,\n queryId: normalizedQueryId,\n requestId: matched.requestId ? String(matched.requestId).trim() : null,\n partIds: Array.isArray(matched.partIds) ? [...matched.partIds] : [],\n }\n }\n return {\n found: false,\n queryId: normalizedQueryId,\n requestId: null,\n partIds: [],\n }\n}\n", "import type { AssistantMessage, UserMessage } from '@query'\nimport { isToolResultUserMessage } from './conversationMessageState'\nimport {\n type ConversationPersistence,\n type PersistedCompletedQuery,\n type PersistedConversationState,\n PERSISTENCE_VERSION,\n} from './conversationPersistence'\n\nexport type CompletedQuery = {\n queryId: string\n userMessageUUID: string\n userQuery: string\n summary: string\n completedAt: number\n finish: 'end_turn' | 'tool_calls' | 'max_tokens' | 'pause_turn'\n}\n\nexport type ConversationTrackerPersistenceMode =\n | 'required'\n | 'optional'\n | 'disabled'\n\nexport type ConversationTrackerPersistenceEventType =\n | 'TRACKER_PERSIST_SKIP'\n | 'TRACKER_PERSIST_FAIL'\n | 'TRACKER_PERSIST_SUCCESS'\n | 'TRACKER_RESTORE_SKIP'\n | 'TRACKER_RESTORE_FAIL'\n | 'TRACKER_RESTORE_SUCCESS'\n | 'TRACKER_RESTORE_INTEGRITY_CHECK'\n\nexport type ConversationTrackerRestoreIntegrityPayload = {\n sourceCount: number\n restoredCount: number\n droppedCount: number\n duplicateQueryIdCount: number\n emptyQueryIdCount: number\n duplicateQueryIdSamples: string[]\n isConsistent: boolean\n}\n\nexport type ConversationTrackerPersistenceEvent = {\n type: ConversationTrackerPersistenceEventType\n mode: ConversationTrackerPersistenceMode\n sessionId: string | null\n timestamp: number\n reason?: string\n errorMessage?: string\n integrity?: ConversationTrackerRestoreIntegrityPayload\n}\n\nexport type ConversationTrackerSnapshot = {\n completedQueries: CompletedQuery[]\n currentQueryId: string | null\n}\n\ntype SummaryOptions = {\n maxEntries?: number\n maxEntryChars?: number\n maxTotalChars?: number\n}\n\nfunction extractText(content: unknown): string {\n if (typeof content === 'string') return content.trim()\n if (!Array.isArray(content)) return ''\n return content\n .filter(block => block && typeof block === 'object' && (block as any).type === 'text')\n .map(block => String((block as any).text ?? '').trim())\n .filter(Boolean)\n .join('\\n')\n .trim()\n}\n\nfunction truncate(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text\n return `${text.slice(0, Math.max(0, maxChars - 3))}...`\n}\n\nexport class ConversationTracker {\n private completedQueries = new Map<string, CompletedQuery>()\n private currentQueryId: string | null = null\n private readonly persistence?: ConversationPersistence\n private readonly sessionId?: string\n private readonly persistenceMode: ConversationTrackerPersistenceMode\n private readonly onPersistenceEvent?: (\n event: ConversationTrackerPersistenceEvent,\n ) => void\n private readonly persistenceEventCounts: Record<\n ConversationTrackerPersistenceEventType,\n number\n > = {\n TRACKER_PERSIST_SKIP: 0,\n TRACKER_PERSIST_FAIL: 0,\n TRACKER_PERSIST_SUCCESS: 0,\n TRACKER_RESTORE_SKIP: 0,\n TRACKER_RESTORE_FAIL: 0,\n TRACKER_RESTORE_SUCCESS: 0,\n TRACKER_RESTORE_INTEGRITY_CHECK: 0,\n }\n\n constructor(options?: {\n persistence?: ConversationPersistence\n sessionId?: string\n persistenceMode?: ConversationTrackerPersistenceMode\n onPersistenceEvent?: (event: ConversationTrackerPersistenceEvent) => void\n }) {\n this.persistence = options?.persistence\n this.sessionId = options?.sessionId\n this.persistenceMode = options?.persistenceMode ?? 'optional'\n this.onPersistenceEvent = options?.onPersistenceEvent\n }\n\n startQuery(queryId: string, userMessage: UserMessage): boolean {\n if (!queryId) return false\n if (isToolResultUserMessage(userMessage)) return false\n if (this.completedQueries.has(queryId)) return false\n if (this.currentQueryId === queryId) return true\n this.currentQueryId = queryId\n return true\n }\n\n completeQuery(\n queryId: string,\n assistantMessage: AssistantMessage,\n userMessage: UserMessage,\n ): boolean {\n if (!queryId) return false\n if (this.completedQueries.has(queryId)) return false\n if (assistantMessage.finish !== 'end_turn') return false\n if (assistantMessage.parentID !== userMessage.uuid) return false\n\n const userQuery = extractText(userMessage.message.content)\n const summaryRaw = extractText(assistantMessage.message.content)\n const completedAt =\n typeof assistantMessage.completedAt === 'number'\n ? assistantMessage.completedAt\n : Date.now()\n\n this.completedQueries.set(queryId, {\n queryId,\n userMessageUUID: userMessage.uuid,\n userQuery,\n summary: summaryRaw,\n completedAt,\n finish: assistantMessage.finish,\n })\n if (this.currentQueryId === queryId) {\n this.currentQueryId = null\n }\n return true\n }\n\n isQueryCompleted(queryId: string): boolean {\n return this.completedQueries.has(queryId)\n }\n\n getCurrentQueryId(): string | null {\n return this.currentQueryId\n }\n\n getCompletedQueries(): CompletedQuery[] {\n return Array.from(this.completedQueries.values()).sort(\n (a, b) => a.completedAt - b.completedAt,\n )\n }\n\n generateConversationSummary(options?: SummaryOptions): string {\n const maxEntries = options?.maxEntries ?? 10\n const maxEntryChars = options?.maxEntryChars ?? 80\n const maxTotalChars = options?.maxTotalChars ?? 2000\n const completed = this.getCompletedQueries()\n if (completed.length === 0) return ''\n\n const recent = completed.slice(-maxEntries)\n const lines = recent.map(item => {\n const q = truncate(item.userQuery || '(\u7A7A\u95EE\u9898)', maxEntryChars)\n const a = truncate(item.summary || '(\u7A7A\u56DE\u7B54)', maxEntryChars)\n return `- Q: ${q}\\n A: ${a}`\n })\n const body = `## \u5DF2\u5B8C\u6210\u95EE\u9898\u6458\u8981\\n${lines.join('\\n')}`\n if (body.length <= maxTotalChars) return body\n return truncate(body, maxTotalChars)\n }\n\n private emitPersistenceEvent(\n type: ConversationTrackerPersistenceEventType,\n data?: {\n reason?: string\n errorMessage?: string\n integrity?: ConversationTrackerRestoreIntegrityPayload\n },\n ): void {\n this.persistenceEventCounts[type] =\n (this.persistenceEventCounts[type] ?? 0) + 1\n this.onPersistenceEvent?.({\n type,\n mode: this.persistenceMode,\n sessionId: this.sessionId ?? null,\n timestamp: Date.now(),\n reason: data?.reason,\n errorMessage: data?.errorMessage,\n integrity: data?.integrity,\n })\n }\n\n private failWhenPersistenceRequired(message: string): never {\n throw new Error(message)\n }\n\n private resolvePersistenceAvailability(\n operation: 'persist' | 'restore',\n ): 'ready' | 'skip' {\n const skipEventType: ConversationTrackerPersistenceEventType =\n operation === 'persist' ? 'TRACKER_PERSIST_SKIP' : 'TRACKER_RESTORE_SKIP'\n if (this.persistenceMode === 'disabled') {\n this.emitPersistenceEvent(skipEventType, { reason: 'mode_disabled' })\n return 'skip'\n }\n if (!this.persistence || !this.sessionId) {\n if (this.persistenceMode === 'required') {\n const message = `ConversationTracker ${operation} requires persistence and sessionId`\n this.emitPersistenceEvent(\n operation === 'persist' ? 'TRACKER_PERSIST_FAIL' : 'TRACKER_RESTORE_FAIL',\n {\n reason: 'missing_dependency',\n errorMessage: message,\n },\n )\n this.failWhenPersistenceRequired(message)\n }\n this.emitPersistenceEvent(skipEventType, { reason: 'missing_dependency' })\n return 'skip'\n }\n return 'ready'\n }\n\n getPersistenceEventCounts(): Readonly<\n Record<ConversationTrackerPersistenceEventType, number>\n > {\n return { ...this.persistenceEventCounts }\n }\n\n createSnapshot(): ConversationTrackerSnapshot {\n return {\n completedQueries: this.getCompletedQueries().map(item => ({ ...item })),\n currentQueryId: this.currentQueryId,\n }\n }\n\n restoreSnapshot(snapshot: ConversationTrackerSnapshot): void {\n this.completedQueries.clear()\n for (const item of snapshot.completedQueries) {\n this.completedQueries.set(item.queryId, { ...item })\n }\n this.currentQueryId = snapshot.currentQueryId\n }\n\n persist(): boolean {\n if (this.resolvePersistenceAvailability('persist') !== 'ready') return false\n try {\n const state: PersistedConversationState = {\n version: PERSISTENCE_VERSION,\n sessionId: this.sessionId,\n completedQueries: this.getCompletedQueries().map(item => ({\n queryId: item.queryId,\n userMessageUUID: item.userMessageUUID,\n userQuery: item.userQuery,\n summary: item.summary,\n completedAt: item.completedAt,\n finish: item.finish,\n })),\n lastUpdatedAt: Date.now(),\n }\n this.persistence!.saveSync(this.sessionId!, state)\n this.emitPersistenceEvent('TRACKER_PERSIST_SUCCESS')\n return true\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.emitPersistenceEvent('TRACKER_PERSIST_FAIL', {\n reason: 'exception',\n errorMessage: message,\n })\n if (this.persistenceMode === 'required') {\n this.failWhenPersistenceRequired(`ConversationTracker persist failed: ${message}`)\n }\n return false\n }\n }\n\n restore(): boolean {\n if (this.resolvePersistenceAvailability('restore') !== 'ready') return false\n try {\n const state = this.persistence!.loadSync(this.sessionId!)\n if (!state) {\n this.emitPersistenceEvent('TRACKER_RESTORE_SKIP', {\n reason: 'empty_state',\n })\n return false\n }\n if (state.version !== PERSISTENCE_VERSION) {\n this.emitPersistenceEvent('TRACKER_RESTORE_FAIL', {\n reason: 'invalid_state',\n })\n if (this.persistenceMode === 'required') {\n this.failWhenPersistenceRequired(\n 'ConversationTracker restore failed: invalid persistence state',\n )\n }\n return false\n }\n this.completedQueries.clear()\n const list = Array.isArray(state.completedQueries)\n ? state.completedQueries\n : []\n const seen = new Set<string>()\n let dropped = 0\n let duplicateQueryIdCount = 0\n let emptyQueryIdCount = 0\n const duplicateQueryIdSamples: string[] = []\n for (const item of list) {\n const normalized: CompletedQuery = {\n queryId: String(item.queryId),\n userMessageUUID: String(item.userMessageUUID),\n userQuery: String(item.userQuery ?? ''),\n summary: String(item.summary ?? ''),\n completedAt: Number(item.completedAt ?? Date.now()),\n finish: item.finish as PersistedCompletedQuery['finish'],\n }\n if (!normalized.queryId) {\n dropped += 1\n emptyQueryIdCount += 1\n continue\n }\n if (seen.has(normalized.queryId)) {\n dropped += 1\n duplicateQueryIdCount += 1\n if (duplicateQueryIdSamples.length < 5) {\n duplicateQueryIdSamples.push(normalized.queryId)\n }\n continue\n }\n seen.add(normalized.queryId)\n this.completedQueries.set(normalized.queryId, normalized)\n }\n this.currentQueryId = null\n const integrity: ConversationTrackerRestoreIntegrityPayload = {\n sourceCount: list.length,\n restoredCount: this.completedQueries.size,\n droppedCount: dropped,\n duplicateQueryIdCount,\n emptyQueryIdCount,\n duplicateQueryIdSamples,\n isConsistent: dropped === 0,\n }\n this.emitPersistenceEvent('TRACKER_RESTORE_INTEGRITY_CHECK', {\n reason: integrity.isConsistent ? 'ok' : 'integrity_partial',\n integrity,\n })\n if (dropped > 0) {\n this.emitPersistenceEvent('TRACKER_RESTORE_FAIL', {\n reason: 'integrity_partial',\n errorMessage: `Dropped ${dropped} invalid or duplicated restored queries`,\n })\n }\n this.emitPersistenceEvent('TRACKER_RESTORE_SUCCESS')\n return true\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.emitPersistenceEvent('TRACKER_RESTORE_FAIL', {\n reason: 'exception',\n errorMessage: message,\n })\n if (this.persistenceMode === 'required') {\n this.failWhenPersistenceRequired(`ConversationTracker restore failed: ${message}`)\n }\n return false\n }\n }\n\n reset(): void {\n this.completedQueries.clear()\n this.currentQueryId = null\n }\n}\n\nexport const conversationTracker = new ConversationTracker()\n\nexport function getConversationTrackerForContext(context?: {\n conversationTracker?: ConversationTracker\n}): ConversationTracker {\n return context?.conversationTracker ?? new ConversationTracker()\n}\n\nexport function resetConversationTrackerForTests(): void {\n conversationTracker.reset()\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAQO,SAAS,gBAAgB,WAAqD;AACnF,QAAM,SAAS,OAAO,aAAa,EAAE,EAClC,KAAK,EACL,YAAY;AACf,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,WAAW,cAAc,WAAW,aAAc,QAAO;AAC7D,MAAI,WAAW,gBAAgB,WAAW,SAAU,QAAO;AAC3D,MAAI,WAAW,aAAc,QAAO;AACpC,MAAI,WAAW,cAAc,WAAW,UAAU,WAAW,iBAAiB;AAC5E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,QAA2C;AAC1E,SAAO,WAAW;AACpB;AAEO,SAAS,wBAAwB,SAA+B;AACrE,MAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,OAAO,EAAG,QAAO;AACpD,SAAO,QAAQ,QAAQ,QAAQ;AAAA,IAC7B,WAAS,SAAS,OAAO,UAAU,YAAa,MAAc,SAAS;AAAA,EACzE;AACF;AAEO,SAAS,gCACd,UACyB;AACzB,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,CAAC,OAAO,IAAI,SAAS,OAAQ;AACjC,QAAI,wBAAwB,GAAG,EAAG;AAClC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,kBACd,kBACA,OAKkB;AAClB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,MAAM;AAAA,IACd,UAAU,MAAM;AAAA,IAChB,GAAI,OAAO,MAAM,gBAAgB,WAC7B,EAAE,aAAa,MAAM,YAAY,IACjC,CAAC;AAAA,EACP;AACF;;;ACEA,SAAS,YAAY,SAA0B;AAC7C,MAAI,OAAO,YAAY,SAAU,QAAO,QAAQ,KAAK;AACrD,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,SAAO,QACJ,OAAO,WAAS,SAAS,OAAO,UAAU,YAAa,MAAc,SAAS,MAAM,EACpF,IAAI,WAAS,OAAQ,MAAc,QAAQ,EAAE,EAAE,KAAK,CAAC,EACrD,OAAO,OAAO,EACd,KAAK,IAAI,EACT,KAAK;AACV;AAEA,SAAS,SAAS,MAAc,UAA0B;AACxD,MAAI,KAAK,UAAU,SAAU,QAAO;AACpC,SAAO,GAAG,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC;AACpD;AAEO,IAAM,sBAAN,MAA0B;AAAA,EACvB,mBAAmB,oBAAI,IAA4B;AAAA,EACnD,iBAAgC;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA,yBAGb;AAAA,IACF,sBAAsB;AAAA,IACtB,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,sBAAsB;AAAA,IACtB,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,iCAAiC;AAAA,EACnC;AAAA,EAEA,YAAY,SAKT;AACD,SAAK,cAAc,SAAS;AAC5B,SAAK,YAAY,SAAS;AAC1B,SAAK,kBAAkB,SAAS,mBAAmB;AACnD,SAAK,qBAAqB,SAAS;AAAA,EACrC;AAAA,EAEA,WAAW,SAAiB,aAAmC;AAC7D,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI,wBAAwB,WAAW,EAAG,QAAO;AACjD,QAAI,KAAK,iBAAiB,IAAI,OAAO,EAAG,QAAO;AAC/C,QAAI,KAAK,mBAAmB,QAAS,QAAO;AAC5C,SAAK,iBAAiB;AACtB,WAAO;AAAA,EACT;AAAA,EAEA,cACE,SACA,kBACA,aACS;AACT,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI,KAAK,iBAAiB,IAAI,OAAO,EAAG,QAAO;AAC/C,QAAI,iBAAiB,WAAW,WAAY,QAAO;AACnD,QAAI,iBAAiB,aAAa,YAAY,KAAM,QAAO;AAE3D,UAAM,YAAY,YAAY,YAAY,QAAQ,OAAO;AACzD,UAAM,aAAa,YAAY,iBAAiB,QAAQ,OAAO;AAC/D,UAAM,cACJ,OAAO,iBAAiB,gBAAgB,WACpC,iBAAiB,cACjB,KAAK,IAAI;AAEf,SAAK,iBAAiB,IAAI,SAAS;AAAA,MACjC;AAAA,MACA,iBAAiB,YAAY;AAAA,MAC7B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,iBAAiB;AAAA,IAC3B,CAAC;AACD,QAAI,KAAK,mBAAmB,SAAS;AACnC,WAAK,iBAAiB;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,SAA0B;AACzC,WAAO,KAAK,iBAAiB,IAAI,OAAO;AAAA,EAC1C;AAAA,EAEA,oBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,sBAAwC;AACtC,WAAO,MAAM,KAAK,KAAK,iBAAiB,OAAO,CAAC,EAAE;AAAA,MAChD,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,4BAA4B,SAAkC;AAC5D,UAAM,aAAa,SAAS,cAAc;AAC1C,UAAM,gBAAgB,SAAS,iBAAiB;AAChD,UAAM,gBAAgB,SAAS,iBAAiB;AAChD,UAAM,YAAY,KAAK,oBAAoB;AAC3C,QAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,UAAM,SAAS,UAAU,MAAM,CAAC,UAAU;AAC1C,UAAM,QAAQ,OAAO,IAAI,UAAQ;AAC/B,YAAM,IAAI,SAAS,KAAK,aAAa,wBAAS,aAAa;AAC3D,YAAM,IAAI,SAAS,KAAK,WAAW,wBAAS,aAAa;AACzD,aAAO,QAAQ,CAAC;AAAA,OAAU,CAAC;AAAA,IAC7B,CAAC;AACD,UAAM,OAAO;AAAA,EAAe,MAAM,KAAK,IAAI,CAAC;AAC5C,QAAI,KAAK,UAAU,cAAe,QAAO;AACzC,WAAO,SAAS,MAAM,aAAa;AAAA,EACrC;AAAA,EAEQ,qBACN,MACA,MAKM;AACN,SAAK,uBAAuB,IAAI,KAC7B,KAAK,uBAAuB,IAAI,KAAK,KAAK;AAC7C,SAAK,qBAAqB;AAAA,MACxB;AAAA,MACA,MAAM,KAAK;AAAA,MACX,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ,MAAM;AAAA,MACd,cAAc,MAAM;AAAA,MACpB,WAAW,MAAM;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEQ,4BAA4B,SAAwB;AAC1D,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AAAA,EAEQ,+BACN,WACkB;AAClB,UAAM,gBACJ,cAAc,YAAY,yBAAyB;AACrD,QAAI,KAAK,oBAAoB,YAAY;AACvC,WAAK,qBAAqB,eAAe,EAAE,QAAQ,gBAAgB,CAAC;AACpE,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,UAAI,KAAK,oBAAoB,YAAY;AACvC,cAAM,UAAU,uBAAuB,SAAS;AAChD,aAAK;AAAA,UACH,cAAc,YAAY,yBAAyB;AAAA,UACnD;AAAA,YACE,QAAQ;AAAA,YACR,cAAc;AAAA,UAChB;AAAA,QACF;AACA,aAAK,4BAA4B,OAAO;AAAA,MAC1C;AACA,WAAK,qBAAqB,eAAe,EAAE,QAAQ,qBAAqB,CAAC;AACzE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,4BAEE;AACA,WAAO,EAAE,GAAG,KAAK,uBAAuB;AAAA,EAC1C;AAAA,EAEA,iBAA8C;AAC5C,WAAO;AAAA,MACL,kBAAkB,KAAK,oBAAoB,EAAE,IAAI,WAAS,EAAE,GAAG,KAAK,EAAE;AAAA,MACtE,gBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,gBAAgB,UAA6C;AAC3D,SAAK,iBAAiB,MAAM;AAC5B,eAAW,QAAQ,SAAS,kBAAkB;AAC5C,WAAK,iBAAiB,IAAI,KAAK,SAAS,EAAE,GAAG,KAAK,CAAC;AAAA,IACrD;AACA,SAAK,iBAAiB,SAAS;AAAA,EACjC;AAAA,EAEA,UAAmB;AACjB,QAAI,KAAK,+BAA+B,SAAS,MAAM,QAAS,QAAO;AACvE,QAAI;AACF,YAAM,QAAoC;AAAA,QACxC,SAAS;AAAA,QACT,WAAW,KAAK;AAAA,QAChB,kBAAkB,KAAK,oBAAoB,EAAE,IAAI,WAAS;AAAA,UACxD,SAAS,KAAK;AAAA,UACd,iBAAiB,KAAK;AAAA,UACtB,WAAW,KAAK;AAAA,UAChB,SAAS,KAAK;AAAA,UACd,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,QACf,EAAE;AAAA,QACF,eAAe,KAAK,IAAI;AAAA,MAC1B;AACA,WAAK,YAAa,SAAS,KAAK,WAAY,KAAK;AACjD,WAAK,qBAAqB,yBAAyB;AACnD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAK,qBAAqB,wBAAwB;AAAA,QAChD,QAAQ;AAAA,QACR,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,KAAK,oBAAoB,YAAY;AACvC,aAAK,4BAA4B,uCAAuC,OAAO,EAAE;AAAA,MACnF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,UAAmB;AACjB,QAAI,KAAK,+BAA+B,SAAS,MAAM,QAAS,QAAO;AACvE,QAAI;AACF,YAAM,QAAQ,KAAK,YAAa,SAAS,KAAK,SAAU;AACxD,UAAI,CAAC,OAAO;AACV,aAAK,qBAAqB,wBAAwB;AAAA,UAChD,QAAQ;AAAA,QACV,CAAC;AACD,eAAO;AAAA,MACT;AACA,UAAI,MAAM,YAAY,qBAAqB;AACzC,aAAK,qBAAqB,wBAAwB;AAAA,UAChD,QAAQ;AAAA,QACV,CAAC;AACD,YAAI,KAAK,oBAAoB,YAAY;AACvC,eAAK;AAAA,YACH;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,WAAK,iBAAiB,MAAM;AAC5B,YAAM,OAAO,MAAM,QAAQ,MAAM,gBAAgB,IAC7C,MAAM,mBACN,CAAC;AACL,YAAM,OAAO,oBAAI,IAAY;AAC7B,UAAI,UAAU;AACd,UAAI,wBAAwB;AAC5B,UAAI,oBAAoB;AACxB,YAAM,0BAAoC,CAAC;AAC3C,iBAAW,QAAQ,MAAM;AACvB,cAAM,aAA6B;AAAA,UACjC,SAAS,OAAO,KAAK,OAAO;AAAA,UAC5B,iBAAiB,OAAO,KAAK,eAAe;AAAA,UAC5C,WAAW,OAAO,KAAK,aAAa,EAAE;AAAA,UACtC,SAAS,OAAO,KAAK,WAAW,EAAE;AAAA,UAClC,aAAa,OAAO,KAAK,eAAe,KAAK,IAAI,CAAC;AAAA,UAClD,QAAQ,KAAK;AAAA,QACf;AACA,YAAI,CAAC,WAAW,SAAS;AACvB,qBAAW;AACX,+BAAqB;AACrB;AAAA,QACF;AACA,YAAI,KAAK,IAAI,WAAW,OAAO,GAAG;AAChC,qBAAW;AACX,mCAAyB;AACzB,cAAI,wBAAwB,SAAS,GAAG;AACtC,oCAAwB,KAAK,WAAW,OAAO;AAAA,UACjD;AACA;AAAA,QACF;AACA,aAAK,IAAI,WAAW,OAAO;AAC3B,aAAK,iBAAiB,IAAI,WAAW,SAAS,UAAU;AAAA,MAC1D;AACA,WAAK,iBAAiB;AACtB,YAAM,YAAwD;AAAA,QAC5D,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK,iBAAiB;AAAA,QACrC,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc,YAAY;AAAA,MAC5B;AACA,WAAK,qBAAqB,mCAAmC;AAAA,QAC3D,QAAQ,UAAU,eAAe,OAAO;AAAA,QACxC;AAAA,MACF,CAAC;AACD,UAAI,UAAU,GAAG;AACf,aAAK,qBAAqB,wBAAwB;AAAA,UAChD,QAAQ;AAAA,UACR,cAAc,WAAW,OAAO;AAAA,QAClC,CAAC;AAAA,MACH;AACA,WAAK,qBAAqB,yBAAyB;AACnD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAK,qBAAqB,wBAAwB;AAAA,QAChD,QAAQ;AAAA,QACR,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,KAAK,oBAAoB,YAAY;AACvC,aAAK,4BAA4B,uCAAuC,OAAO,EAAE;AAAA,MACnF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,iBAAiB,MAAM;AAC5B,SAAK,iBAAiB;AAAA,EACxB;AACF;AAEO,IAAM,sBAAsB,IAAI,oBAAoB;AAEpD,SAAS,iCAAiC,SAEzB;AACtB,SAAO,SAAS,uBAAuB,IAAI,oBAAoB;AACjE;AAEO,SAAS,mCAAyC;AACvD,sBAAoB,MAAM;AAC5B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -2,7 +2,7 @@ import { createRequire as __pybCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __pybCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
getSessionProjectDir
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-L3R7MPZU.js";
|
|
6
6
|
import {
|
|
7
7
|
isUuid
|
|
8
8
|
} from "./chunk-5P7HBXTD.js";
|
|
@@ -3,13 +3,13 @@ const require = __pybCreateRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
getGlobalConfig,
|
|
5
5
|
saveGlobalConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LEYWQQ7V.js";
|
|
7
7
|
import {
|
|
8
8
|
debug
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-AMQ6XZOU.js";
|
|
10
10
|
import {
|
|
11
11
|
logError
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-G7DKRXDS.js";
|
|
13
13
|
|
|
14
14
|
// src/utils/model/index.ts
|
|
15
15
|
import { memoize } from "lodash-es";
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
PRODUCT_NAME,
|
|
5
5
|
execFileNoThrow,
|
|
6
6
|
logError
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-G7DKRXDS.js";
|
|
8
8
|
import {
|
|
9
9
|
MACRO
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AWRDD6BG.js";
|
|
11
11
|
|
|
12
12
|
// src/utils/session/autoUpdater.ts
|
|
13
13
|
async function getSemver() {
|
|
@@ -82,7 +82,7 @@ async function checkAndNotifyUpdate() {
|
|
|
82
82
|
const [
|
|
83
83
|
{ isAutoUpdaterDisabled, getGlobalConfig, saveGlobalConfig },
|
|
84
84
|
{ env }
|
|
85
|
-
] = await Promise.all([import("./config-
|
|
85
|
+
] = await Promise.all([import("./config-66BMMOES.js"), import("./env-FW74XJHK.js")]);
|
|
86
86
|
if (await isAutoUpdaterDisabled()) return;
|
|
87
87
|
if (await env.getIsDocker()) return;
|
|
88
88
|
if (!await env.hasInternetAccess()) return;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createRequire as __pybCreateRequire } from "node:module";
|
|
2
|
+
const require = __pybCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
logError
|
|
5
|
+
} from "./chunk-G7DKRXDS.js";
|
|
6
|
+
|
|
7
|
+
// src/utils/session/conversationPersistence.ts
|
|
8
|
+
import {
|
|
9
|
+
existsSync,
|
|
10
|
+
mkdirSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
renameSync,
|
|
13
|
+
unlinkSync,
|
|
14
|
+
writeFileSync
|
|
15
|
+
} from "fs";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
var PERSISTENCE_VERSION = 1;
|
|
18
|
+
function sanitizeSessionId(sessionId) {
|
|
19
|
+
return sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
20
|
+
}
|
|
21
|
+
function isValidPersistedCompletedQuery(value) {
|
|
22
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
23
|
+
const item = value;
|
|
24
|
+
return typeof item.queryId === "string" && typeof item.userMessageUUID === "string" && typeof item.userQuery === "string" && typeof item.summary === "string" && typeof item.completedAt === "number" && (item.finish === "end_turn" || item.finish === "tool_calls" || item.finish === "max_tokens" || item.finish === "pause_turn");
|
|
25
|
+
}
|
|
26
|
+
function isValidPersistedConversationState(value) {
|
|
27
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
28
|
+
const state = value;
|
|
29
|
+
return typeof state.version === "number" && typeof state.sessionId === "string" && Array.isArray(state.completedQueries) && state.completedQueries.every(isValidPersistedCompletedQuery) && typeof state.lastUpdatedAt === "number";
|
|
30
|
+
}
|
|
31
|
+
var FileSystemConversationPersistence = class {
|
|
32
|
+
constructor(baseDir) {
|
|
33
|
+
this.baseDir = baseDir;
|
|
34
|
+
}
|
|
35
|
+
getFilePath(sessionId) {
|
|
36
|
+
return join(this.baseDir, `${sanitizeSessionId(sessionId)}.json`);
|
|
37
|
+
}
|
|
38
|
+
saveSync(sessionId, state) {
|
|
39
|
+
const filePath = this.getFilePath(sessionId);
|
|
40
|
+
const tempPath = `${filePath}.tmp`;
|
|
41
|
+
try {
|
|
42
|
+
mkdirSync(this.baseDir, { recursive: true });
|
|
43
|
+
writeFileSync(tempPath, JSON.stringify(state, null, 2), "utf8");
|
|
44
|
+
renameSync(tempPath, filePath);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logError(error);
|
|
47
|
+
try {
|
|
48
|
+
if (existsSync(tempPath)) unlinkSync(tempPath);
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
loadSync(sessionId) {
|
|
54
|
+
const filePath = this.getFilePath(sessionId);
|
|
55
|
+
if (!existsSync(filePath)) return null;
|
|
56
|
+
try {
|
|
57
|
+
const raw = readFileSync(filePath, "utf8");
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
if (!isValidPersistedConversationState(parsed)) return null;
|
|
60
|
+
return parsed;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
clearSync(sessionId) {
|
|
66
|
+
const filePath = this.getFilePath(sessionId);
|
|
67
|
+
try {
|
|
68
|
+
if (existsSync(filePath)) unlinkSync(filePath);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logError(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
PERSISTENCE_VERSION,
|
|
77
|
+
FileSystemConversationPersistence
|
|
78
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/utils/session/conversationPersistence.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from 'fs'\nimport { join } from 'path'\nimport { logError } from '@utils/log'\n\nexport const PERSISTENCE_VERSION = 1\n\nexport type PersistedCompletedQuery = {\n queryId: string\n userMessageUUID: string\n userQuery: string\n summary: string\n completedAt: number\n finish: 'end_turn' | 'tool_calls' | 'max_tokens' | 'pause_turn'\n}\n\nexport type PersistedConversationState = {\n version: number\n sessionId: string\n completedQueries: PersistedCompletedQuery[]\n lastUpdatedAt: number\n}\n\nexport interface ConversationPersistence {\n saveSync(sessionId: string, state: PersistedConversationState): void\n loadSync(sessionId: string): PersistedConversationState | null\n clearSync(sessionId: string): void\n}\n\nfunction sanitizeSessionId(sessionId: string): string {\n return sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')\n}\n\nfunction isValidPersistedCompletedQuery(value: unknown): value is PersistedCompletedQuery {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n const item = value as PersistedCompletedQuery\n return (\n typeof item.queryId === 'string' &&\n typeof item.userMessageUUID === 'string' &&\n typeof item.userQuery === 'string' &&\n typeof item.summary === 'string' &&\n typeof item.completedAt === 'number' &&\n (item.finish === 'end_turn' ||\n item.finish === 'tool_calls' ||\n item.finish === 'max_tokens' ||\n item.finish === 'pause_turn')\n )\n}\n\nfunction isValidPersistedConversationState(\n value: unknown,\n): value is PersistedConversationState {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n const state = value as PersistedConversationState\n return (\n typeof state.version === 'number' &&\n typeof state.sessionId === 'string' &&\n Array.isArray(state.completedQueries) &&\n state.completedQueries.every(isValidPersistedCompletedQuery) &&\n typeof state.lastUpdatedAt === 'number'\n )\n}\n\nexport class FileSystemConversationPersistence implements ConversationPersistence {\n constructor(private readonly baseDir: string) {}\n\n private getFilePath(sessionId: string): string {\n return join(this.baseDir, `${sanitizeSessionId(sessionId)}.json`)\n }\n\n saveSync(sessionId: string, state: PersistedConversationState): void {\n const filePath = this.getFilePath(sessionId)\n const tempPath = `${filePath}.tmp`\n try {\n mkdirSync(this.baseDir, { recursive: true })\n writeFileSync(tempPath, JSON.stringify(state, null, 2), 'utf8')\n renameSync(tempPath, filePath)\n } catch (error) {\n logError(error)\n try {\n if (existsSync(tempPath)) unlinkSync(tempPath)\n } catch {}\n }\n }\n\n loadSync(sessionId: string): PersistedConversationState | null {\n const filePath = this.getFilePath(sessionId)\n if (!existsSync(filePath)) return null\n try {\n const raw = readFileSync(filePath, 'utf8')\n const parsed = JSON.parse(raw) as unknown\n if (!isValidPersistedConversationState(parsed)) return null\n return parsed\n } catch {\n return null\n }\n }\n\n clearSync(sessionId: string): void {\n const filePath = this.getFilePath(sessionId)\n try {\n if (existsSync(filePath)) unlinkSync(filePath)\n } catch (error) {\n logError(error)\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAGd,IAAM,sBAAsB;AAwBnC,SAAS,kBAAkB,WAA2B;AACpD,SAAO,UAAU,QAAQ,mBAAmB,GAAG;AACjD;AAEA,SAAS,+BAA+B,OAAkD;AACxF,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,OAAO;AACb,SACE,OAAO,KAAK,YAAY,YACxB,OAAO,KAAK,oBAAoB,YAChC,OAAO,KAAK,cAAc,YAC1B,OAAO,KAAK,YAAY,YACxB,OAAO,KAAK,gBAAgB,aAC3B,KAAK,WAAW,cACf,KAAK,WAAW,gBAChB,KAAK,WAAW,gBAChB,KAAK,WAAW;AAEtB;AAEA,SAAS,kCACP,OACqC;AACrC,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,QAAQ;AACd,SACE,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,cAAc,YAC3B,MAAM,QAAQ,MAAM,gBAAgB,KACpC,MAAM,iBAAiB,MAAM,8BAA8B,KAC3D,OAAO,MAAM,kBAAkB;AAEnC;AAEO,IAAM,oCAAN,MAA2E;AAAA,EAChF,YAA6B,SAAiB;AAAjB;AAAA,EAAkB;AAAA,EAEvC,YAAY,WAA2B;AAC7C,WAAO,KAAK,KAAK,SAAS,GAAG,kBAAkB,SAAS,CAAC,OAAO;AAAA,EAClE;AAAA,EAEA,SAAS,WAAmB,OAAyC;AACnE,UAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,UAAM,WAAW,GAAG,QAAQ;AAC5B,QAAI;AACF,gBAAU,KAAK,SAAS,EAAE,WAAW,KAAK,CAAC;AAC3C,oBAAc,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,MAAM;AAC9D,iBAAW,UAAU,QAAQ;AAAA,IAC/B,SAAS,OAAO;AACd,eAAS,KAAK;AACd,UAAI;AACF,YAAI,WAAW,QAAQ,EAAG,YAAW,QAAQ;AAAA,MAC/C,QAAQ;AAAA,MAAC;AAAA,IACX;AAAA,EACF;AAAA,EAEA,SAAS,WAAsD;AAC7D,UAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,QAAI,CAAC,WAAW,QAAQ,EAAG,QAAO;AAClC,QAAI;AACF,YAAM,MAAM,aAAa,UAAU,MAAM;AACzC,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,kCAAkC,MAAM,EAAG,QAAO;AACvD,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,UAAU,WAAyB;AACjC,UAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,QAAI;AACF,UAAI,WAAW,QAAQ,EAAG,YAAW,QAAQ;AAAA,IAC/C,SAAS,OAAO;AACd,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
} from "./chunk-B6IMQJZM.js";
|
|
6
6
|
import {
|
|
7
7
|
loadSettingsWithLegacyFallback
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HIJYNCCN.js";
|
|
9
9
|
import {
|
|
10
10
|
getSessionPlugins
|
|
11
11
|
} from "./chunk-BJSWTHRM.js";
|
|
12
12
|
import {
|
|
13
13
|
getCwd,
|
|
14
14
|
logError
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-G7DKRXDS.js";
|
|
16
16
|
|
|
17
17
|
// src/utils/session/pybHooks.ts
|
|
18
18
|
import { spawn } from "child_process";
|
|
@@ -496,7 +496,7 @@ async function runPromptHook(args) {
|
|
|
496
496
|
fallbackTimeoutMs: args.fallbackTimeoutMs
|
|
497
497
|
});
|
|
498
498
|
try {
|
|
499
|
-
const { queryQuick } = await import("./llmLazy-
|
|
499
|
+
const { queryQuick } = await import("./llmLazy-LYGZWC7G.js");
|
|
500
500
|
const systemPrompt = [
|
|
501
501
|
"You are executing a Pyb prompt hook.",
|
|
502
502
|
"Return a single JSON object only (no markdown, no prose).",
|
|
@@ -2,10 +2,10 @@ import { createRequire as __pybCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __pybCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
debug
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AMQ6XZOU.js";
|
|
6
6
|
import {
|
|
7
7
|
logError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-G7DKRXDS.js";
|
|
9
9
|
|
|
10
10
|
// src/services/system/systemReminder.ts
|
|
11
11
|
var SystemReminderService = class {
|