jinzd-ai-cli 0.4.242 → 0.4.243
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-CUVZUPRK.js} +2 -2
- package/dist/{chunk-Y4CMNXZH.js → chunk-66CE3E6X.js} +1 -1
- package/dist/{chunk-LHINXQZF.js → chunk-DJGCG7SF.js} +1 -1
- package/dist/{chunk-J363BGOH.js → chunk-EMFCHE2B.js} +1 -1
- package/dist/{chunk-MKLPAQT6.js → chunk-GEWPLNKA.js} +1 -1
- package/dist/{chunk-PSP6UIKL.js → chunk-H3ARWBYR.js} +2 -2
- package/dist/{chunk-FRNWQIG6.js → chunk-HNJX3N2V.js} +3 -3
- package/dist/{chunk-FEMPCNX3.js → chunk-KILKF2VN.js} +28 -12
- package/dist/{chunk-6ZWNXHNH.js → chunk-L5IRDRWG.js} +1 -1
- package/dist/{chunk-MC2ZNPBC.js → chunk-PLEXBFCR.js} +1 -1
- package/dist/{chunk-UWV2NBCO.js → chunk-PNNZRJ67.js} +107 -2
- package/dist/{chunk-OO2PHOXD.js → chunk-QNK7GUUB.js} +3 -3
- package/dist/{chunk-D27TMEOV.js → chunk-TY4FSEZS.js} +107 -2
- package/dist/{chunk-WMAXYDCB.js → chunk-X73Y4JZI.js} +1 -1
- package/dist/{ci-WSED3Z6V.js → ci-3O3JR6FX.js} +4 -4
- package/dist/{ci-format-6AYL2X2J.js → ci-format-KGWF6KOU.js} +2 -2
- package/dist/{constants-FJ3L5GYO.js → constants-NMFRZ5LW.js} +1 -1
- package/dist/{doctor-cli-HCP56MKH.js → doctor-cli-4QUHTJZ4.js} +4 -4
- package/dist/electron-server.js +94 -78
- package/dist/{hub-K5MYSVEF.js → hub-2GXFPWOR.js} +1 -1
- package/dist/index.js +91 -25
- package/dist/{persistent-memory-EYAKL2XA.js → persistent-memory-VFBRMKGG.js} +12 -2
- package/dist/{persistent-memory-HWFNDQFQ.js → persistent-memory-ZCQKLIC5.js} +12 -2
- package/dist/{pr-OICMUN6R.js → pr-GIDFO4KP.js} +4 -4
- package/dist/{run-tests-DSEW5HED.js → run-tests-BMH6QJN2.js} +2 -2
- package/dist/{run-tests-B3FSE5NV.js → run-tests-WCZBWQFS.js} +2 -2
- package/dist/{server-2FS65CQZ.js → server-A5NGGDMP.js} +11 -11
- package/dist/{server-EDCGPEGC.js → server-FEFIFJDA.js} +5 -5
- package/dist/{task-orchestrator-WCZYV3TE.js → task-orchestrator-J2H6OV6R.js} +5 -5
- package/dist/{usage-WVUYNLOD.js → usage-7WJC234G.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-X73Y4JZI.js";
|
|
5
5
|
import "./chunk-5ULLIOVC.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-66CE3E6X.js";
|
|
7
7
|
import {
|
|
8
8
|
atomicWriteFileSync
|
|
9
9
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
truncateForPersist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KILKF2VN.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-66CE3E6X.js";
|
|
15
15
|
import {
|
|
16
16
|
atomicWriteFileSync
|
|
17
17
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-QYQI7ZWK.js";
|
|
5
5
|
import {
|
|
6
6
|
ConfigManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-X73Y4JZI.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-EMFCHE2B.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-66CE3E6X.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -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-TY4FSEZS.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-EMFCHE2B.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-L5IRDRWG.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-66CE3E6X.js";
|
|
48
50
|
import {
|
|
49
51
|
loadChatIndex,
|
|
50
52
|
searchChatMemory
|
|
@@ -6576,6 +6578,8 @@ ${lines.join("\n")}`;
|
|
|
6576
6578
|
};
|
|
6577
6579
|
|
|
6578
6580
|
// src/tools/builtin/recall-memory.ts
|
|
6581
|
+
import { join as join8 } from "path";
|
|
6582
|
+
import { homedir as homedir5 } from "os";
|
|
6579
6583
|
function formatHit(h, i) {
|
|
6580
6584
|
const ts = h.chunk.timestamp.slice(0, 16).replace("T", " ");
|
|
6581
6585
|
const title = h.chunk.sessionTitle ? ` \xB7 ${h.chunk.sessionTitle}` : "";
|
|
@@ -6588,7 +6592,7 @@ function formatHit(h, i) {
|
|
|
6588
6592
|
var recallMemoryTool = {
|
|
6589
6593
|
definition: {
|
|
6590
6594
|
name: "recall_memory",
|
|
6591
|
-
description: '
|
|
6595
|
+
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
6596
|
parameters: {
|
|
6593
6597
|
query: {
|
|
6594
6598
|
type: "string",
|
|
@@ -6625,9 +6629,21 @@ var recallMemoryTool = {
|
|
|
6625
6629
|
const excludeCurrent = Boolean(args["excludeCurrentSession"]);
|
|
6626
6630
|
const currentId = args["currentSessionId"] ? String(args["currentSessionId"]) : void 0;
|
|
6627
6631
|
const minScore = args["minScore"] !== void 0 ? Number(args["minScore"]) : 0.25;
|
|
6632
|
+
const configDir = join8(homedir5(), CONFIG_DIR_NAME);
|
|
6633
|
+
let persistentSection = "";
|
|
6634
|
+
try {
|
|
6635
|
+
const persistentHits = searchPersistentMemories(configDir, query, process.cwd(), 3);
|
|
6636
|
+
if (persistentHits.length > 0) {
|
|
6637
|
+
touchMemoryReferences(configDir, persistentHits.map((h) => h.entry.id));
|
|
6638
|
+
persistentSection = `\u2500\u2500 Persistent memory (${persistentHits.length} hit(s)) \u2500\u2500
|
|
6639
|
+
` + persistentHits.map((h) => `[id ${h.entry.id.slice(0, 8)} \xB7 ${h.entry.scope} \xB7 coverage ${h.score.toFixed(2)}]
|
|
6640
|
+
${h.entry.content}`).join("\n\n") + "\n\n";
|
|
6641
|
+
}
|
|
6642
|
+
} catch {
|
|
6643
|
+
}
|
|
6628
6644
|
const status = loadChatIndex();
|
|
6629
6645
|
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.";
|
|
6646
|
+
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
6647
|
}
|
|
6632
6648
|
const hits = await searchChatMemory(query, {
|
|
6633
6649
|
topK,
|
|
@@ -6635,11 +6651,11 @@ var recallMemoryTool = {
|
|
|
6635
6651
|
excludeSessionId: excludeCurrent ? currentId : void 0
|
|
6636
6652
|
});
|
|
6637
6653
|
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.`;
|
|
6654
|
+
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
6655
|
}
|
|
6640
|
-
const header = `Found ${hits.length}
|
|
6656
|
+
const header = `Found ${hits.length} chat-history hit(s) for "${query}" (min-score ${minScore}):
|
|
6641
6657
|
`;
|
|
6642
|
-
return header + "\n" + hits.map(formatHit).join("\n\n");
|
|
6658
|
+
return persistentSection + header + "\n" + hits.map(formatHit).join("\n\n");
|
|
6643
6659
|
}
|
|
6644
6660
|
};
|
|
6645
6661
|
|
|
@@ -6668,7 +6684,7 @@ function estimateToolDefinitionTokens(def) {
|
|
|
6668
6684
|
// src/tools/registry.ts
|
|
6669
6685
|
import { pathToFileURL } from "url";
|
|
6670
6686
|
import { existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync7 } from "fs";
|
|
6671
|
-
import { join as
|
|
6687
|
+
import { join as join9 } from "path";
|
|
6672
6688
|
var ToolRegistry = class {
|
|
6673
6689
|
tools = /* @__PURE__ */ new Map();
|
|
6674
6690
|
pluginToolNames = /* @__PURE__ */ new Set();
|
|
@@ -6855,12 +6871,12 @@ var ToolRegistry = class {
|
|
|
6855
6871
|
process.stderr.write(
|
|
6856
6872
|
`
|
|
6857
6873
|
[plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
|
|
6858
|
-
` + files.map((f) => ` + ${
|
|
6874
|
+
` + files.map((f) => ` + ${join9(pluginsDir, f)}`).join("\n") + "\n\n"
|
|
6859
6875
|
);
|
|
6860
6876
|
let loaded = 0;
|
|
6861
6877
|
for (const file of files) {
|
|
6862
6878
|
try {
|
|
6863
|
-
const fileUrl = pathToFileURL(
|
|
6879
|
+
const fileUrl = pathToFileURL(join9(pluginsDir, file)).href;
|
|
6864
6880
|
const mod = await import(fileUrl);
|
|
6865
6881
|
const tool = mod.tool ?? mod.default?.tool ?? mod.default;
|
|
6866
6882
|
if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
|
|
@@ -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-GEWPLNKA.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
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DJGCG7SF.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-X73Y4JZI.js";
|
|
17
17
|
import {
|
|
18
18
|
VERSION
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-66CE3E6X.js";
|
|
20
20
|
|
|
21
21
|
// src/cli/ci.ts
|
|
22
22
|
import { execFileSync } from "child_process";
|
|
@@ -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-66CE3E6X.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
|
};
|
|
@@ -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-QNK7GUUB.js";
|
|
7
|
+
import "./chunk-DJGCG7SF.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-QYQI7ZWK.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-X73Y4JZI.js";
|
|
11
11
|
import "./chunk-O3XSFPYH.js";
|
|
12
12
|
import "./chunk-5ULLIOVC.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-66CE3E6X.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-HNJX3N2V.js";
|
|
6
6
|
import "./chunk-QYQI7ZWK.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-X73Y4JZI.js";
|
|
8
|
+
import "./chunk-EMFCHE2B.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-66CE3E6X.js";
|
|
13
13
|
import "./chunk-IW3Q7AE5.js";
|
|
14
14
|
export {
|
|
15
15
|
formatDoctorReport,
|