jinzd-ai-cli 0.4.242 → 0.4.244
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-D3UHL432.js → batch-GLB7ES6K.js} +2 -2
- package/dist/{chunk-6ZWNXHNH.js → chunk-6IAVHU3I.js} +1 -1
- package/dist/{chunk-WMAXYDCB.js → chunk-ACU6T7B3.js} +1 -1
- package/dist/{chunk-Y4CMNXZH.js → chunk-B7KTFHK2.js} +1 -1
- package/dist/{chunk-D27TMEOV.js → chunk-BKTCOL5D.js} +107 -2
- package/dist/{chunk-J363BGOH.js → chunk-BO5UU3TY.js} +1 -1
- package/dist/{chunk-FRNWQIG6.js → chunk-HN4FU37T.js} +3 -3
- package/dist/{chunk-UWV2NBCO.js → chunk-M7XY5AK5.js} +107 -2
- package/dist/{chunk-MC2ZNPBC.js → chunk-MCC5BEZG.js} +1 -1
- package/dist/{chunk-PSP6UIKL.js → chunk-OYFDGRYD.js} +2 -2
- package/dist/{chunk-OO2PHOXD.js → chunk-P6AUULT2.js} +3 -3
- package/dist/{chunk-FEMPCNX3.js → chunk-WF7FD7WS.js} +49 -27
- package/dist/{chunk-LHINXQZF.js → chunk-XZI4ULXF.js} +1 -1
- package/dist/{chunk-MKLPAQT6.js → chunk-ZQGCX4QD.js} +1 -1
- package/dist/{ci-WSED3Z6V.js → ci-V7RGDIER.js} +4 -4
- package/dist/{ci-format-6AYL2X2J.js → ci-format-HSUEHAM2.js} +2 -2
- package/dist/{constants-FJ3L5GYO.js → constants-OQ6FVQ23.js} +1 -1
- package/dist/{doctor-cli-HCP56MKH.js → doctor-cli-LABZF3XG.js} +4 -4
- package/dist/electron-server.js +115 -93
- package/dist/{hub-K5MYSVEF.js → hub-RTFICY6M.js} +1 -1
- package/dist/index.js +91 -25
- package/dist/{persistent-memory-HWFNDQFQ.js → persistent-memory-OWXDBSZY.js} +12 -2
- package/dist/{persistent-memory-EYAKL2XA.js → persistent-memory-P6LU5KDG.js} +12 -2
- package/dist/{pr-OICMUN6R.js → pr-HXJ6ML6M.js} +4 -4
- package/dist/{run-tests-B3FSE5NV.js → run-tests-EFWAH43I.js} +2 -2
- package/dist/{run-tests-DSEW5HED.js → run-tests-XJ44FWIK.js} +2 -2
- package/dist/{server-2FS65CQZ.js → server-6OPGWJ7S.js} +11 -11
- package/dist/{server-EDCGPEGC.js → server-B6WJWV3T.js} +5 -5
- package/dist/{task-orchestrator-WCZYV3TE.js → task-orchestrator-KHJYQXWU.js} +5 -5
- package/dist/{usage-WVUYNLOD.js → usage-NW2ZXN6N.js} +2 -2
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ACU6T7B3.js";
|
|
5
5
|
import "./chunk-5ULLIOVC.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-B7KTFHK2.js";
|
|
7
7
|
import {
|
|
8
8
|
atomicWriteFileSync
|
|
9
9
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
MEMORY_FILE_NAME,
|
|
7
7
|
MEMORY_MAX_CHARS,
|
|
8
8
|
MEMORY_STORE_FILE_NAME
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-B7KTFHK2.js";
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_PATTERNS,
|
|
12
12
|
redactString
|
|
@@ -59,6 +59,7 @@ function normalizeEntry(value) {
|
|
|
59
59
|
createdAt,
|
|
60
60
|
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : createdAt,
|
|
61
61
|
expiresAt: typeof raw.expiresAt === "string" && raw.expiresAt ? raw.expiresAt : void 0,
|
|
62
|
+
lastReferencedAt: typeof raw.lastReferencedAt === "string" && raw.lastReferencedAt ? raw.lastReferencedAt : void 0,
|
|
62
63
|
sensitivity: isValidSensitivity(raw.sensitivity) ? raw.sensitivity : "low",
|
|
63
64
|
approved: raw.approved === true,
|
|
64
65
|
redactedKinds: Array.isArray(raw.redactedKinds) ? raw.redactedKinds.filter((x) => typeof x === "string") : void 0
|
|
@@ -299,6 +300,105 @@ function detectStaleLegacyMarkdownEdit(configDir) {
|
|
|
299
300
|
return false;
|
|
300
301
|
}
|
|
301
302
|
}
|
|
303
|
+
function touchMemoryReferences(configDir, ids) {
|
|
304
|
+
if (ids.length === 0) return;
|
|
305
|
+
const wanted = new Set(ids);
|
|
306
|
+
const entries = loadMemoryEntries(configDir);
|
|
307
|
+
let changed = false;
|
|
308
|
+
const ts = nowIso();
|
|
309
|
+
for (const entry of entries) {
|
|
310
|
+
if (wanted.has(entry.id)) {
|
|
311
|
+
entry.lastReferencedAt = ts;
|
|
312
|
+
changed = true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (changed) saveMemoryEntries(configDir, entries);
|
|
316
|
+
}
|
|
317
|
+
function isMemoryStale(entry, days, at = /* @__PURE__ */ new Date()) {
|
|
318
|
+
const reference = Date.parse(entry.lastReferencedAt ?? entry.updatedAt);
|
|
319
|
+
if (!Number.isFinite(reference)) return false;
|
|
320
|
+
return at.getTime() - reference > days * 864e5;
|
|
321
|
+
}
|
|
322
|
+
function tokenizeQuery(query) {
|
|
323
|
+
const tokens = [];
|
|
324
|
+
for (const word of query.toLowerCase().split(/\s+/).filter(Boolean)) {
|
|
325
|
+
const cjkRuns = word.match(/[一-鿿-ヿ가-]+/g) ?? [];
|
|
326
|
+
const nonCjk = word.replace(/[一-鿿-ヿ가-]+/g, " ").split(/\s+/).filter((t) => t.length >= 2);
|
|
327
|
+
tokens.push(...nonCjk);
|
|
328
|
+
for (const run of cjkRuns) {
|
|
329
|
+
if (run.length === 1) tokens.push(run);
|
|
330
|
+
for (let i = 0; i + 2 <= run.length; i++) tokens.push(run.slice(i, i + 2));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return [...new Set(tokens)];
|
|
334
|
+
}
|
|
335
|
+
function searchPersistentMemories(configDir, query, cwd = process.cwd(), limit = 3) {
|
|
336
|
+
const tokens = tokenizeQuery(query);
|
|
337
|
+
if (tokens.length === 0) return [];
|
|
338
|
+
const entries = listMemoryEntries(configDir, { cwd }).filter((entry) => entry.approved && !isMemoryExpired(entry));
|
|
339
|
+
const hits = [];
|
|
340
|
+
for (const entry of entries) {
|
|
341
|
+
const haystack = entry.content.toLowerCase();
|
|
342
|
+
const matched = tokens.filter((token) => haystack.includes(token)).length;
|
|
343
|
+
const score = matched / tokens.length;
|
|
344
|
+
if (score >= 0.34) hits.push({ entry, score });
|
|
345
|
+
}
|
|
346
|
+
return hits.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
347
|
+
}
|
|
348
|
+
function backupMemoryStore(configDir, outPath) {
|
|
349
|
+
const entries = loadMemoryEntries(configDir);
|
|
350
|
+
if (entries.length === 0) throw new Error("memory is empty \u2014 nothing to back up");
|
|
351
|
+
const storePath = memoryStorePath(configDir);
|
|
352
|
+
if (!existsSync(storePath)) saveMemoryEntries(configDir, entries);
|
|
353
|
+
const backupPath = outPath ?? `${storePath}.bak.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
354
|
+
copyFileSync(storePath, backupPath);
|
|
355
|
+
return { backupPath, count: entries.length };
|
|
356
|
+
}
|
|
357
|
+
function restoreMemoryEntries(configDir, filePath) {
|
|
358
|
+
const text = readFileSync(filePath, "utf-8").trim();
|
|
359
|
+
if (!text) throw new Error(`restore file is empty: ${filePath}`);
|
|
360
|
+
let rawItems;
|
|
361
|
+
try {
|
|
362
|
+
const parsed = JSON.parse(text);
|
|
363
|
+
rawItems = Array.isArray(parsed) ? parsed : [parsed];
|
|
364
|
+
} catch {
|
|
365
|
+
rawItems = text.split("\n").map((line) => {
|
|
366
|
+
try {
|
|
367
|
+
return JSON.parse(line.trim());
|
|
368
|
+
} catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
}).filter((x) => x !== null);
|
|
372
|
+
}
|
|
373
|
+
const candidates = rawItems.map((item) => normalizeEntry(item)).filter((entry) => Boolean(entry));
|
|
374
|
+
if (candidates.length === 0) throw new Error(`no valid memory entries found in ${filePath}`);
|
|
375
|
+
const existing = loadMemoryEntries(configDir);
|
|
376
|
+
const existingIds = new Set(existing.map((entry) => entry.id));
|
|
377
|
+
let backupPath = null;
|
|
378
|
+
if (existing.length > 0) {
|
|
379
|
+
backupPath = backupMemoryStore(configDir).backupPath;
|
|
380
|
+
}
|
|
381
|
+
let imported = 0;
|
|
382
|
+
let skipped = 0;
|
|
383
|
+
for (const candidate of candidates) {
|
|
384
|
+
if (existingIds.has(candidate.id)) {
|
|
385
|
+
skipped++;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
const redacted = redactString(candidate.content, { enabled: true, patterns: DEFAULT_PATTERNS });
|
|
389
|
+
if (redacted.hits.length > 0) {
|
|
390
|
+
candidate.content = redacted.redacted.trim();
|
|
391
|
+
candidate.sensitivity = "high";
|
|
392
|
+
candidate.approved = false;
|
|
393
|
+
candidate.redactedKinds = [...new Set(redacted.hits.map((hit) => hit.kind))];
|
|
394
|
+
}
|
|
395
|
+
existing.push(candidate);
|
|
396
|
+
existingIds.add(candidate.id);
|
|
397
|
+
imported++;
|
|
398
|
+
}
|
|
399
|
+
saveMemoryEntries(configDir, existing);
|
|
400
|
+
return { imported, skipped, backupPath };
|
|
401
|
+
}
|
|
302
402
|
|
|
303
403
|
export {
|
|
304
404
|
parseWritableScope,
|
|
@@ -323,5 +423,10 @@ export {
|
|
|
323
423
|
findSimilarMemory,
|
|
324
424
|
listOrphanedProjectMemories,
|
|
325
425
|
rebindMemoryProject,
|
|
326
|
-
detectStaleLegacyMarkdownEdit
|
|
426
|
+
detectStaleLegacyMarkdownEdit,
|
|
427
|
+
touchMemoryReferences,
|
|
428
|
+
isMemoryStale,
|
|
429
|
+
searchPersistentMemories,
|
|
430
|
+
backupMemoryStore,
|
|
431
|
+
restoreMemoryEntries
|
|
327
432
|
};
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-QYQI7ZWK.js";
|
|
5
5
|
import {
|
|
6
6
|
ConfigManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ACU6T7B3.js";
|
|
8
8
|
import {
|
|
9
9
|
getActivePluginAssets,
|
|
10
10
|
getPendingHookTrust,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
listHooks,
|
|
15
15
|
listInstalledPlugins,
|
|
16
16
|
resetStats
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BO5UU3TY.js";
|
|
18
18
|
import {
|
|
19
19
|
getGitRoot
|
|
20
20
|
} from "./chunk-HOSJZMQS.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
MCP_PROJECT_CONFIG_NAME,
|
|
27
27
|
MEMORY_FILE_NAME,
|
|
28
28
|
VERSION
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-B7KTFHK2.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
MEMORY_FILE_NAME,
|
|
7
7
|
MEMORY_MAX_CHARS,
|
|
8
8
|
MEMORY_STORE_FILE_NAME
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZQGCX4QD.js";
|
|
10
10
|
import {
|
|
11
11
|
atomicWriteFileSync
|
|
12
12
|
} from "./chunk-6BUTA5VW.js";
|
|
@@ -147,6 +147,7 @@ function normalizeEntry(value) {
|
|
|
147
147
|
createdAt,
|
|
148
148
|
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : createdAt,
|
|
149
149
|
expiresAt: typeof raw.expiresAt === "string" && raw.expiresAt ? raw.expiresAt : void 0,
|
|
150
|
+
lastReferencedAt: typeof raw.lastReferencedAt === "string" && raw.lastReferencedAt ? raw.lastReferencedAt : void 0,
|
|
150
151
|
sensitivity: isValidSensitivity(raw.sensitivity) ? raw.sensitivity : "low",
|
|
151
152
|
approved: raw.approved === true,
|
|
152
153
|
redactedKinds: Array.isArray(raw.redactedKinds) ? raw.redactedKinds.filter((x) => typeof x === "string") : void 0
|
|
@@ -387,6 +388,105 @@ function detectStaleLegacyMarkdownEdit(configDir) {
|
|
|
387
388
|
return false;
|
|
388
389
|
}
|
|
389
390
|
}
|
|
391
|
+
function touchMemoryReferences(configDir, ids) {
|
|
392
|
+
if (ids.length === 0) return;
|
|
393
|
+
const wanted = new Set(ids);
|
|
394
|
+
const entries = loadMemoryEntries(configDir);
|
|
395
|
+
let changed = false;
|
|
396
|
+
const ts = nowIso();
|
|
397
|
+
for (const entry of entries) {
|
|
398
|
+
if (wanted.has(entry.id)) {
|
|
399
|
+
entry.lastReferencedAt = ts;
|
|
400
|
+
changed = true;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (changed) saveMemoryEntries(configDir, entries);
|
|
404
|
+
}
|
|
405
|
+
function isMemoryStale(entry, days, at = /* @__PURE__ */ new Date()) {
|
|
406
|
+
const reference = Date.parse(entry.lastReferencedAt ?? entry.updatedAt);
|
|
407
|
+
if (!Number.isFinite(reference)) return false;
|
|
408
|
+
return at.getTime() - reference > days * 864e5;
|
|
409
|
+
}
|
|
410
|
+
function tokenizeQuery(query) {
|
|
411
|
+
const tokens = [];
|
|
412
|
+
for (const word of query.toLowerCase().split(/\s+/).filter(Boolean)) {
|
|
413
|
+
const cjkRuns = word.match(/[一-鿿-ヿ가-]+/g) ?? [];
|
|
414
|
+
const nonCjk = word.replace(/[一-鿿-ヿ가-]+/g, " ").split(/\s+/).filter((t) => t.length >= 2);
|
|
415
|
+
tokens.push(...nonCjk);
|
|
416
|
+
for (const run of cjkRuns) {
|
|
417
|
+
if (run.length === 1) tokens.push(run);
|
|
418
|
+
for (let i = 0; i + 2 <= run.length; i++) tokens.push(run.slice(i, i + 2));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return [...new Set(tokens)];
|
|
422
|
+
}
|
|
423
|
+
function searchPersistentMemories(configDir, query, cwd = process.cwd(), limit = 3) {
|
|
424
|
+
const tokens = tokenizeQuery(query);
|
|
425
|
+
if (tokens.length === 0) return [];
|
|
426
|
+
const entries = listMemoryEntries(configDir, { cwd }).filter((entry) => entry.approved && !isMemoryExpired(entry));
|
|
427
|
+
const hits = [];
|
|
428
|
+
for (const entry of entries) {
|
|
429
|
+
const haystack = entry.content.toLowerCase();
|
|
430
|
+
const matched = tokens.filter((token) => haystack.includes(token)).length;
|
|
431
|
+
const score = matched / tokens.length;
|
|
432
|
+
if (score >= 0.34) hits.push({ entry, score });
|
|
433
|
+
}
|
|
434
|
+
return hits.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
435
|
+
}
|
|
436
|
+
function backupMemoryStore(configDir, outPath) {
|
|
437
|
+
const entries = loadMemoryEntries(configDir);
|
|
438
|
+
if (entries.length === 0) throw new Error("memory is empty \u2014 nothing to back up");
|
|
439
|
+
const storePath = memoryStorePath(configDir);
|
|
440
|
+
if (!existsSync2(storePath)) saveMemoryEntries(configDir, entries);
|
|
441
|
+
const backupPath = outPath ?? `${storePath}.bak.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
442
|
+
copyFileSync(storePath, backupPath);
|
|
443
|
+
return { backupPath, count: entries.length };
|
|
444
|
+
}
|
|
445
|
+
function restoreMemoryEntries(configDir, filePath) {
|
|
446
|
+
const text = readFileSync(filePath, "utf-8").trim();
|
|
447
|
+
if (!text) throw new Error(`restore file is empty: ${filePath}`);
|
|
448
|
+
let rawItems;
|
|
449
|
+
try {
|
|
450
|
+
const parsed = JSON.parse(text);
|
|
451
|
+
rawItems = Array.isArray(parsed) ? parsed : [parsed];
|
|
452
|
+
} catch {
|
|
453
|
+
rawItems = text.split("\n").map((line) => {
|
|
454
|
+
try {
|
|
455
|
+
return JSON.parse(line.trim());
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}).filter((x) => x !== null);
|
|
460
|
+
}
|
|
461
|
+
const candidates = rawItems.map((item) => normalizeEntry(item)).filter((entry) => Boolean(entry));
|
|
462
|
+
if (candidates.length === 0) throw new Error(`no valid memory entries found in ${filePath}`);
|
|
463
|
+
const existing = loadMemoryEntries(configDir);
|
|
464
|
+
const existingIds = new Set(existing.map((entry) => entry.id));
|
|
465
|
+
let backupPath = null;
|
|
466
|
+
if (existing.length > 0) {
|
|
467
|
+
backupPath = backupMemoryStore(configDir).backupPath;
|
|
468
|
+
}
|
|
469
|
+
let imported = 0;
|
|
470
|
+
let skipped = 0;
|
|
471
|
+
for (const candidate of candidates) {
|
|
472
|
+
if (existingIds.has(candidate.id)) {
|
|
473
|
+
skipped++;
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
const redacted = redactString(candidate.content, { enabled: true, patterns: DEFAULT_PATTERNS });
|
|
477
|
+
if (redacted.hits.length > 0) {
|
|
478
|
+
candidate.content = redacted.redacted.trim();
|
|
479
|
+
candidate.sensitivity = "high";
|
|
480
|
+
candidate.approved = false;
|
|
481
|
+
candidate.redactedKinds = [...new Set(redacted.hits.map((hit) => hit.kind))];
|
|
482
|
+
}
|
|
483
|
+
existing.push(candidate);
|
|
484
|
+
existingIds.add(candidate.id);
|
|
485
|
+
imported++;
|
|
486
|
+
}
|
|
487
|
+
saveMemoryEntries(configDir, existing);
|
|
488
|
+
return { imported, skipped, backupPath };
|
|
489
|
+
}
|
|
390
490
|
|
|
391
491
|
export {
|
|
392
492
|
getGitRoot,
|
|
@@ -414,5 +514,10 @@ export {
|
|
|
414
514
|
findSimilarMemory,
|
|
415
515
|
listOrphanedProjectMemories,
|
|
416
516
|
rebindMemoryProject,
|
|
417
|
-
detectStaleLegacyMarkdownEdit
|
|
517
|
+
detectStaleLegacyMarkdownEdit,
|
|
518
|
+
touchMemoryReferences,
|
|
519
|
+
isMemoryStale,
|
|
520
|
+
searchPersistentMemories,
|
|
521
|
+
backupMemoryStore,
|
|
522
|
+
restoreMemoryEntries
|
|
418
523
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
truncateForPersist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WF7FD7WS.js";
|
|
5
5
|
import {
|
|
6
6
|
APP_NAME,
|
|
7
7
|
CONFIG_DIR_NAME,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
MCP_PROTOCOL_VERSION,
|
|
12
12
|
MCP_TOOL_PREFIX,
|
|
13
13
|
VERSION
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-B7KTFHK2.js";
|
|
15
15
|
import {
|
|
16
16
|
atomicWriteFileSync
|
|
17
17
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XZI4ULXF.js";
|
|
6
6
|
import {
|
|
7
7
|
buildReviewPrompt,
|
|
8
8
|
buildSecurityReviewPrompt,
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
} from "./chunk-QYQI7ZWK.js";
|
|
14
14
|
import {
|
|
15
15
|
ConfigManager
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ACU6T7B3.js";
|
|
17
17
|
import {
|
|
18
18
|
VERSION
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-B7KTFHK2.js";
|
|
20
20
|
|
|
21
21
|
// src/cli/ci.ts
|
|
22
22
|
import { execFileSync } from "child_process";
|
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
findSimilarMemory,
|
|
5
5
|
loadMemoryEntries,
|
|
6
6
|
parseWritableScope,
|
|
7
|
+
searchPersistentMemories,
|
|
8
|
+
touchMemoryReferences,
|
|
7
9
|
updateMemoryEntry
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BKTCOL5D.js";
|
|
9
11
|
import {
|
|
10
12
|
indexProject
|
|
11
13
|
} from "./chunk-K3CF65QH.js";
|
|
@@ -21,7 +23,7 @@ import {
|
|
|
21
23
|
runHook,
|
|
22
24
|
runLifecycleHooks,
|
|
23
25
|
runTool
|
|
24
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-BO5UU3TY.js";
|
|
25
27
|
import {
|
|
26
28
|
getDangerLevel,
|
|
27
29
|
isFileWriteTool,
|
|
@@ -37,14 +39,14 @@ import {
|
|
|
37
39
|
} from "./chunk-4BKXL7SM.js";
|
|
38
40
|
import {
|
|
39
41
|
runTestsTool
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-6IAVHU3I.js";
|
|
41
43
|
import {
|
|
42
44
|
CONFIG_DIR_NAME,
|
|
43
45
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
44
46
|
SUBAGENT_ALLOWED_TOOLS,
|
|
45
47
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
46
48
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-B7KTFHK2.js";
|
|
48
50
|
import {
|
|
49
51
|
loadChatIndex,
|
|
50
52
|
searchChatMemory
|
|
@@ -556,6 +558,10 @@ Important rules:
|
|
|
556
558
|
[The user pressed Ctrl+C while this command was running. Stop the current task, summarize what was done so far, and wait for the user's next instruction. Do NOT retry this command or continue with further tool calls unless explicitly asked.]`
|
|
557
559
|
);
|
|
558
560
|
}
|
|
561
|
+
if (timedOut) {
|
|
562
|
+
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
563
|
+
throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
|
|
564
|
+
}
|
|
559
565
|
if (status !== 0 || timedOut) {
|
|
560
566
|
const poolStdout = (stdout ?? "").trim();
|
|
561
567
|
const poolStderr = (stderr ?? "").trim();
|
|
@@ -617,21 +623,7 @@ ${combined || formatFailureFallback(status)}
|
|
|
617
623
|
const execErr = err;
|
|
618
624
|
const isTimeout = execErr.code === "ETIMEDOUT" || execErr.status == null && execErr.signal === "SIGTERM" || /ETIMEDOUT/i.test(execErr.message ?? "");
|
|
619
625
|
if (isTimeout) {
|
|
620
|
-
|
|
621
|
-
throw new ToolError(
|
|
622
|
-
"bash",
|
|
623
|
-
`Command timed out after ${seconds}s.
|
|
624
|
-
|
|
625
|
-
The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.
|
|
626
|
-
|
|
627
|
-
How to recover (pick ONE \u2014 do NOT retry the same command):
|
|
628
|
-
1. Pass an explicit longer timeout, e.g. timeout: ${Math.min(timeout * 2, MAX_TIMEOUT)}
|
|
629
|
-
2. Use a non-recursive / narrower alternative (e.g. 'Get-ChildItem -File' without -Recurse, or limit depth with -Depth 1)
|
|
630
|
-
3. Split the work into smaller batches (process subdirectories one at a time)
|
|
631
|
-
4. For size/count queries, use '(Get-ChildItem X).Count' per directory instead of one giant pipeline
|
|
632
|
-
|
|
633
|
-
[Do NOT retry the identical command \u2014 it will time out again.]`
|
|
634
|
-
);
|
|
626
|
+
throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
|
|
635
627
|
}
|
|
636
628
|
if ("status" in execErr && execErr.status !== void 0) {
|
|
637
629
|
const stderr = IS_WINDOWS3 && Buffer.isBuffer(execErr.stderr) ? decodeWindowsBuffer(execErr.stderr).trim() : execErr.stderr?.toString().trim() ?? "";
|
|
@@ -656,6 +648,22 @@ ${combined || execErr.message || formatFailureFallback(execErr.status)}
|
|
|
656
648
|
function formatFailureHeader(status) {
|
|
657
649
|
return typeof status === "number" ? `Exit code ${status}:` : "Command failed before exit code could be determined:";
|
|
658
650
|
}
|
|
651
|
+
function formatTimeoutMessage(timeout, maxTimeout) {
|
|
652
|
+
const seconds = Math.round(timeout / 1e3);
|
|
653
|
+
return [
|
|
654
|
+
`Command timed out after ${seconds}s.`,
|
|
655
|
+
"",
|
|
656
|
+
"The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.",
|
|
657
|
+
"",
|
|
658
|
+
"How to recover (pick ONE \u2014 do NOT retry the same command):",
|
|
659
|
+
` 1. Pass an explicit longer timeout, e.g. timeout: ${Math.min(timeout * 2, maxTimeout)}`,
|
|
660
|
+
" 2. Use a non-recursive / narrower alternative (e.g. 'Get-ChildItem -File' without -Recurse, or limit depth with -Depth 1)",
|
|
661
|
+
" 3. Split the work into smaller batches (process subdirectories one at a time)",
|
|
662
|
+
" 4. For size/count queries, use '(Get-ChildItem X).Count' per directory instead of one giant pipeline",
|
|
663
|
+
"",
|
|
664
|
+
"[Do NOT retry the identical command \u2014 it will time out again.]"
|
|
665
|
+
].join(String.fromCharCode(10));
|
|
666
|
+
}
|
|
659
667
|
function formatFailureFallback(status) {
|
|
660
668
|
return typeof status === "number" ? `exit ${status}` : "The shell process ended before reporting a numeric exit code.";
|
|
661
669
|
}
|
|
@@ -6576,6 +6584,8 @@ ${lines.join("\n")}`;
|
|
|
6576
6584
|
};
|
|
6577
6585
|
|
|
6578
6586
|
// src/tools/builtin/recall-memory.ts
|
|
6587
|
+
import { join as join8 } from "path";
|
|
6588
|
+
import { homedir as homedir5 } from "os";
|
|
6579
6589
|
function formatHit(h, i) {
|
|
6580
6590
|
const ts = h.chunk.timestamp.slice(0, 16).replace("T", " ");
|
|
6581
6591
|
const title = h.chunk.sessionTitle ? ` \xB7 ${h.chunk.sessionTitle}` : "";
|
|
@@ -6588,7 +6598,7 @@ function formatHit(h, i) {
|
|
|
6588
6598
|
var recallMemoryTool = {
|
|
6589
6599
|
definition: {
|
|
6590
6600
|
name: "recall_memory",
|
|
6591
|
-
description: '
|
|
6601
|
+
description: 'Search long-term memory: governed persistent memory entries (keyword match) plus semantic search over past chat sessions. Call this whenever the user references something that may have been discussed before ("last time", "remember", "\u4E4B\u524D", "\u4E0A\u6B21"), when context is ambiguous and continuity matters, or when you want to check what decisions or preferences have been established across prior conversations \u2014 including memories that were dropped from the injected system prompt by the size budget. Returns persistent-memory hits first, then up to `topK` chat snippets with session id, timestamp, and cosine similarity score. Prefer this over asking the user "can you remind me".',
|
|
6592
6602
|
parameters: {
|
|
6593
6603
|
query: {
|
|
6594
6604
|
type: "string",
|
|
@@ -6625,9 +6635,21 @@ var recallMemoryTool = {
|
|
|
6625
6635
|
const excludeCurrent = Boolean(args["excludeCurrentSession"]);
|
|
6626
6636
|
const currentId = args["currentSessionId"] ? String(args["currentSessionId"]) : void 0;
|
|
6627
6637
|
const minScore = args["minScore"] !== void 0 ? Number(args["minScore"]) : 0.25;
|
|
6638
|
+
const configDir = join8(homedir5(), CONFIG_DIR_NAME);
|
|
6639
|
+
let persistentSection = "";
|
|
6640
|
+
try {
|
|
6641
|
+
const persistentHits = searchPersistentMemories(configDir, query, process.cwd(), 3);
|
|
6642
|
+
if (persistentHits.length > 0) {
|
|
6643
|
+
touchMemoryReferences(configDir, persistentHits.map((h) => h.entry.id));
|
|
6644
|
+
persistentSection = `\u2500\u2500 Persistent memory (${persistentHits.length} hit(s)) \u2500\u2500
|
|
6645
|
+
` + persistentHits.map((h) => `[id ${h.entry.id.slice(0, 8)} \xB7 ${h.entry.scope} \xB7 coverage ${h.score.toFixed(2)}]
|
|
6646
|
+
${h.entry.content}`).join("\n\n") + "\n\n";
|
|
6647
|
+
}
|
|
6648
|
+
} catch {
|
|
6649
|
+
}
|
|
6628
6650
|
const status = loadChatIndex();
|
|
6629
6651
|
if (!status) {
|
|
6630
|
-
return "No chat memory index found. The index is built on REPL startup, or run `/memory rebuild` manually. If you have no past sessions yet, this is expected.";
|
|
6652
|
+
return persistentSection + "No chat memory index found. The index is built on REPL startup, or run `/memory rebuild` manually. If you have no past sessions yet, this is expected.";
|
|
6631
6653
|
}
|
|
6632
6654
|
const hits = await searchChatMemory(query, {
|
|
6633
6655
|
topK,
|
|
@@ -6635,11 +6657,11 @@ var recallMemoryTool = {
|
|
|
6635
6657
|
excludeSessionId: excludeCurrent ? currentId : void 0
|
|
6636
6658
|
});
|
|
6637
6659
|
if (hits.length === 0) {
|
|
6638
|
-
return `No memories matched "${query}" above score ${minScore}. Index has ${status.idx.chunks.length} chunks across ${Object.keys(status.idx.sessionMtimes).length} sessions. Consider lowering minScore to 0.15 or rephrasing the query.`;
|
|
6660
|
+
return persistentSection + `No chat-history memories matched "${query}" above score ${minScore}. Index has ${status.idx.chunks.length} chunks across ${Object.keys(status.idx.sessionMtimes).length} sessions. Consider lowering minScore to 0.15 or rephrasing the query.`;
|
|
6639
6661
|
}
|
|
6640
|
-
const header = `Found ${hits.length}
|
|
6662
|
+
const header = `Found ${hits.length} chat-history hit(s) for "${query}" (min-score ${minScore}):
|
|
6641
6663
|
`;
|
|
6642
|
-
return header + "\n" + hits.map(formatHit).join("\n\n");
|
|
6664
|
+
return persistentSection + header + "\n" + hits.map(formatHit).join("\n\n");
|
|
6643
6665
|
}
|
|
6644
6666
|
};
|
|
6645
6667
|
|
|
@@ -6668,7 +6690,7 @@ function estimateToolDefinitionTokens(def) {
|
|
|
6668
6690
|
// src/tools/registry.ts
|
|
6669
6691
|
import { pathToFileURL } from "url";
|
|
6670
6692
|
import { existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync7 } from "fs";
|
|
6671
|
-
import { join as
|
|
6693
|
+
import { join as join9 } from "path";
|
|
6672
6694
|
var ToolRegistry = class {
|
|
6673
6695
|
tools = /* @__PURE__ */ new Map();
|
|
6674
6696
|
pluginToolNames = /* @__PURE__ */ new Set();
|
|
@@ -6855,12 +6877,12 @@ var ToolRegistry = class {
|
|
|
6855
6877
|
process.stderr.write(
|
|
6856
6878
|
`
|
|
6857
6879
|
[plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
|
|
6858
|
-
` + files.map((f) => ` + ${
|
|
6880
|
+
` + files.map((f) => ` + ${join9(pluginsDir, f)}`).join("\n") + "\n\n"
|
|
6859
6881
|
);
|
|
6860
6882
|
let loaded = 0;
|
|
6861
6883
|
for (const file of files) {
|
|
6862
6884
|
try {
|
|
6863
|
-
const fileUrl = pathToFileURL(
|
|
6885
|
+
const fileUrl = pathToFileURL(join9(pluginsDir, file)).href;
|
|
6864
6886
|
const mod = await import(fileUrl);
|
|
6865
6887
|
const tool = mod.tool ?? mod.default?.tool ?? mod.default;
|
|
6866
6888
|
if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
|
|
@@ -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-P6AUULT2.js";
|
|
7
|
+
import "./chunk-XZI4ULXF.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-QYQI7ZWK.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-ACU6T7B3.js";
|
|
11
11
|
import "./chunk-O3XSFPYH.js";
|
|
12
12
|
import "./chunk-5ULLIOVC.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-B7KTFHK2.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-HN4FU37T.js";
|
|
6
6
|
import "./chunk-QYQI7ZWK.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-ACU6T7B3.js";
|
|
8
|
+
import "./chunk-BO5UU3TY.js";
|
|
9
9
|
import "./chunk-O3XSFPYH.js";
|
|
10
10
|
import "./chunk-5ULLIOVC.js";
|
|
11
11
|
import "./chunk-HOSJZMQS.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-B7KTFHK2.js";
|
|
13
13
|
import "./chunk-IW3Q7AE5.js";
|
|
14
14
|
export {
|
|
15
15
|
formatDoctorReport,
|