jinzd-ai-cli 0.4.233 → 0.4.234
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/{batch-WWNPYQ6G.js → batch-T3FRX4B6.js} +2 -2
- package/dist/{chat-index-O56HDGFI.js → chat-index-7HXBWQFH.js} +2 -2
- package/dist/{chat-index-WSI7ULRQ.js → chat-index-WYXYD7YP.js} +1 -1
- package/dist/{chunk-4KM53GLG.js → chunk-2QQKS56X.js} +1 -1
- package/dist/{chunk-ACTO5C6K.js → chunk-3KTSJ2EL.js} +1 -1
- package/dist/{chunk-NXYXFRPA.js → chunk-5DTEEWYC.js} +3 -3
- package/dist/{chunk-NVUCDUXE.js → chunk-5MYPIQ3Y.js} +11 -5
- package/dist/{chunk-7KS3RGZ7.js → chunk-5VPRZMZB.js} +2 -2
- package/dist/{chunk-FQSAK75P.js → chunk-6MJMHHRK.js} +3 -3
- package/dist/{chunk-M4FW2NPU.js → chunk-AFT6VFMI.js} +1 -1
- package/dist/{chunk-HX67JAK6.js → chunk-E5RLXMSU.js} +5 -5
- package/dist/{chunk-4OAV7QMB.js → chunk-ETJ5X6V7.js} +1 -1
- package/dist/{chunk-EZGZOK6E.js → chunk-II6RZRTF.js} +1 -1
- package/dist/{chunk-ZWU7FWHO.js → chunk-JMP3LJC2.js} +38 -91
- package/dist/chunk-KCEO2XJ4.js +420 -0
- package/dist/{chunk-5PKNKJYP.js → chunk-L5PNAQ6O.js} +1 -1
- package/dist/{chunk-TJK7AU65.js → chunk-TAXIG7HH.js} +1 -1
- package/dist/{chunk-LF3OUJHK.js → chunk-UO3XWZFE.js} +302 -4
- package/dist/{ci-V5V3JSJC.js → ci-GJ53GPLA.js} +4 -4
- package/dist/{ci-format-XS7LKBO5.js → ci-format-AXE4QCI6.js} +2 -2
- package/dist/{constants-UROQJXLY.js → constants-DC4EXFSB.js} +1 -1
- package/dist/{doctor-cli-BY3FIV2B.js → doctor-cli-HKREND6Q.js} +4 -4
- package/dist/electron-server.js +43 -96
- package/dist/{hub-L2QCRI5M.js → hub-LTTKRGZC.js} +2 -2
- package/dist/index.js +22 -22
- package/dist/{persist-I3JI27OK.js → persist-AMH5SQ4W.js} +3 -3
- package/dist/{pr-IJRUPR5C.js → pr-4VODJVRV.js} +4 -4
- package/dist/{run-tests-FLCVJ6TK.js → run-tests-G5BNTMWQ.js} +2 -2
- package/dist/{run-tests-NNXBS4EL.js → run-tests-QR2PYR2P.js} +1 -1
- package/dist/{server-W2X3C6GJ.js → server-64WZVZZN.js} +15 -15
- package/dist/{server-E6LZB72O.js → server-EO6VQHKL.js} +6 -6
- package/dist/{task-orchestrator-W55VKYTC.js → task-orchestrator-4INCZMLT.js} +6 -6
- package/dist/{usage-MZCDTJWB.js → usage-T3HFMNNV.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-B5TYJO7V.js +0 -123
|
@@ -128,6 +128,293 @@ function scanString(input, options) {
|
|
|
128
128
|
return hits;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
// src/session/session-index.ts
|
|
132
|
+
import { existsSync, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
133
|
+
import { join } from "path";
|
|
134
|
+
|
|
135
|
+
// src/session/session-meta.ts
|
|
136
|
+
import { readFileSync, openSync, readSync, closeSync } from "fs";
|
|
137
|
+
function safeDate(value) {
|
|
138
|
+
const d = new Date(value);
|
|
139
|
+
return isNaN(d.getTime()) ? /* @__PURE__ */ new Date(0) : d;
|
|
140
|
+
}
|
|
141
|
+
function extractJsonField(header, field) {
|
|
142
|
+
const re = new RegExp(`"${field}"\\s*:\\s*"([^"]*)"`, "i");
|
|
143
|
+
const m = header.match(re);
|
|
144
|
+
return m ? m[1] : void 0;
|
|
145
|
+
}
|
|
146
|
+
function extractJsonNumberField(header, field) {
|
|
147
|
+
const m = header.match(new RegExp(`"${field}"\\s*:\\s*(\\d+)`));
|
|
148
|
+
return m ? Number(m[1]) : void 0;
|
|
149
|
+
}
|
|
150
|
+
function readSessionMeta(filePath) {
|
|
151
|
+
const HEADER_SIZE = 1024;
|
|
152
|
+
let header;
|
|
153
|
+
try {
|
|
154
|
+
const fd = openSync(filePath, "r");
|
|
155
|
+
const buf = Buffer.alloc(HEADER_SIZE);
|
|
156
|
+
const bytesRead = readSync(fd, buf, 0, HEADER_SIZE, 0);
|
|
157
|
+
closeSync(fd);
|
|
158
|
+
header = buf.toString("utf-8", 0, bytesRead);
|
|
159
|
+
} catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const id = extractJsonField(header, "id");
|
|
163
|
+
const provider = extractJsonField(header, "provider");
|
|
164
|
+
const model = extractJsonField(header, "model");
|
|
165
|
+
const created = extractJsonField(header, "created");
|
|
166
|
+
const updated = extractJsonField(header, "updated");
|
|
167
|
+
const title = extractJsonField(header, "title");
|
|
168
|
+
if (id && provider && model) {
|
|
169
|
+
let messageCount = extractJsonNumberField(header, "messageCount");
|
|
170
|
+
if (messageCount === void 0) {
|
|
171
|
+
messageCount = 0;
|
|
172
|
+
try {
|
|
173
|
+
const full = readFileSync(filePath, "utf-8");
|
|
174
|
+
const matches = full.match(/"role"\s*:/g);
|
|
175
|
+
messageCount = matches ? matches.length : 0;
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
let branchCount;
|
|
180
|
+
let activeBranch;
|
|
181
|
+
try {
|
|
182
|
+
const brMatch = header.match(/"branches"\s*:\s*\[/);
|
|
183
|
+
if (brMatch) {
|
|
184
|
+
const parentMatches = header.match(/"parentBranchId"/g);
|
|
185
|
+
branchCount = parentMatches ? parentMatches.length + 1 : 1;
|
|
186
|
+
}
|
|
187
|
+
activeBranch = extractJsonField(header, "activeBranchId");
|
|
188
|
+
} catch {
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
id,
|
|
192
|
+
provider,
|
|
193
|
+
model,
|
|
194
|
+
messageCount,
|
|
195
|
+
created: safeDate(created),
|
|
196
|
+
updated: safeDate(updated),
|
|
197
|
+
title: title || void 0,
|
|
198
|
+
branchCount,
|
|
199
|
+
activeBranch
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const data = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
203
|
+
return {
|
|
204
|
+
id: data.id,
|
|
205
|
+
provider: data.provider,
|
|
206
|
+
model: data.model,
|
|
207
|
+
messageCount: data.messages?.length ?? 0,
|
|
208
|
+
created: safeDate(data.created),
|
|
209
|
+
updated: safeDate(data.updated),
|
|
210
|
+
title: data.title,
|
|
211
|
+
branchCount: data.branches?.length ?? 1,
|
|
212
|
+
activeBranch: data.activeBranchId
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/session/session-index.ts
|
|
217
|
+
var INDEX_FILE = "sessions.index.json";
|
|
218
|
+
function indexFilePath(historyDir2) {
|
|
219
|
+
return join(historyDir2, INDEX_FILE);
|
|
220
|
+
}
|
|
221
|
+
function loadIndex(historyDir2) {
|
|
222
|
+
const fp = indexFilePath(historyDir2);
|
|
223
|
+
if (!existsSync(fp)) return null;
|
|
224
|
+
try {
|
|
225
|
+
const data = JSON.parse(readFileSync2(fp, "utf-8"));
|
|
226
|
+
if (data?.version === 1 && data.sessions && data.invertedIndex) {
|
|
227
|
+
return data;
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function saveIndex(historyDir2, idx) {
|
|
235
|
+
idx.built = (/* @__PURE__ */ new Date()).toISOString();
|
|
236
|
+
const fp = indexFilePath(historyDir2);
|
|
237
|
+
atomicWriteFileSync(fp, JSON.stringify(idx));
|
|
238
|
+
}
|
|
239
|
+
function rebuildIndex(historyDir2) {
|
|
240
|
+
if (!existsSync(historyDir2)) {
|
|
241
|
+
const empty = { version: 1, built: (/* @__PURE__ */ new Date()).toISOString(), sessions: {}, invertedIndex: {} };
|
|
242
|
+
return empty;
|
|
243
|
+
}
|
|
244
|
+
const files = readdirSync(historyDir2).filter((f) => f.endsWith(".json"));
|
|
245
|
+
const sessions = {};
|
|
246
|
+
const invertedIndex = /* @__PURE__ */ new Map();
|
|
247
|
+
for (const file of files) {
|
|
248
|
+
const filePath = join(historyDir2, file);
|
|
249
|
+
const meta = readSessionMeta(filePath);
|
|
250
|
+
if (!meta) continue;
|
|
251
|
+
let fileSize = 0;
|
|
252
|
+
try {
|
|
253
|
+
fileSize = statSync(filePath).size;
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
let mtimeMs = 0;
|
|
257
|
+
try {
|
|
258
|
+
mtimeMs = statSync(filePath).mtimeMs;
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
const entry = {
|
|
262
|
+
id: meta.id,
|
|
263
|
+
provider: meta.provider,
|
|
264
|
+
model: meta.model,
|
|
265
|
+
title: meta.title,
|
|
266
|
+
messageCount: meta.messageCount,
|
|
267
|
+
fileSize,
|
|
268
|
+
created: meta.created.toISOString(),
|
|
269
|
+
updated: meta.updated.toISOString(),
|
|
270
|
+
branchCount: meta.branchCount,
|
|
271
|
+
activeBranch: meta.activeBranch,
|
|
272
|
+
_mtimeMs: mtimeMs
|
|
273
|
+
};
|
|
274
|
+
sessions[meta.id] = entry;
|
|
275
|
+
addTokensToIndex(invertedIndex, meta.title ?? "", meta.id);
|
|
276
|
+
}
|
|
277
|
+
const serializedIndex = {};
|
|
278
|
+
for (const [token, ids] of invertedIndex) {
|
|
279
|
+
serializedIndex[token] = [...ids];
|
|
280
|
+
}
|
|
281
|
+
const idx = {
|
|
282
|
+
version: 1,
|
|
283
|
+
built: (/* @__PURE__ */ new Date()).toISOString(),
|
|
284
|
+
sessions,
|
|
285
|
+
invertedIndex: serializedIndex
|
|
286
|
+
};
|
|
287
|
+
saveIndex(historyDir2, idx);
|
|
288
|
+
return idx;
|
|
289
|
+
}
|
|
290
|
+
function updateSessionInIndex(historyDir2, meta, filePath) {
|
|
291
|
+
let idx = loadIndex(historyDir2);
|
|
292
|
+
if (!idx) {
|
|
293
|
+
rebuildIndex(historyDir2);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
let fileSize = 0;
|
|
297
|
+
try {
|
|
298
|
+
fileSize = statSync(filePath).size;
|
|
299
|
+
} catch {
|
|
300
|
+
}
|
|
301
|
+
let mtimeMs = 0;
|
|
302
|
+
try {
|
|
303
|
+
mtimeMs = statSync(filePath).mtimeMs;
|
|
304
|
+
} catch {
|
|
305
|
+
}
|
|
306
|
+
const id = meta.id;
|
|
307
|
+
for (const [token, ids] of Object.entries(idx.invertedIndex)) {
|
|
308
|
+
const filtered = ids.filter((sid) => sid !== id);
|
|
309
|
+
if (filtered.length === 0) {
|
|
310
|
+
delete idx.invertedIndex[token];
|
|
311
|
+
} else {
|
|
312
|
+
idx.invertedIndex[token] = filtered;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
idx.sessions[id] = {
|
|
316
|
+
id,
|
|
317
|
+
provider: meta.provider,
|
|
318
|
+
model: meta.model,
|
|
319
|
+
title: meta.title,
|
|
320
|
+
messageCount: meta.messageCount,
|
|
321
|
+
fileSize,
|
|
322
|
+
created: meta.created.toISOString(),
|
|
323
|
+
updated: meta.updated.toISOString(),
|
|
324
|
+
_mtimeMs: mtimeMs
|
|
325
|
+
};
|
|
326
|
+
const tokens = tokenize(meta.title ?? "");
|
|
327
|
+
for (const token of tokens) {
|
|
328
|
+
const existing = idx.invertedIndex[token] ?? [];
|
|
329
|
+
if (!existing.includes(id)) {
|
|
330
|
+
existing.push(id);
|
|
331
|
+
idx.invertedIndex[token] = existing;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
saveIndex(historyDir2, idx);
|
|
335
|
+
}
|
|
336
|
+
function removeSessionFromIndex(historyDir2, id) {
|
|
337
|
+
const idx = loadIndex(historyDir2);
|
|
338
|
+
if (!idx) return;
|
|
339
|
+
delete idx.sessions[id];
|
|
340
|
+
for (const [token, ids] of Object.entries(idx.invertedIndex)) {
|
|
341
|
+
const filtered = ids.filter((sid) => sid !== id);
|
|
342
|
+
if (filtered.length === 0) {
|
|
343
|
+
delete idx.invertedIndex[token];
|
|
344
|
+
} else {
|
|
345
|
+
idx.invertedIndex[token] = filtered;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
saveIndex(historyDir2, idx);
|
|
349
|
+
}
|
|
350
|
+
function listFromIndex(historyDir2, opts) {
|
|
351
|
+
let idx = loadIndex(historyDir2);
|
|
352
|
+
if (!idx) {
|
|
353
|
+
idx = rebuildIndex(historyDir2);
|
|
354
|
+
}
|
|
355
|
+
return Object.values(idx.sessions).map((entry) => ({
|
|
356
|
+
id: entry.id,
|
|
357
|
+
provider: entry.provider,
|
|
358
|
+
model: entry.model,
|
|
359
|
+
title: entry.title,
|
|
360
|
+
messageCount: entry.messageCount,
|
|
361
|
+
created: new Date(entry.created),
|
|
362
|
+
updated: new Date(entry.updated),
|
|
363
|
+
fileSize: opts?.includeFileSize ? entry.fileSize : void 0,
|
|
364
|
+
branchCount: entry.branchCount,
|
|
365
|
+
activeBranch: entry.activeBranch
|
|
366
|
+
})).sort((a, b) => b.updated.getTime() - a.updated.getTime());
|
|
367
|
+
}
|
|
368
|
+
function searchCandidates(historyDir2, query) {
|
|
369
|
+
const idx = loadIndex(historyDir2);
|
|
370
|
+
if (!idx) return null;
|
|
371
|
+
const queryTokens = tokenize(query.toLowerCase());
|
|
372
|
+
if (queryTokens.length === 0) return null;
|
|
373
|
+
const scoreMap = /* @__PURE__ */ new Map();
|
|
374
|
+
for (const token of queryTokens) {
|
|
375
|
+
const matchingIds = idx.invertedIndex[token];
|
|
376
|
+
if (!matchingIds) continue;
|
|
377
|
+
for (const sid of matchingIds) {
|
|
378
|
+
scoreMap.set(sid, (scoreMap.get(sid) ?? 0) + 1);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const candidates = [...scoreMap.entries()].filter(([, score]) => score > 0).sort((a, b) => {
|
|
382
|
+
const scoreDiff = b[1] - a[1];
|
|
383
|
+
if (scoreDiff !== 0) return scoreDiff;
|
|
384
|
+
const aMeta = idx.sessions[a[0]];
|
|
385
|
+
const bMeta = idx.sessions[b[0]];
|
|
386
|
+
return (bMeta?.updated ?? "").localeCompare(aMeta?.updated ?? "");
|
|
387
|
+
}).map(([sid]) => sid);
|
|
388
|
+
return candidates.length > 0 ? candidates : null;
|
|
389
|
+
}
|
|
390
|
+
function getIndexMtimeMap(historyDir2) {
|
|
391
|
+
const idx = loadIndex(historyDir2);
|
|
392
|
+
if (!idx) return null;
|
|
393
|
+
const map = {};
|
|
394
|
+
for (const entry of Object.values(idx.sessions)) {
|
|
395
|
+
map[entry.id] = entry._mtimeMs;
|
|
396
|
+
}
|
|
397
|
+
return map;
|
|
398
|
+
}
|
|
399
|
+
function addTokensToIndex(invertedIndex, text, sessionId) {
|
|
400
|
+
for (const token of tokenize(text)) {
|
|
401
|
+
const s = invertedIndex.get(token) ?? /* @__PURE__ */ new Set();
|
|
402
|
+
s.add(sessionId);
|
|
403
|
+
invertedIndex.set(token, s);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function tokenize(text) {
|
|
407
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
408
|
+
const cjkOnly = text.replace(/[^\u4e00-\u9fff\u3400-\u4dbf]/g, "");
|
|
409
|
+
for (let i = 0; i < cjkOnly.length - 1; i++) {
|
|
410
|
+
tokens.add(cjkOnly.slice(i, i + 2));
|
|
411
|
+
}
|
|
412
|
+
const english = text.replace(/[\u4e00-\u9fff\u3400-\u4dbf]/g, " ").toLowerCase();
|
|
413
|
+
const words = english.split(/[^a-z0-9]+/).filter((w) => w.length >= 2);
|
|
414
|
+
for (const w of words) tokens.add(w);
|
|
415
|
+
return [...tokens];
|
|
416
|
+
}
|
|
417
|
+
|
|
131
418
|
// src/memory/chat-index.ts
|
|
132
419
|
var MEMORY_DIR_NAME = "memory-index";
|
|
133
420
|
var CHUNKS_FILE = "chunks.json";
|
|
@@ -285,14 +572,19 @@ function listSessionFiles() {
|
|
|
285
572
|
const dir = historyDir();
|
|
286
573
|
if (!fs.existsSync(dir)) return [];
|
|
287
574
|
const out = [];
|
|
575
|
+
const indexMtimes = getIndexMtimeMap(dir);
|
|
288
576
|
for (const name of fs.readdirSync(dir)) {
|
|
289
577
|
if (!name.endsWith(".json")) continue;
|
|
290
578
|
const id = name.replace(/\.json$/, "");
|
|
291
579
|
const p = path.join(dir, name);
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
580
|
+
if (indexMtimes && indexMtimes[id] !== void 0) {
|
|
581
|
+
out.push({ id, path: p, mtime: indexMtimes[id] });
|
|
582
|
+
} else {
|
|
583
|
+
try {
|
|
584
|
+
const st = fs.statSync(p);
|
|
585
|
+
out.push({ id, path: p, mtime: st.mtimeMs });
|
|
586
|
+
} catch {
|
|
587
|
+
}
|
|
296
588
|
}
|
|
297
589
|
}
|
|
298
590
|
return out;
|
|
@@ -461,6 +753,12 @@ export {
|
|
|
461
753
|
redactString,
|
|
462
754
|
redactJson,
|
|
463
755
|
scanString,
|
|
756
|
+
safeDate,
|
|
757
|
+
readSessionMeta,
|
|
758
|
+
updateSessionInIndex,
|
|
759
|
+
removeSessionFromIndex,
|
|
760
|
+
listFromIndex,
|
|
761
|
+
searchCandidates,
|
|
464
762
|
chunkSession,
|
|
465
763
|
loadChatIndex,
|
|
466
764
|
clearChatIndex,
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
CI_COMMENT_MARKER,
|
|
4
4
|
countSeverity,
|
|
5
5
|
runCi
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-6MJMHHRK.js";
|
|
7
|
+
import "./chunk-TAXIG7HH.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-QYQI7ZWK.js";
|
|
10
10
|
import "./chunk-O3XSFPYH.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-L5PNAQ6O.js";
|
|
12
12
|
import "./chunk-5ULLIOVC.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-3KTSJ2EL.js";
|
|
14
14
|
import "./chunk-IW3Q7AE5.js";
|
|
15
15
|
export {
|
|
16
16
|
CI_COMMENT_MARKER,
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
formatDoctorReport,
|
|
4
4
|
runDoctorCli
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5DTEEWYC.js";
|
|
6
6
|
import "./chunk-QYQI7ZWK.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-II6RZRTF.js";
|
|
8
8
|
import "./chunk-O3XSFPYH.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-L5PNAQ6O.js";
|
|
10
10
|
import "./chunk-5ULLIOVC.js";
|
|
11
11
|
import "./chunk-HOSJZMQS.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-3KTSJ2EL.js";
|
|
13
13
|
import "./chunk-IW3Q7AE5.js";
|
|
14
14
|
export {
|
|
15
15
|
formatDoctorReport,
|
package/dist/electron-server.js
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
VERSION,
|
|
39
39
|
buildUserIdentityPrompt,
|
|
40
40
|
runTestsTool
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-ETJ5X6V7.js";
|
|
42
42
|
import {
|
|
43
43
|
hasSemanticIndex,
|
|
44
44
|
semanticSearch
|
|
@@ -49,12 +49,18 @@ import {
|
|
|
49
49
|
import "./chunk-IEQAE3QG.js";
|
|
50
50
|
import {
|
|
51
51
|
DEFAULT_PATTERNS,
|
|
52
|
+
listFromIndex,
|
|
52
53
|
loadChatIndex,
|
|
54
|
+
readSessionMeta,
|
|
53
55
|
redactJson,
|
|
54
56
|
redactString,
|
|
57
|
+
removeSessionFromIndex,
|
|
58
|
+
safeDate,
|
|
55
59
|
scanString,
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
searchCandidates,
|
|
61
|
+
searchChatMemory,
|
|
62
|
+
updateSessionInIndex
|
|
63
|
+
} from "./chunk-UO3XWZFE.js";
|
|
58
64
|
import "./chunk-JV5N65KN.js";
|
|
59
65
|
import {
|
|
60
66
|
atomicWriteFileSync
|
|
@@ -3947,7 +3953,7 @@ var ProviderRegistry = class {
|
|
|
3947
3953
|
};
|
|
3948
3954
|
|
|
3949
3955
|
// src/session/session-manager.ts
|
|
3950
|
-
import { readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync, unlinkSync as unlinkSync2,
|
|
3956
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync, unlinkSync as unlinkSync2, statSync } from "fs";
|
|
3951
3957
|
import { join as join3 } from "path";
|
|
3952
3958
|
import { v4 as uuidv4 } from "uuid";
|
|
3953
3959
|
|
|
@@ -4483,19 +4489,6 @@ var Session = class _Session {
|
|
|
4483
4489
|
};
|
|
4484
4490
|
|
|
4485
4491
|
// src/session/session-manager.ts
|
|
4486
|
-
function safeDate(value) {
|
|
4487
|
-
const d = new Date(value);
|
|
4488
|
-
return isNaN(d.getTime()) ? /* @__PURE__ */ new Date(0) : d;
|
|
4489
|
-
}
|
|
4490
|
-
function extractJsonField(header, field) {
|
|
4491
|
-
const re = new RegExp(`"${field}"\\s*:\\s*"([^"]*)"`, "i");
|
|
4492
|
-
const m = header.match(re);
|
|
4493
|
-
return m ? m[1] : void 0;
|
|
4494
|
-
}
|
|
4495
|
-
function extractJsonNumberField(header, field) {
|
|
4496
|
-
const m = header.match(new RegExp(`"${field}"\\s*:\\s*(\\d+)`));
|
|
4497
|
-
return m ? Number(m[1]) : void 0;
|
|
4498
|
-
}
|
|
4499
4492
|
var SessionManager = class {
|
|
4500
4493
|
_current = null;
|
|
4501
4494
|
historyDir;
|
|
@@ -4553,6 +4546,18 @@ var SessionManager = class {
|
|
|
4553
4546
|
this.lastRedactionHits = hits.length;
|
|
4554
4547
|
atomicWriteFileSync(filePath, JSON.stringify(payload, null, 2));
|
|
4555
4548
|
this._current.dirty = false;
|
|
4549
|
+
try {
|
|
4550
|
+
updateSessionInIndex(this.historyDir, {
|
|
4551
|
+
id: this._current.id,
|
|
4552
|
+
provider: this._current.provider,
|
|
4553
|
+
model: this._current.model,
|
|
4554
|
+
title: this._current.title,
|
|
4555
|
+
messageCount: this._current.messages.length,
|
|
4556
|
+
created: this._current.created,
|
|
4557
|
+
updated: this._current.updated
|
|
4558
|
+
}, filePath);
|
|
4559
|
+
} catch {
|
|
4560
|
+
}
|
|
4556
4561
|
}
|
|
4557
4562
|
loadSession(id) {
|
|
4558
4563
|
const filePath = join3(this.historyDir, `${id}.json`);
|
|
@@ -4571,12 +4576,16 @@ var SessionManager = class {
|
|
|
4571
4576
|
}
|
|
4572
4577
|
listSessions(opts) {
|
|
4573
4578
|
if (!existsSync3(this.historyDir)) return [];
|
|
4579
|
+
try {
|
|
4580
|
+
return listFromIndex(this.historyDir, opts);
|
|
4581
|
+
} catch {
|
|
4582
|
+
}
|
|
4574
4583
|
const files = readdirSync(this.historyDir).filter((f) => f.endsWith(".json"));
|
|
4575
4584
|
const metas = [];
|
|
4576
4585
|
for (const file of files) {
|
|
4577
4586
|
try {
|
|
4578
4587
|
const filePath = join3(this.historyDir, file);
|
|
4579
|
-
const meta =
|
|
4588
|
+
const meta = readSessionMeta(filePath);
|
|
4580
4589
|
if (!meta) continue;
|
|
4581
4590
|
if (opts?.includeFileSize) {
|
|
4582
4591
|
try {
|
|
@@ -4594,78 +4603,6 @@ var SessionManager = class {
|
|
|
4594
4603
|
}
|
|
4595
4604
|
return metas.sort((a, b) => b.updated.getTime() - a.updated.getTime());
|
|
4596
4605
|
}
|
|
4597
|
-
/**
|
|
4598
|
-
* P1-B: Read only the first ~1KB of a session file to extract metadata fields.
|
|
4599
|
-
* Session JSON format puts id/provider/model/created/updated/title before the
|
|
4600
|
-
* large "messages" array, so a small header read suffices for metadata extraction.
|
|
4601
|
-
* Falls back to full file read if header parsing fails.
|
|
4602
|
-
*/
|
|
4603
|
-
readSessionMeta(filePath) {
|
|
4604
|
-
const HEADER_SIZE = 1024;
|
|
4605
|
-
let header;
|
|
4606
|
-
try {
|
|
4607
|
-
const fd = openSync(filePath, "r");
|
|
4608
|
-
const buf = Buffer.alloc(HEADER_SIZE);
|
|
4609
|
-
const bytesRead = readSync(fd, buf, 0, HEADER_SIZE, 0);
|
|
4610
|
-
closeSync(fd);
|
|
4611
|
-
header = buf.toString("utf-8", 0, bytesRead);
|
|
4612
|
-
} catch {
|
|
4613
|
-
return null;
|
|
4614
|
-
}
|
|
4615
|
-
const id = extractJsonField(header, "id");
|
|
4616
|
-
const provider = extractJsonField(header, "provider");
|
|
4617
|
-
const model = extractJsonField(header, "model");
|
|
4618
|
-
const created = extractJsonField(header, "created");
|
|
4619
|
-
const updated = extractJsonField(header, "updated");
|
|
4620
|
-
const title = extractJsonField(header, "title");
|
|
4621
|
-
if (id && provider && model) {
|
|
4622
|
-
let messageCount = extractJsonNumberField(header, "messageCount");
|
|
4623
|
-
if (messageCount === void 0) {
|
|
4624
|
-
messageCount = 0;
|
|
4625
|
-
try {
|
|
4626
|
-
const full = readFileSync3(filePath, "utf-8");
|
|
4627
|
-
const matches = full.match(/"role"\s*:/g);
|
|
4628
|
-
messageCount = matches ? matches.length : 0;
|
|
4629
|
-
} catch {
|
|
4630
|
-
}
|
|
4631
|
-
}
|
|
4632
|
-
let branchCount;
|
|
4633
|
-
let activeBranch;
|
|
4634
|
-
try {
|
|
4635
|
-
const brMatch = header.match(/"branches"\s*:\s*\[/);
|
|
4636
|
-
if (brMatch) {
|
|
4637
|
-
const brIds = header.match(/"id"\s*:\s*"[^"]*"/g);
|
|
4638
|
-
const parentMatches = header.match(/"parentBranchId"/g);
|
|
4639
|
-
branchCount = parentMatches ? parentMatches.length + 1 : 1;
|
|
4640
|
-
}
|
|
4641
|
-
activeBranch = extractJsonField(header, "activeBranchId");
|
|
4642
|
-
} catch {
|
|
4643
|
-
}
|
|
4644
|
-
return {
|
|
4645
|
-
id,
|
|
4646
|
-
provider,
|
|
4647
|
-
model,
|
|
4648
|
-
messageCount,
|
|
4649
|
-
created: safeDate(created),
|
|
4650
|
-
updated: safeDate(updated),
|
|
4651
|
-
title: title || void 0,
|
|
4652
|
-
branchCount,
|
|
4653
|
-
activeBranch
|
|
4654
|
-
};
|
|
4655
|
-
}
|
|
4656
|
-
const data = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
4657
|
-
return {
|
|
4658
|
-
id: data.id,
|
|
4659
|
-
provider: data.provider,
|
|
4660
|
-
model: data.model,
|
|
4661
|
-
messageCount: data.messages?.length ?? 0,
|
|
4662
|
-
created: safeDate(data.created),
|
|
4663
|
-
updated: safeDate(data.updated),
|
|
4664
|
-
title: data.title,
|
|
4665
|
-
branchCount: data.branches?.length ?? 1,
|
|
4666
|
-
activeBranch: data.activeBranchId
|
|
4667
|
-
};
|
|
4668
|
-
}
|
|
4669
4606
|
deleteSession(id) {
|
|
4670
4607
|
const filePath = join3(this.historyDir, `${id}.json`);
|
|
4671
4608
|
if (!existsSync3(filePath)) return false;
|
|
@@ -4674,6 +4611,10 @@ var SessionManager = class {
|
|
|
4674
4611
|
if (this._current && this._current.id === id) {
|
|
4675
4612
|
this._current = null;
|
|
4676
4613
|
}
|
|
4614
|
+
try {
|
|
4615
|
+
removeSessionFromIndex(this.historyDir, id);
|
|
4616
|
+
} catch {
|
|
4617
|
+
}
|
|
4677
4618
|
return true;
|
|
4678
4619
|
} catch {
|
|
4679
4620
|
return false;
|
|
@@ -4707,9 +4648,15 @@ var SessionManager = class {
|
|
|
4707
4648
|
searchMessages(query, maxResults = 20) {
|
|
4708
4649
|
if (!existsSync3(this.historyDir)) return [];
|
|
4709
4650
|
const q = query.toLowerCase();
|
|
4710
|
-
const
|
|
4651
|
+
const candidateIds = searchCandidates(this.historyDir, q);
|
|
4652
|
+
let filesToSearch;
|
|
4653
|
+
if (candidateIds !== null) {
|
|
4654
|
+
filesToSearch = candidateIds.map((id) => join3(this.historyDir, `${id}.json`)).filter((fp) => existsSync3(fp));
|
|
4655
|
+
} else {
|
|
4656
|
+
filesToSearch = readdirSync(this.historyDir).filter((f) => f.endsWith(".json")).map((f) => join3(this.historyDir, f));
|
|
4657
|
+
}
|
|
4711
4658
|
const results = [];
|
|
4712
|
-
for (const filePath of
|
|
4659
|
+
for (const filePath of filesToSearch) {
|
|
4713
4660
|
if (results.length >= maxResults) break;
|
|
4714
4661
|
try {
|
|
4715
4662
|
const data = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
@@ -15908,7 +15855,7 @@ async function handleSecurityReview(args, ctx) {
|
|
|
15908
15855
|
async function handleTest(args, ctx) {
|
|
15909
15856
|
ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
15910
15857
|
try {
|
|
15911
|
-
const { executeTests } = await import("./run-tests-
|
|
15858
|
+
const { executeTests } = await import("./run-tests-QR2PYR2P.js");
|
|
15912
15859
|
const argStr = args.join(" ").trim();
|
|
15913
15860
|
let testArgs = {};
|
|
15914
15861
|
if (argStr) {
|
|
@@ -17771,7 +17718,7 @@ ${entry.content}`;
|
|
|
17771
17718
|
return;
|
|
17772
17719
|
}
|
|
17773
17720
|
try {
|
|
17774
|
-
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-
|
|
17721
|
+
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-WYXYD7YP.js");
|
|
17775
17722
|
const loaded = loadChatIndex2();
|
|
17776
17723
|
if (!loaded || loaded.idx.chunks.length === 0) {
|
|
17777
17724
|
this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
|
|
@@ -17807,7 +17754,7 @@ ${entry.content}`;
|
|
|
17807
17754
|
}
|
|
17808
17755
|
async handleMemoryStatus() {
|
|
17809
17756
|
try {
|
|
17810
|
-
const { getChatIndexStatus } = await import("./chat-index-
|
|
17757
|
+
const { getChatIndexStatus } = await import("./chat-index-WYXYD7YP.js");
|
|
17811
17758
|
const s = getChatIndexStatus();
|
|
17812
17759
|
this.send({
|
|
17813
17760
|
type: "memory_status",
|
|
@@ -17832,7 +17779,7 @@ ${entry.content}`;
|
|
|
17832
17779
|
type: "info",
|
|
17833
17780
|
message: full ? "\u{1F9E0} Rebuilding chat memory index (this may take a while on first run \u2014 ~117 MB embedder)." : "\u{1F9E0} Refreshing chat memory index (incremental)\u2026"
|
|
17834
17781
|
});
|
|
17835
|
-
const { buildChatIndex } = await import("./chat-index-
|
|
17782
|
+
const { buildChatIndex } = await import("./chat-index-WYXYD7YP.js");
|
|
17836
17783
|
const stats = await buildChatIndex({
|
|
17837
17784
|
full,
|
|
17838
17785
|
onProgress: (p) => {
|
|
@@ -139,7 +139,7 @@ ${content}`);
|
|
|
139
139
|
const state = await runDiscussion(config, providers, options.topic);
|
|
140
140
|
if (options.save !== false && state.messages.length > 0) {
|
|
141
141
|
try {
|
|
142
|
-
const { persistDiscussion } = await import("./persist-
|
|
142
|
+
const { persistDiscussion } = await import("./persist-AMH5SQ4W.js");
|
|
143
143
|
const { path } = await persistDiscussion(state, configManager, defaultProvider, defaultModel);
|
|
144
144
|
console.log(chalk.dim(`
|
|
145
145
|
\u{1F4BE} Saved to history \u2014 open it in the Web UI and hit \u{1F3AC} to replay.
|
|
@@ -154,7 +154,7 @@ ${content}`);
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
157
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
157
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-4INCZMLT.js");
|
|
158
158
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
159
159
|
let interrupted = false;
|
|
160
160
|
const onSigint = () => {
|