jinzd-ai-cli 0.4.241 → 0.4.242
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/README.md +2 -2
- package/dist/{batch-K66BLTLJ.js → batch-D3UHL432.js} +2 -2
- package/dist/{chat-index-7HXBWQFH.js → chat-index-ALUHFJKI.js} +3 -2
- package/dist/{chat-index-WYXYD7YP.js → chat-index-ML5FF5L6.js} +2 -1
- package/dist/{chunk-NAQPP3GZ.js → chunk-6ZWNXHNH.js} +1 -1
- package/dist/chunk-B5TYJO7V.js +123 -0
- package/dist/chunk-D27TMEOV.js +327 -0
- package/dist/{chunk-2QQKS56X.js → chunk-DT77O33T.js} +1 -1
- package/dist/{chunk-GORPFFV4.js → chunk-FEMPCNX3.js} +79 -252
- package/dist/{chunk-3AIR7N5M.js → chunk-FRNWQIG6.js} +5 -5
- package/dist/{chunk-5MYPIQ3Y.js → chunk-IGPFYNZA.js} +4 -2
- package/dist/{chunk-2LLQOMMW.js → chunk-J363BGOH.js} +1 -1
- package/dist/{chunk-JMP3LJC2.js → chunk-KWQKQVPH.js} +4 -2
- package/dist/{chunk-PGHTAKIA.js → chunk-LHINXQZF.js} +1 -1
- package/dist/{chunk-ZPXMT2B6.js → chunk-MC2ZNPBC.js} +4 -163
- package/dist/chunk-MKLPAQT6.js +164 -0
- package/dist/{chunk-UO3XWZFE.js → chunk-NV63EYFL.js} +3 -119
- package/dist/{chunk-CHFFEVVT.js → chunk-OO2PHOXD.js} +3 -3
- package/dist/{chunk-KCEO2XJ4.js → chunk-PJ3ONBWZ.js} +0 -119
- package/dist/{chunk-LXSUPLCK.js → chunk-PSP6UIKL.js} +2 -2
- package/dist/chunk-UWV2NBCO.js +418 -0
- package/dist/{chunk-IV6GCDVR.js → chunk-WMAXYDCB.js} +7 -1
- package/dist/{chunk-SMQHEJSH.js → chunk-Y4CMNXZH.js} +1 -1
- package/dist/chunk-YVTASHS5.js +121 -0
- package/dist/{ci-T2ABDMMQ.js → ci-WSED3Z6V.js} +4 -4
- package/dist/{ci-format-S2PPU27O.js → ci-format-6AYL2X2J.js} +2 -2
- package/dist/{constants-RS7OUU7X.js → constants-FJ3L5GYO.js} +1 -1
- package/dist/{doctor-cli-TGAW6RAP.js → doctor-cli-HCP56MKH.js} +4 -4
- package/dist/electron-server.js +423 -572
- package/dist/{hub-GL5ZU6WS.js → hub-K5MYSVEF.js} +2 -2
- package/dist/index.js +203 -58
- package/dist/{persist-AMH5SQ4W.js → persist-WGIJ6RXY.js} +4 -3
- package/dist/persistent-memory-EYAKL2XA.js +55 -0
- package/dist/persistent-memory-HWFNDQFQ.js +53 -0
- package/dist/{pr-TJFKUZ4B.js → pr-OICMUN6R.js} +5 -5
- package/dist/{run-tests-EWMU34A4.js → run-tests-B3FSE5NV.js} +2 -1
- package/dist/{run-tests-KEI7IXTB.js → run-tests-DSEW5HED.js} +2 -2
- package/dist/{server-UVS2D4M6.js → server-2FS65CQZ.js} +130 -47
- package/dist/{server-E545UIX7.js → server-EDCGPEGC.js} +8 -6
- package/dist/{task-orchestrator-PWXV2EBN.js → task-orchestrator-WCZYV3TE.js} +8 -6
- package/dist/{usage-EDJ6QOWB.js → usage-WVUYNLOD.js} +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
addMemoryEntry,
|
|
4
|
+
findSimilarMemory,
|
|
5
|
+
loadMemoryEntries,
|
|
6
|
+
parseWritableScope,
|
|
7
|
+
updateMemoryEntry
|
|
8
|
+
} from "./chunk-D27TMEOV.js";
|
|
2
9
|
import {
|
|
3
10
|
indexProject
|
|
4
11
|
} from "./chunk-K3CF65QH.js";
|
|
@@ -14,7 +21,7 @@ import {
|
|
|
14
21
|
runHook,
|
|
15
22
|
runLifecycleHooks,
|
|
16
23
|
runTool
|
|
17
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-J363BGOH.js";
|
|
18
25
|
import {
|
|
19
26
|
getDangerLevel,
|
|
20
27
|
isFileWriteTool,
|
|
@@ -25,33 +32,23 @@ import {
|
|
|
25
32
|
NetworkError,
|
|
26
33
|
ToolError
|
|
27
34
|
} from "./chunk-5ULLIOVC.js";
|
|
28
|
-
import {
|
|
29
|
-
getGitRoot
|
|
30
|
-
} from "./chunk-HOSJZMQS.js";
|
|
31
35
|
import {
|
|
32
36
|
fileCheckpoints
|
|
33
37
|
} from "./chunk-4BKXL7SM.js";
|
|
34
38
|
import {
|
|
35
39
|
runTestsTool
|
|
36
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-6ZWNXHNH.js";
|
|
37
41
|
import {
|
|
38
42
|
CONFIG_DIR_NAME,
|
|
39
43
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
40
|
-
MEMORY_FILE_NAME,
|
|
41
|
-
MEMORY_MAX_CHARS,
|
|
42
|
-
MEMORY_STORE_FILE_NAME,
|
|
43
44
|
SUBAGENT_ALLOWED_TOOLS,
|
|
44
45
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
45
46
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
46
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-Y4CMNXZH.js";
|
|
47
48
|
import {
|
|
48
49
|
loadChatIndex,
|
|
49
50
|
searchChatMemory
|
|
50
|
-
} from "./chunk-
|
|
51
|
-
import {
|
|
52
|
-
DEFAULT_PATTERNS,
|
|
53
|
-
redactString
|
|
54
|
-
} from "./chunk-KCEO2XJ4.js";
|
|
51
|
+
} from "./chunk-IGPFYNZA.js";
|
|
55
52
|
import {
|
|
56
53
|
atomicWriteFileSync
|
|
57
54
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -140,7 +137,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
140
137
|
const markerStart = `AICLI_MARKER_START:${id}`;
|
|
141
138
|
const markerEnd = `AICLI_MARKER_END:${id}`;
|
|
142
139
|
const wrappedCmd = IS_WINDOWS2 ? `${WIN_UTF8_PREAMBLE} echo "${markerStart}"; ${command}; echo "${markerEnd}:0"` : `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
|
|
143
|
-
return new Promise((
|
|
140
|
+
return new Promise((resolve7) => {
|
|
144
141
|
let stdout = "";
|
|
145
142
|
let stderr = "";
|
|
146
143
|
let timedOut = false;
|
|
@@ -156,7 +153,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
156
153
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
157
154
|
resolved = true;
|
|
158
155
|
cleanup();
|
|
159
|
-
|
|
156
|
+
resolve7({ stdout, stderr, exitCode, timedOut, aborted });
|
|
160
157
|
}
|
|
161
158
|
};
|
|
162
159
|
const onErr = (chunk) => {
|
|
@@ -171,7 +168,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
171
168
|
resolved = true;
|
|
172
169
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
173
170
|
cleanup();
|
|
174
|
-
|
|
171
|
+
resolve7({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
175
172
|
try {
|
|
176
173
|
proc.kill();
|
|
177
174
|
} catch {
|
|
@@ -184,7 +181,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
184
181
|
resolved = true;
|
|
185
182
|
cleanup();
|
|
186
183
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
187
|
-
|
|
184
|
+
resolve7({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
188
185
|
try {
|
|
189
186
|
proc.kill();
|
|
190
187
|
} catch {
|
|
@@ -202,7 +199,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
202
199
|
stderr += `
|
|
203
200
|
[pool error] ${err.message}`;
|
|
204
201
|
cleanup();
|
|
205
|
-
|
|
202
|
+
resolve7({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
206
203
|
pool.delete(sessionKey);
|
|
207
204
|
};
|
|
208
205
|
proc.on("error", onError);
|
|
@@ -2540,7 +2537,7 @@ var ToolExecutor = class {
|
|
|
2540
2537
|
rl.resume();
|
|
2541
2538
|
process.stdout.write(prompt);
|
|
2542
2539
|
this.confirming = true;
|
|
2543
|
-
return new Promise((
|
|
2540
|
+
return new Promise((resolve7) => {
|
|
2544
2541
|
let completed = false;
|
|
2545
2542
|
const cleanup = (result) => {
|
|
2546
2543
|
if (completed) return;
|
|
@@ -2550,7 +2547,7 @@ var ToolExecutor = class {
|
|
|
2550
2547
|
rl.pause();
|
|
2551
2548
|
rlAny.output = savedOutput;
|
|
2552
2549
|
this.confirming = false;
|
|
2553
|
-
|
|
2550
|
+
resolve7(result);
|
|
2554
2551
|
};
|
|
2555
2552
|
const onLine = (line) => {
|
|
2556
2553
|
const trimmed = line.trim();
|
|
@@ -2724,7 +2721,7 @@ var ToolExecutor = class {
|
|
|
2724
2721
|
rl.resume();
|
|
2725
2722
|
process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
|
|
2726
2723
|
this.confirming = true;
|
|
2727
|
-
return new Promise((
|
|
2724
|
+
return new Promise((resolve7) => {
|
|
2728
2725
|
let completed = false;
|
|
2729
2726
|
const cleanup = (answer) => {
|
|
2730
2727
|
if (completed) return;
|
|
@@ -2734,7 +2731,7 @@ var ToolExecutor = class {
|
|
|
2734
2731
|
rl.pause();
|
|
2735
2732
|
rlAny.output = savedOutput;
|
|
2736
2733
|
this.confirming = false;
|
|
2737
|
-
|
|
2734
|
+
resolve7(answer === "y");
|
|
2738
2735
|
};
|
|
2739
2736
|
const onLine = (line) => {
|
|
2740
2737
|
const trimmed = line.trim();
|
|
@@ -3983,7 +3980,7 @@ var runInteractiveTool = {
|
|
|
3983
3980
|
PYTHONDONTWRITEBYTECODE: "1"
|
|
3984
3981
|
};
|
|
3985
3982
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
3986
|
-
return new Promise((
|
|
3983
|
+
return new Promise((resolve7) => {
|
|
3987
3984
|
const child = spawn3(executable, cmdArgs.map(String), {
|
|
3988
3985
|
cwd: process.cwd(),
|
|
3989
3986
|
env,
|
|
@@ -4016,22 +4013,22 @@ var runInteractiveTool = {
|
|
|
4016
4013
|
setTimeout(writeNextLine, 400);
|
|
4017
4014
|
const timer = setTimeout(() => {
|
|
4018
4015
|
child.kill();
|
|
4019
|
-
|
|
4016
|
+
resolve7(`${prefixWarnings}[Timeout after ${timeout}ms]
|
|
4020
4017
|
${buildOutput(stdout, stderr)}`);
|
|
4021
4018
|
}, timeout);
|
|
4022
4019
|
child.on("close", (code) => {
|
|
4023
4020
|
clearTimeout(timer);
|
|
4024
4021
|
const output = buildOutput(stdout, stderr);
|
|
4025
4022
|
if (code !== 0 && code !== null) {
|
|
4026
|
-
|
|
4023
|
+
resolve7(`${prefixWarnings}Exit code ${code}:
|
|
4027
4024
|
${output}`);
|
|
4028
4025
|
} else {
|
|
4029
|
-
|
|
4026
|
+
resolve7(`${prefixWarnings}${output || "(no output)"}`);
|
|
4030
4027
|
}
|
|
4031
4028
|
});
|
|
4032
4029
|
child.on("error", (err) => {
|
|
4033
4030
|
clearTimeout(timer);
|
|
4034
|
-
|
|
4031
|
+
resolve7(
|
|
4035
4032
|
`${prefixWarnings}Failed to start process "${executable}": ${err.message}
|
|
4036
4033
|
Hint: On Windows, use the full path to the executable, e.g.:
|
|
4037
4034
|
C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
|
|
@@ -4743,188 +4740,10 @@ Any of these triggers means use save_last_response, NOT write_file:
|
|
|
4743
4740
|
};
|
|
4744
4741
|
|
|
4745
4742
|
// src/tools/builtin/save-memory.ts
|
|
4746
|
-
import { join as
|
|
4743
|
+
import { join as join5 } from "path";
|
|
4747
4744
|
import { homedir as homedir3 } from "os";
|
|
4748
|
-
|
|
4749
|
-
// src/memory/persistent-memory.ts
|
|
4750
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync7 } from "fs";
|
|
4751
|
-
import { randomUUID, createHash } from "crypto";
|
|
4752
|
-
import { dirname as dirname5, join as join5, resolve as resolve6 } from "path";
|
|
4753
|
-
function memoryStorePath(configDir) {
|
|
4754
|
-
return join5(configDir, MEMORY_STORE_FILE_NAME);
|
|
4755
|
-
}
|
|
4756
|
-
function memoryMarkdownPath(configDir) {
|
|
4757
|
-
return join5(configDir, MEMORY_FILE_NAME);
|
|
4758
|
-
}
|
|
4759
|
-
function getProjectKey(cwd = process.cwd()) {
|
|
4760
|
-
return resolve6(getGitRoot(cwd) ?? cwd);
|
|
4761
|
-
}
|
|
4762
|
-
function nowIso() {
|
|
4763
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4764
|
-
}
|
|
4765
|
-
function isValidScope(value) {
|
|
4766
|
-
return value === "personal" || value === "project" || value === "session" || value === "team";
|
|
4767
|
-
}
|
|
4768
|
-
function isValidSensitivity(value) {
|
|
4769
|
-
return value === "low" || value === "medium" || value === "high";
|
|
4770
|
-
}
|
|
4771
|
-
function normalizeEntry(value) {
|
|
4772
|
-
if (!value || typeof value !== "object") return null;
|
|
4773
|
-
const raw = value;
|
|
4774
|
-
const content = typeof raw.content === "string" ? raw.content.trim() : "";
|
|
4775
|
-
if (!content) return null;
|
|
4776
|
-
const createdAt = typeof raw.createdAt === "string" ? raw.createdAt : nowIso();
|
|
4777
|
-
return {
|
|
4778
|
-
id: typeof raw.id === "string" && raw.id ? raw.id : randomUUID(),
|
|
4779
|
-
content,
|
|
4780
|
-
scope: isValidScope(raw.scope) ? raw.scope : "personal",
|
|
4781
|
-
sourceSession: typeof raw.sourceSession === "string" && raw.sourceSession ? raw.sourceSession : void 0,
|
|
4782
|
-
sourceProject: typeof raw.sourceProject === "string" && raw.sourceProject ? raw.sourceProject : void 0,
|
|
4783
|
-
createdAt,
|
|
4784
|
-
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : createdAt,
|
|
4785
|
-
expiresAt: typeof raw.expiresAt === "string" && raw.expiresAt ? raw.expiresAt : void 0,
|
|
4786
|
-
sensitivity: isValidSensitivity(raw.sensitivity) ? raw.sensitivity : "low",
|
|
4787
|
-
approved: raw.approved === true,
|
|
4788
|
-
redactedKinds: Array.isArray(raw.redactedKinds) ? raw.redactedKinds.filter((x) => typeof x === "string") : void 0
|
|
4789
|
-
};
|
|
4790
|
-
}
|
|
4791
|
-
function legacyEntriesFromMarkdown(configDir) {
|
|
4792
|
-
const file = memoryMarkdownPath(configDir);
|
|
4793
|
-
if (!existsSync11(file)) return [];
|
|
4794
|
-
const content = readFileSync7(file, "utf-8").trim();
|
|
4795
|
-
if (!content) return [];
|
|
4796
|
-
const parts = content.split(/\n(?=##\s+\d{4}-\d{2}-\d{2})/g);
|
|
4797
|
-
const chunks = parts.length > 1 ? parts : [content];
|
|
4798
|
-
return chunks.map((chunk, index) => {
|
|
4799
|
-
const match = chunk.match(/^##\s+([^\n]+)\n([\s\S]*)$/);
|
|
4800
|
-
const body = (match ? match[2] : chunk).trim();
|
|
4801
|
-
const parsed = match ? Date.parse(match[1].replace(" ", "T")) : NaN;
|
|
4802
|
-
const createdAt = Number.isFinite(parsed) ? new Date(parsed).toISOString() : nowIso();
|
|
4803
|
-
const id = "legacy-" + createHash("sha1").update(`${index}
|
|
4804
|
-
${chunk}`).digest("hex").slice(0, 12);
|
|
4805
|
-
return normalizeEntry({ id, content: body, scope: "personal", createdAt, updatedAt: createdAt, sensitivity: "low", approved: true });
|
|
4806
|
-
}).filter((entry) => Boolean(entry));
|
|
4807
|
-
}
|
|
4808
|
-
function loadMemoryEntries(configDir) {
|
|
4809
|
-
const file = memoryStorePath(configDir);
|
|
4810
|
-
if (!existsSync11(file)) return legacyEntriesFromMarkdown(configDir);
|
|
4811
|
-
const text = readFileSync7(file, "utf-8").trim();
|
|
4812
|
-
if (!text) return [];
|
|
4813
|
-
const entries = [];
|
|
4814
|
-
for (const line of text.split("\n")) {
|
|
4815
|
-
const trimmed = line.trim();
|
|
4816
|
-
if (!trimmed) continue;
|
|
4817
|
-
try {
|
|
4818
|
-
const entry = normalizeEntry(JSON.parse(trimmed));
|
|
4819
|
-
if (entry) entries.push(entry);
|
|
4820
|
-
} catch {
|
|
4821
|
-
}
|
|
4822
|
-
}
|
|
4823
|
-
return entries;
|
|
4824
|
-
}
|
|
4825
|
-
function saveMemoryEntries(configDir, entries) {
|
|
4826
|
-
mkdirSync3(configDir, { recursive: true });
|
|
4827
|
-
const jsonl = entries.map((entry) => JSON.stringify(entry)).join("\n");
|
|
4828
|
-
atomicWriteFileSync(memoryStorePath(configDir), jsonl ? jsonl + "\n" : "");
|
|
4829
|
-
}
|
|
4830
|
-
function isMemoryExpired(entry, at = /* @__PURE__ */ new Date()) {
|
|
4831
|
-
return Boolean(entry.expiresAt && Date.parse(entry.expiresAt) <= at.getTime());
|
|
4832
|
-
}
|
|
4833
|
-
function isMemoryVisibleInProject(entry, cwd = process.cwd()) {
|
|
4834
|
-
if (entry.scope !== "project") return true;
|
|
4835
|
-
return entry.sourceProject === getProjectKey(cwd);
|
|
4836
|
-
}
|
|
4837
|
-
function listMemoryEntries(configDir, options = {}) {
|
|
4838
|
-
const cwd = options.cwd ?? process.cwd();
|
|
4839
|
-
return loadMemoryEntries(configDir).filter((entry) => options.includeRejected || entry.approved).filter((entry) => options.includeExpired || !isMemoryExpired(entry)).filter((entry) => isMemoryVisibleInProject(entry, cwd));
|
|
4840
|
-
}
|
|
4841
|
-
function addMemoryEntry(configDir, content, options = {}) {
|
|
4842
|
-
const original = content.trim();
|
|
4843
|
-
if (!original) throw new Error("memory content is required");
|
|
4844
|
-
const redact = options.redact ?? true;
|
|
4845
|
-
const redacted = redact ? redactString(original, { enabled: true, patterns: options.patterns ?? DEFAULT_PATTERNS, customRegexes: options.customPatterns }) : { redacted: original, hits: [] };
|
|
4846
|
-
const sensitivity = options.sensitivity ?? (redacted.hits.length > 0 ? "high" : "low");
|
|
4847
|
-
const approved = options.approved ?? (sensitivity === "low" && redacted.hits.length === 0);
|
|
4848
|
-
const scope = options.scope ?? "personal";
|
|
4849
|
-
const timestamp = nowIso();
|
|
4850
|
-
const entry = {
|
|
4851
|
-
id: randomUUID(),
|
|
4852
|
-
content: redacted.redacted.trim(),
|
|
4853
|
-
scope,
|
|
4854
|
-
sourceSession: options.sourceSession,
|
|
4855
|
-
sourceProject: scope === "project" ? getProjectKey(options.cwd) : void 0,
|
|
4856
|
-
createdAt: timestamp,
|
|
4857
|
-
updatedAt: timestamp,
|
|
4858
|
-
expiresAt: options.expiresAt,
|
|
4859
|
-
sensitivity,
|
|
4860
|
-
approved,
|
|
4861
|
-
redactedKinds: [...new Set(redacted.hits.map((hit) => hit.kind))]
|
|
4862
|
-
};
|
|
4863
|
-
const entries = loadMemoryEntries(configDir);
|
|
4864
|
-
entries.push(entry);
|
|
4865
|
-
saveMemoryEntries(configDir, entries);
|
|
4866
|
-
return entry;
|
|
4867
|
-
}
|
|
4868
|
-
function updateMemoryApproval(configDir, idPrefix, approved) {
|
|
4869
|
-
const entries = loadMemoryEntries(configDir);
|
|
4870
|
-
const entry = findUnique(entries, idPrefix);
|
|
4871
|
-
entry.approved = approved;
|
|
4872
|
-
entry.updatedAt = nowIso();
|
|
4873
|
-
saveMemoryEntries(configDir, entries);
|
|
4874
|
-
return entry;
|
|
4875
|
-
}
|
|
4876
|
-
function deleteMemoryEntry(configDir, idPrefix) {
|
|
4877
|
-
const entries = loadMemoryEntries(configDir);
|
|
4878
|
-
const entry = findUnique(entries, idPrefix);
|
|
4879
|
-
saveMemoryEntries(configDir, entries.filter((candidate) => candidate.id !== entry.id));
|
|
4880
|
-
return entry;
|
|
4881
|
-
}
|
|
4882
|
-
function expireMemoryEntry(configDir, idPrefix, expiresAt = nowIso()) {
|
|
4883
|
-
const entries = loadMemoryEntries(configDir);
|
|
4884
|
-
const entry = findUnique(entries, idPrefix);
|
|
4885
|
-
entry.expiresAt = expiresAt;
|
|
4886
|
-
entry.updatedAt = nowIso();
|
|
4887
|
-
saveMemoryEntries(configDir, entries);
|
|
4888
|
-
return entry;
|
|
4889
|
-
}
|
|
4890
|
-
function exportMemoryEntries(configDir, cwd = process.cwd()) {
|
|
4891
|
-
return JSON.stringify(listMemoryEntries(configDir, { cwd, includeExpired: true, includeRejected: true }), null, 2);
|
|
4892
|
-
}
|
|
4893
|
-
function findUnique(entries, idPrefix) {
|
|
4894
|
-
const matches = entries.filter((entry) => entry.id.startsWith(idPrefix));
|
|
4895
|
-
if (matches.length === 0) throw new Error(`memory id not found: ${idPrefix}`);
|
|
4896
|
-
if (matches.length > 1) throw new Error(`memory id is ambiguous: ${idPrefix}`);
|
|
4897
|
-
return matches[0];
|
|
4898
|
-
}
|
|
4899
|
-
function formatMemoryForPrompt(configDir, cwd = process.cwd()) {
|
|
4900
|
-
const entries = listMemoryEntries(configDir, { cwd }).filter((entry) => entry.approved && !isMemoryExpired(entry));
|
|
4901
|
-
if (entries.length === 0) return null;
|
|
4902
|
-
let content = entries.map((entry) => {
|
|
4903
|
-
const source = [
|
|
4904
|
-
`id ${entry.id.slice(0, 8)}`,
|
|
4905
|
-
`scope ${entry.scope}`,
|
|
4906
|
-
entry.sourceSession ? `source session ${entry.sourceSession.slice(0, 8)}` : "source manual/tool",
|
|
4907
|
-
entry.sourceProject ? `project ${entry.sourceProject}` : "",
|
|
4908
|
-
`sensitivity ${entry.sensitivity}`
|
|
4909
|
-
].filter(Boolean).join(" \xB7 ");
|
|
4910
|
-
return `## ${entry.createdAt.replace("T", " ").slice(0, 19)}
|
|
4911
|
-
Source: ${source}
|
|
4912
|
-
${entry.content}`;
|
|
4913
|
-
}).join("\n\n");
|
|
4914
|
-
if (content.length > MEMORY_MAX_CHARS) {
|
|
4915
|
-
content = content.slice(-MEMORY_MAX_CHARS);
|
|
4916
|
-
const firstEntry = content.indexOf("\n## ");
|
|
4917
|
-
if (firstEntry !== -1) content = content.slice(firstEntry + 1);
|
|
4918
|
-
}
|
|
4919
|
-
return { content, entryCount: entries.length };
|
|
4920
|
-
}
|
|
4921
|
-
|
|
4922
|
-
// src/tools/builtin/save-memory.ts
|
|
4923
4745
|
function getConfigDir() {
|
|
4924
|
-
return
|
|
4925
|
-
}
|
|
4926
|
-
function parseScope(value) {
|
|
4927
|
-
return value === "personal" || value === "project" || value === "session" || value === "team" ? value : void 0;
|
|
4746
|
+
return join5(homedir3(), CONFIG_DIR_NAME);
|
|
4928
4747
|
}
|
|
4929
4748
|
function parseSensitivity(value) {
|
|
4930
4749
|
return value === "low" || value === "medium" || value === "high" ? value : void 0;
|
|
@@ -4932,7 +4751,7 @@ function parseSensitivity(value) {
|
|
|
4932
4751
|
var saveMemoryTool = {
|
|
4933
4752
|
definition: {
|
|
4934
4753
|
name: "save_memory",
|
|
4935
|
-
description: "Save important information to governed persistent memory.
|
|
4754
|
+
description: "Save important information to governed persistent memory. Entries saved by this tool are stored as PENDING and only take effect after the user runs /memory approve <id> \u2014 tell the user the returned id so they can approve it. Use concise entries for user preferences, project decisions, recurring patterns, and key findings.",
|
|
4936
4755
|
parameters: {
|
|
4937
4756
|
content: {
|
|
4938
4757
|
type: "string",
|
|
@@ -4941,7 +4760,7 @@ var saveMemoryTool = {
|
|
|
4941
4760
|
},
|
|
4942
4761
|
scope: {
|
|
4943
4762
|
type: "string",
|
|
4944
|
-
description: "Memory scope: personal
|
|
4763
|
+
description: "Memory scope: personal (default, injected everywhere) or project (only injected inside the current project).",
|
|
4945
4764
|
required: false
|
|
4946
4765
|
},
|
|
4947
4766
|
sensitivity: {
|
|
@@ -4953,6 +4772,11 @@ var saveMemoryTool = {
|
|
|
4953
4772
|
type: "string",
|
|
4954
4773
|
description: "Optional ISO timestamp after which this memory should no longer be injected.",
|
|
4955
4774
|
required: false
|
|
4775
|
+
},
|
|
4776
|
+
updateId: {
|
|
4777
|
+
type: "string",
|
|
4778
|
+
description: "Optional id (or unique id prefix) of an existing memory entry to update in place instead of creating a new one. Use this when a previously saved memory is outdated \u2014 do not save a contradicting duplicate. Updated entries go back to pending and need user re-approval.",
|
|
4779
|
+
required: false
|
|
4956
4780
|
}
|
|
4957
4781
|
},
|
|
4958
4782
|
dangerous: false
|
|
@@ -4960,16 +4784,29 @@ var saveMemoryTool = {
|
|
|
4960
4784
|
async execute(args) {
|
|
4961
4785
|
const content = String(args["content"] ?? "").trim();
|
|
4962
4786
|
if (!content) throw new ToolError("save_memory", "content is required");
|
|
4787
|
+
const updateId = typeof args["updateId"] === "string" ? args["updateId"].trim() : "";
|
|
4788
|
+
if (updateId) {
|
|
4789
|
+
try {
|
|
4790
|
+
const updated = updateMemoryEntry(getConfigDir(), updateId, content, { source: "tool", redact: true });
|
|
4791
|
+
const redactedNote = updated.redactedKinds?.length ? ` Redacted: ${updated.redactedKinds.join(", ")}.` : "";
|
|
4792
|
+
return `Memory ${updated.id.slice(0, 8)} updated (pending approval \u2014 the user must run \`/memory approve ${updated.id.slice(0, 8)}\` before the new content is injected; mention this to the user). scope=${updated.scope} sensitivity=${updated.sensitivity}.${redactedNote}`;
|
|
4793
|
+
} catch (err) {
|
|
4794
|
+
throw new ToolError("save_memory", err instanceof Error ? err.message : String(err));
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4797
|
+
const similar = findSimilarMemory(loadMemoryEntries(getConfigDir()), content);
|
|
4963
4798
|
const entry = addMemoryEntry(getConfigDir(), content, {
|
|
4964
|
-
scope:
|
|
4799
|
+
scope: parseWritableScope(args["scope"]) ?? "personal",
|
|
4800
|
+
source: "tool",
|
|
4965
4801
|
sensitivity: parseSensitivity(args["sensitivity"]),
|
|
4966
4802
|
expiresAt: typeof args["expiresAt"] === "string" ? args["expiresAt"] : void 0,
|
|
4967
4803
|
cwd: process.cwd(),
|
|
4968
4804
|
redact: true
|
|
4969
4805
|
});
|
|
4970
|
-
const status = entry.approved ? "approved and active" :
|
|
4806
|
+
const status = entry.approved ? "approved and active" : `pending approval \u2014 the user must run \`/memory approve ${entry.id.slice(0, 8)}\` before it is injected; mention this to the user`;
|
|
4971
4807
|
const redacted = entry.redactedKinds?.length ? ` Redacted: ${entry.redactedKinds.join(", ")}.` : "";
|
|
4972
|
-
|
|
4808
|
+
const similarNote = similar ? ` Warning: a similar entry already exists (id=${similar.id.slice(0, 8)}) \u2014 next time pass updateId to revise it instead of duplicating.` : "";
|
|
4809
|
+
return `Memory saved (${status}). id=${entry.id.slice(0, 8)} scope=${entry.scope} sensitivity=${entry.sensitivity}.${redacted}${similarNote}`;
|
|
4973
4810
|
}
|
|
4974
4811
|
};
|
|
4975
4812
|
|
|
@@ -5013,7 +4850,7 @@ function promptUser(rl, question) {
|
|
|
5013
4850
|
console.log();
|
|
5014
4851
|
console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
|
|
5015
4852
|
process.stdout.write(chalk4.cyan("> "));
|
|
5016
|
-
return new Promise((
|
|
4853
|
+
return new Promise((resolve7) => {
|
|
5017
4854
|
let completed = false;
|
|
5018
4855
|
const cleanup = (answer) => {
|
|
5019
4856
|
if (completed) return;
|
|
@@ -5023,7 +4860,7 @@ function promptUser(rl, question) {
|
|
|
5023
4860
|
rl.pause();
|
|
5024
4861
|
rlAny.output = savedOutput;
|
|
5025
4862
|
askUserContext.prompting = false;
|
|
5026
|
-
|
|
4863
|
+
resolve7(answer);
|
|
5027
4864
|
};
|
|
5028
4865
|
const onLine = (line) => {
|
|
5029
4866
|
cleanup(line);
|
|
@@ -5255,8 +5092,8 @@ function formatResults2(query, data, _requested) {
|
|
|
5255
5092
|
}
|
|
5256
5093
|
|
|
5257
5094
|
// src/agents/agent-config.ts
|
|
5258
|
-
import { existsSync as
|
|
5259
|
-
import { join as
|
|
5095
|
+
import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync7 } from "fs";
|
|
5096
|
+
import { join as join6 } from "path";
|
|
5260
5097
|
import { homedir as homedir4 } from "os";
|
|
5261
5098
|
var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
|
|
5262
5099
|
"read_file",
|
|
@@ -5351,13 +5188,13 @@ function parseAgentConfig(raw, source, path3) {
|
|
|
5351
5188
|
return cfg;
|
|
5352
5189
|
}
|
|
5353
5190
|
function loadAgentDir(dir, source) {
|
|
5354
|
-
if (!
|
|
5191
|
+
if (!existsSync11(dir)) return [];
|
|
5355
5192
|
const out = [];
|
|
5356
5193
|
for (const file of readdirSync6(dir)) {
|
|
5357
5194
|
if (!file.endsWith(".json")) continue;
|
|
5358
|
-
const path3 =
|
|
5195
|
+
const path3 = join6(dir, file);
|
|
5359
5196
|
try {
|
|
5360
|
-
const parsed = JSON.parse(
|
|
5197
|
+
const parsed = JSON.parse(readFileSync7(path3, "utf-8"));
|
|
5361
5198
|
const cfg = parseAgentConfig(parsed, source, path3);
|
|
5362
5199
|
if (cfg) out.push(cfg);
|
|
5363
5200
|
} catch {
|
|
@@ -5367,8 +5204,8 @@ function loadAgentDir(dir, source) {
|
|
|
5367
5204
|
}
|
|
5368
5205
|
function getAgentDirs(configDir, cwd = process.cwd()) {
|
|
5369
5206
|
return {
|
|
5370
|
-
user:
|
|
5371
|
-
project:
|
|
5207
|
+
user: join6(configDir ?? join6(homedir4(), CONFIG_DIR_NAME), "agents"),
|
|
5208
|
+
project: join6(cwd, CONFIG_DIR_NAME, "agents")
|
|
5372
5209
|
};
|
|
5373
5210
|
}
|
|
5374
5211
|
function listAgentConfigs(configDir, cwd = process.cwd()) {
|
|
@@ -5415,7 +5252,7 @@ var nextId = 1;
|
|
|
5415
5252
|
var preferredAgentName = "worker";
|
|
5416
5253
|
var runs = [];
|
|
5417
5254
|
var MAX_RUNS = 50;
|
|
5418
|
-
function
|
|
5255
|
+
function nowIso() {
|
|
5419
5256
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5420
5257
|
}
|
|
5421
5258
|
function startAgentRun(input) {
|
|
@@ -5424,7 +5261,7 @@ function startAgentRun(input) {
|
|
|
5424
5261
|
agentName: input.agentName,
|
|
5425
5262
|
task: input.task,
|
|
5426
5263
|
status: "running",
|
|
5427
|
-
startedAt:
|
|
5264
|
+
startedAt: nowIso(),
|
|
5428
5265
|
toolNames: [],
|
|
5429
5266
|
agentIndex: input.agentIndex,
|
|
5430
5267
|
stopRequested: false
|
|
@@ -5442,7 +5279,7 @@ function finishAgentRun(runId, status, summary, error) {
|
|
|
5442
5279
|
const run = runs.find((r) => r.id === runId);
|
|
5443
5280
|
if (!run) return;
|
|
5444
5281
|
run.status = status;
|
|
5445
|
-
run.finishedAt =
|
|
5282
|
+
run.finishedAt = nowIso();
|
|
5446
5283
|
if (summary) run.summary = summary;
|
|
5447
5284
|
if (error) run.error = error;
|
|
5448
5285
|
}
|
|
@@ -5868,7 +5705,7 @@ var spawnAgentTool = {
|
|
|
5868
5705
|
|
|
5869
5706
|
// src/tools/builtin/task-manager.ts
|
|
5870
5707
|
import { spawn as spawn4 } from "child_process";
|
|
5871
|
-
import { randomUUID
|
|
5708
|
+
import { randomUUID } from "crypto";
|
|
5872
5709
|
import { platform as platform5 } from "os";
|
|
5873
5710
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
5874
5711
|
var MAX_OUTPUT_BYTES = 64 * 1024;
|
|
@@ -5901,7 +5738,7 @@ function createTask(command, description) {
|
|
|
5901
5738
|
}
|
|
5902
5739
|
}
|
|
5903
5740
|
}
|
|
5904
|
-
const id =
|
|
5741
|
+
const id = randomUUID().slice(0, 8);
|
|
5905
5742
|
const { shell, args } = shellInvocation(command);
|
|
5906
5743
|
const proc = spawn4(shell, args, {
|
|
5907
5744
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -6083,14 +5920,14 @@ var taskStopTool = {
|
|
|
6083
5920
|
|
|
6084
5921
|
// src/tools/builtin/git-tools.ts
|
|
6085
5922
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
6086
|
-
import { existsSync as
|
|
6087
|
-
import { join as
|
|
5923
|
+
import { existsSync as existsSync12 } from "fs";
|
|
5924
|
+
import { join as join7 } from "path";
|
|
6088
5925
|
function assertGitRepo(cwd) {
|
|
6089
5926
|
let dir = cwd;
|
|
6090
5927
|
const root = dir.split(/[\\/]/)[0] + (dir.includes("\\") ? "\\" : "/");
|
|
6091
5928
|
while (dir && dir !== root) {
|
|
6092
|
-
if (
|
|
6093
|
-
const parent =
|
|
5929
|
+
if (existsSync12(join7(dir, ".git"))) return;
|
|
5930
|
+
const parent = join7(dir, "..");
|
|
6094
5931
|
if (parent === dir) break;
|
|
6095
5932
|
dir = parent;
|
|
6096
5933
|
}
|
|
@@ -6355,9 +6192,9 @@ ${commitOutput.trim()}`;
|
|
|
6355
6192
|
};
|
|
6356
6193
|
|
|
6357
6194
|
// src/tools/builtin/notebook-edit.ts
|
|
6358
|
-
import { readFileSync as
|
|
6195
|
+
import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
|
|
6359
6196
|
import { writeFile } from "fs/promises";
|
|
6360
|
-
import { resolve as
|
|
6197
|
+
import { resolve as resolve6, extname as extname2 } from "path";
|
|
6361
6198
|
var notebookEditTool = {
|
|
6362
6199
|
definition: {
|
|
6363
6200
|
name: "notebook_edit",
|
|
@@ -6406,14 +6243,14 @@ var notebookEditTool = {
|
|
|
6406
6243
|
if (!Number.isInteger(cellIndexRaw) || cellIndexRaw < 1) {
|
|
6407
6244
|
throw new ToolError("notebook_edit", "cell_index must be a positive integer (1-based)");
|
|
6408
6245
|
}
|
|
6409
|
-
const absPath =
|
|
6246
|
+
const absPath = resolve6(filePath);
|
|
6410
6247
|
if (extname2(absPath).toLowerCase() !== ".ipynb") {
|
|
6411
6248
|
throw new ToolError("notebook_edit", "path must point to a .ipynb file");
|
|
6412
6249
|
}
|
|
6413
|
-
if (!
|
|
6250
|
+
if (!existsSync13(absPath)) {
|
|
6414
6251
|
throw new ToolError("notebook_edit", `Notebook not found: ${filePath}`);
|
|
6415
6252
|
}
|
|
6416
|
-
const raw =
|
|
6253
|
+
const raw = readFileSync8(absPath, "utf-8");
|
|
6417
6254
|
const nb = parseNotebook(raw);
|
|
6418
6255
|
const cellIdx0 = cellIndexRaw - 1;
|
|
6419
6256
|
undoStack.push(absPath, `notebook_edit (${action}): ${filePath}`);
|
|
@@ -6830,8 +6667,8 @@ function estimateToolDefinitionTokens(def) {
|
|
|
6830
6667
|
|
|
6831
6668
|
// src/tools/registry.ts
|
|
6832
6669
|
import { pathToFileURL } from "url";
|
|
6833
|
-
import { existsSync as
|
|
6834
|
-
import { join as
|
|
6670
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync7 } from "fs";
|
|
6671
|
+
import { join as join8 } from "path";
|
|
6835
6672
|
var ToolRegistry = class {
|
|
6836
6673
|
tools = /* @__PURE__ */ new Map();
|
|
6837
6674
|
pluginToolNames = /* @__PURE__ */ new Set();
|
|
@@ -6992,9 +6829,9 @@ var ToolRegistry = class {
|
|
|
6992
6829
|
* Returns the number of successfully loaded plugins.
|
|
6993
6830
|
*/
|
|
6994
6831
|
async loadPlugins(pluginsDir, allowPlugins = false) {
|
|
6995
|
-
if (!
|
|
6832
|
+
if (!existsSync14(pluginsDir)) {
|
|
6996
6833
|
try {
|
|
6997
|
-
|
|
6834
|
+
mkdirSync3(pluginsDir, { recursive: true });
|
|
6998
6835
|
} catch {
|
|
6999
6836
|
}
|
|
7000
6837
|
return 0;
|
|
@@ -7018,12 +6855,12 @@ var ToolRegistry = class {
|
|
|
7018
6855
|
process.stderr.write(
|
|
7019
6856
|
`
|
|
7020
6857
|
[plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
|
|
7021
|
-
` + files.map((f) => ` + ${
|
|
6858
|
+
` + files.map((f) => ` + ${join8(pluginsDir, f)}`).join("\n") + "\n\n"
|
|
7022
6859
|
);
|
|
7023
6860
|
let loaded = 0;
|
|
7024
6861
|
for (const file of files) {
|
|
7025
6862
|
try {
|
|
7026
|
-
const fileUrl = pathToFileURL(
|
|
6863
|
+
const fileUrl = pathToFileURL(join8(pluginsDir, file)).href;
|
|
7027
6864
|
const mod = await import(fileUrl);
|
|
7028
6865
|
const tool = mod.tool ?? mod.default?.tool ?? mod.default;
|
|
7029
6866
|
if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
|
|
@@ -7056,16 +6893,6 @@ export {
|
|
|
7056
6893
|
theme,
|
|
7057
6894
|
undoStack,
|
|
7058
6895
|
renderDiff,
|
|
7059
|
-
memoryStorePath,
|
|
7060
|
-
memoryMarkdownPath,
|
|
7061
|
-
isMemoryExpired,
|
|
7062
|
-
listMemoryEntries,
|
|
7063
|
-
addMemoryEntry,
|
|
7064
|
-
updateMemoryApproval,
|
|
7065
|
-
deleteMemoryEntry,
|
|
7066
|
-
expireMemoryEntry,
|
|
7067
|
-
exportMemoryEntries,
|
|
7068
|
-
formatMemoryForPrompt,
|
|
7069
6896
|
recordRecentlyDeniedAutoAction,
|
|
7070
6897
|
getRecentlyDeniedAutoActions,
|
|
7071
6898
|
clearRecentlyDeniedAutoActions,
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ProviderRegistry
|
|
4
4
|
} from "./chunk-QYQI7ZWK.js";
|
|
5
|
+
import {
|
|
6
|
+
ConfigManager
|
|
7
|
+
} from "./chunk-WMAXYDCB.js";
|
|
5
8
|
import {
|
|
6
9
|
getActivePluginAssets,
|
|
7
10
|
getPendingHookTrust,
|
|
@@ -11,10 +14,7 @@ import {
|
|
|
11
14
|
listHooks,
|
|
12
15
|
listInstalledPlugins,
|
|
13
16
|
resetStats
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import {
|
|
16
|
-
ConfigManager
|
|
17
|
-
} from "./chunk-IV6GCDVR.js";
|
|
17
|
+
} from "./chunk-J363BGOH.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-Y4CMNXZH.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -5,9 +5,11 @@ import {
|
|
|
5
5
|
embedOne
|
|
6
6
|
} from "./chunk-KHYD3WXE.js";
|
|
7
7
|
import {
|
|
8
|
-
getIndexMtimeMap
|
|
8
|
+
getIndexMtimeMap
|
|
9
|
+
} from "./chunk-PJ3ONBWZ.js";
|
|
10
|
+
import {
|
|
9
11
|
redactString
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-B5TYJO7V.js";
|
|
11
13
|
import {
|
|
12
14
|
atomicWriteFileSync
|
|
13
15
|
} from "./chunk-IW3Q7AE5.js";
|