jinzd-ai-cli 0.4.216 → 0.4.217
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 +3 -2
- package/dist/{batch-C6HCXZIG.js → batch-YCOVKTXD.js} +2 -2
- package/dist/{chat-index-R2E27VXN.js → chat-index-PS274XM7.js} +1 -1
- package/dist/{chunk-6HLKCSB3.js → chunk-524WZOKS.js} +1 -1
- package/dist/{chunk-GY3C3C2Y.js → chunk-KOPUCJXM.js} +3 -3
- package/dist/{chunk-TCOC4AUI.js → chunk-MGBMNCHG.js} +279 -54
- package/dist/{chunk-PNTLA3MN.js → chunk-OUAZOE5U.js} +2 -2
- package/dist/{chunk-OLN7VUZA.js → chunk-QAYOI57M.js} +3 -1
- package/dist/{chunk-77HDCGTN.js → chunk-SNJAOXFT.js} +1 -1
- package/dist/{chunk-OQGVGPEK.js → chunk-VHY6NVMQ.js} +2 -0
- package/dist/{chunk-VW7Y27WW.js → chunk-VTH7BLXK.js} +1 -1
- package/dist/{chunk-WAI3WPV2.js → chunk-WKOQ5CYC.js} +1 -1
- package/dist/{chunk-TJ6GGN4B.js → chunk-WZ3VKLF3.js} +1 -1
- package/dist/{chunk-7YWS3JLU.js → chunk-XJGEQIYS.js} +3 -1
- package/dist/{ci-6ZTFO3LX.js → ci-52RZIYWB.js} +4 -4
- package/dist/{ci-format-CLZ6QJRL.js → ci-format-73UXKE65.js} +2 -2
- package/dist/{constants-APSORFOH.js → constants-DIXAD35W.js} +3 -1
- package/dist/{doctor-cli-GUIX4X5F.js → doctor-cli-7GOQPULZ.js} +4 -4
- package/dist/electron-server.js +562 -318
- package/dist/{hub-ZGHQWNWE.js → hub-GIGBITZN.js} +1 -1
- package/dist/index.js +129 -69
- package/dist/{pr-JOL3IAGV.js → pr-KPQ5RPKB.js} +4 -4
- package/dist/{run-tests-4PKSIVK5.js → run-tests-K7QR5QN4.js} +1 -1
- package/dist/{run-tests-ZRK4TQUN.js → run-tests-ZDSA3QES.js} +2 -2
- package/dist/{server-O3XHT56X.js → server-22YF3U34.js} +5 -4
- package/dist/{server-FXUF5P64.js → server-QT3SC2KI.js} +129 -86
- package/dist/{task-orchestrator-TUMDTOAX.js → task-orchestrator-BHQQCVTY.js} +5 -4
- package/dist/{usage-X7MJX4YD.js → usage-WZZFSFLM.js} +2 -2
- package/dist/web/client/app.js +53 -2
- package/dist/web/client/index.html +11 -1
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
scanDirTree,
|
|
25
25
|
scanProject,
|
|
26
26
|
setupProxy
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-OUAZOE5U.js";
|
|
28
28
|
import {
|
|
29
29
|
buildReviewPrompt,
|
|
30
30
|
buildSecurityReviewPrompt
|
|
@@ -32,21 +32,29 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
ToolExecutor,
|
|
34
34
|
ToolRegistry,
|
|
35
|
+
addMemoryEntry,
|
|
35
36
|
askUserContext,
|
|
36
37
|
checkNetworkPolicy,
|
|
37
38
|
checkPermissionWithProfile,
|
|
38
39
|
cleanupRejectedTeeFile,
|
|
39
40
|
clearRecentlyDeniedAutoActions,
|
|
40
41
|
defaultActionClassifier,
|
|
42
|
+
deleteMemoryEntry,
|
|
41
43
|
estimateTokens,
|
|
44
|
+
expireMemoryEntry,
|
|
45
|
+
exportMemoryEntries,
|
|
46
|
+
formatMemoryForPrompt,
|
|
42
47
|
formatPermissionProfileWarning,
|
|
43
48
|
getPendingHookTrust,
|
|
44
49
|
getPreferredAgentName,
|
|
45
50
|
getRecentlyDeniedAutoActions,
|
|
46
51
|
googleSearchContext,
|
|
47
52
|
groupCallsByPhase,
|
|
53
|
+
isMemoryExpired,
|
|
48
54
|
listAgentConfigs,
|
|
49
55
|
listAgentRuns,
|
|
56
|
+
listMemoryEntries,
|
|
57
|
+
memoryStorePath,
|
|
50
58
|
recordRecentlyDeniedAutoAction,
|
|
51
59
|
renderDiff,
|
|
52
60
|
requestAgentStop,
|
|
@@ -60,11 +68,12 @@ import {
|
|
|
60
68
|
setPreferredAgentName,
|
|
61
69
|
spawnAgentContext,
|
|
62
70
|
truncateOutput,
|
|
63
|
-
undoStack
|
|
64
|
-
|
|
71
|
+
undoStack,
|
|
72
|
+
updateMemoryApproval
|
|
73
|
+
} from "./chunk-MGBMNCHG.js";
|
|
65
74
|
import "./chunk-T2NL5ZIA.js";
|
|
66
75
|
import "./chunk-BXP6YZ2P.js";
|
|
67
|
-
import "./chunk-
|
|
76
|
+
import "./chunk-VTH7BLXK.js";
|
|
68
77
|
import {
|
|
69
78
|
SessionManager,
|
|
70
79
|
getContentText
|
|
@@ -78,7 +87,7 @@ import {
|
|
|
78
87
|
} from "./chunk-QMXC327F.js";
|
|
79
88
|
import {
|
|
80
89
|
runTool
|
|
81
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-SNJAOXFT.js";
|
|
82
91
|
import {
|
|
83
92
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
84
93
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -97,7 +106,7 @@ import {
|
|
|
97
106
|
} from "./chunk-XPBEJB27.js";
|
|
98
107
|
import {
|
|
99
108
|
ConfigManager
|
|
100
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-WKOQ5CYC.js";
|
|
101
110
|
import "./chunk-TZQHYZKT.js";
|
|
102
111
|
import {
|
|
103
112
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -109,14 +118,13 @@ import {
|
|
|
109
118
|
DESCRIPTION,
|
|
110
119
|
MCP_PROJECT_CONFIG_NAME,
|
|
111
120
|
MEMORY_FILE_NAME,
|
|
112
|
-
MEMORY_MAX_CHARS,
|
|
113
121
|
PLAN_MODE_READONLY_TOOLS,
|
|
114
122
|
PLAN_MODE_SYSTEM_ADDON,
|
|
115
123
|
PLUGINS_DIR_NAME,
|
|
116
124
|
SKILLS_DIR_NAME,
|
|
117
125
|
VERSION,
|
|
118
126
|
buildUserIdentityPrompt
|
|
119
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-XJGEQIYS.js";
|
|
120
128
|
import {
|
|
121
129
|
formatGitContextForPrompt,
|
|
122
130
|
getGitContext,
|
|
@@ -138,8 +146,8 @@ import {
|
|
|
138
146
|
import express from "express";
|
|
139
147
|
import { createServer } from "http";
|
|
140
148
|
import { WebSocketServer } from "ws";
|
|
141
|
-
import { join as
|
|
142
|
-
import { existsSync as
|
|
149
|
+
import { join as join2, dirname as dirname2, resolve as resolve2, relative, sep } from "path";
|
|
150
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2, realpathSync } from "fs";
|
|
143
151
|
import { networkInterfaces } from "os";
|
|
144
152
|
|
|
145
153
|
// src/web/tool-executor-web.ts
|
|
@@ -589,8 +597,6 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
589
597
|
};
|
|
590
598
|
|
|
591
599
|
// src/core/system-prompt-builder.ts
|
|
592
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
593
|
-
import { join } from "path";
|
|
594
600
|
function buildSystemPromptParts(ctx) {
|
|
595
601
|
const now = /* @__PURE__ */ new Date();
|
|
596
602
|
const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
@@ -644,24 +650,12 @@ ${ctx.activeSkill.content}`);
|
|
|
644
650
|
return { stable: stableParts.join("\n\n---\n\n"), volatile };
|
|
645
651
|
}
|
|
646
652
|
function loadMemoryContent(configDir) {
|
|
647
|
-
|
|
648
|
-
if (!existsSync2(memoryPath)) return null;
|
|
649
|
-
let content = readFileSync2(memoryPath, "utf-8").trim();
|
|
650
|
-
if (!content) return null;
|
|
651
|
-
if (content.length > MEMORY_MAX_CHARS) {
|
|
652
|
-
content = content.slice(-MEMORY_MAX_CHARS);
|
|
653
|
-
const firstEntry = content.indexOf("\n## ");
|
|
654
|
-
if (firstEntry !== -1) {
|
|
655
|
-
content = content.slice(firstEntry + 1);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
const entryCount = (content.match(/^## \d{4}-\d{2}-\d{2}/gm) ?? []).length;
|
|
659
|
-
return { content, entryCount };
|
|
653
|
+
return formatMemoryForPrompt(configDir, process.cwd());
|
|
660
654
|
}
|
|
661
655
|
|
|
662
656
|
// src/web/session-handler.ts
|
|
663
|
-
import { existsSync as
|
|
664
|
-
import { join
|
|
657
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync, readdirSync, statSync, createWriteStream } from "fs";
|
|
658
|
+
import { join, resolve, dirname } from "path";
|
|
665
659
|
function lastAssistantText(messages) {
|
|
666
660
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
667
661
|
const m = messages[i];
|
|
@@ -867,6 +861,8 @@ var SessionHandler = class {
|
|
|
867
861
|
return this.handleMemoryStatus();
|
|
868
862
|
case "memory_rebuild":
|
|
869
863
|
return this.handleMemoryRebuild(Boolean(msg.full));
|
|
864
|
+
case "memory_manage":
|
|
865
|
+
return this.handleMemoryManage(msg.action, msg.id, msg.expiresAt);
|
|
870
866
|
case "auto_pause_response": {
|
|
871
867
|
const resolve3 = this.pendingAutoPause.get(msg.requestId);
|
|
872
868
|
if (resolve3) {
|
|
@@ -2237,9 +2233,9 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2237
2233
|
let modifiedFiles = 0;
|
|
2238
2234
|
const diffLines = [];
|
|
2239
2235
|
for (const [filePath, { earliest }] of fileMap) {
|
|
2240
|
-
const currentContent =
|
|
2236
|
+
const currentContent = existsSync2(filePath) ? (() => {
|
|
2241
2237
|
try {
|
|
2242
|
-
return
|
|
2238
|
+
return readFileSync2(filePath, "utf-8");
|
|
2243
2239
|
} catch {
|
|
2244
2240
|
return null;
|
|
2245
2241
|
}
|
|
@@ -2755,7 +2751,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2755
2751
|
case "test": {
|
|
2756
2752
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2757
2753
|
try {
|
|
2758
|
-
const { executeTests } = await import("./run-tests-
|
|
2754
|
+
const { executeTests } = await import("./run-tests-ZDSA3QES.js");
|
|
2759
2755
|
const argStr = args.join(" ").trim();
|
|
2760
2756
|
let testArgs = {};
|
|
2761
2757
|
if (argStr) {
|
|
@@ -2772,9 +2768,9 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2772
2768
|
// ── /init ───────────────────────────────────────────────────────
|
|
2773
2769
|
case "init": {
|
|
2774
2770
|
const cwd = process.cwd();
|
|
2775
|
-
const targetPath =
|
|
2771
|
+
const targetPath = join(cwd, "AICLI.md");
|
|
2776
2772
|
const force = args.includes("--force");
|
|
2777
|
-
if (
|
|
2773
|
+
if (existsSync2(targetPath) && !force) {
|
|
2778
2774
|
this.send({ type: "info", message: `AICLI.md already exists at ${targetPath}
|
|
2779
2775
|
Use /init --force to overwrite.` });
|
|
2780
2776
|
break;
|
|
@@ -2807,7 +2803,7 @@ Use /context reload to load it.` });
|
|
|
2807
2803
|
lines.push("**Config Files:**");
|
|
2808
2804
|
lines.push(` Dir: ${configDir}`);
|
|
2809
2805
|
const checkFile = (label, filePath) => {
|
|
2810
|
-
const exists =
|
|
2806
|
+
const exists = existsSync2(filePath);
|
|
2811
2807
|
let extra = "";
|
|
2812
2808
|
if (exists) {
|
|
2813
2809
|
try {
|
|
@@ -2817,9 +2813,9 @@ Use /context reload to load it.` });
|
|
|
2817
2813
|
}
|
|
2818
2814
|
lines.push(` ${exists ? "\u2713" : "\u2013"} ${label.padEnd(14)} ${exists ? filePath + extra : "(not found)"}`);
|
|
2819
2815
|
};
|
|
2820
|
-
checkFile("config.json",
|
|
2821
|
-
checkFile("memory.md",
|
|
2822
|
-
checkFile("dev-state.md",
|
|
2816
|
+
checkFile("config.json", join(configDir, "config.json"));
|
|
2817
|
+
checkFile("memory.md", join(configDir, MEMORY_FILE_NAME));
|
|
2818
|
+
checkFile("dev-state.md", join(configDir, "dev-state.md"));
|
|
2823
2819
|
lines.push("");
|
|
2824
2820
|
if (this.mcpManager) {
|
|
2825
2821
|
lines.push("**MCP Servers:**");
|
|
@@ -3007,7 +3003,7 @@ Use /add-dir remove to clear.` : "No directories added.\nUsage: /add-dir <path>
|
|
|
3007
3003
|
break;
|
|
3008
3004
|
}
|
|
3009
3005
|
const dirPath = resolve(sub);
|
|
3010
|
-
if (!
|
|
3006
|
+
if (!existsSync2(dirPath)) {
|
|
3011
3007
|
this.send({ type: "error", message: `Directory not found: ${dirPath}` });
|
|
3012
3008
|
break;
|
|
3013
3009
|
}
|
|
@@ -3023,8 +3019,8 @@ It will be included in AI context for subsequent messages.` });
|
|
|
3023
3019
|
// ── /commands ───────────────────────────────────────────────────
|
|
3024
3020
|
case "commands": {
|
|
3025
3021
|
const configDir = this.config.getConfigDir();
|
|
3026
|
-
const commandsDir =
|
|
3027
|
-
if (!
|
|
3022
|
+
const commandsDir = join(configDir, CUSTOM_COMMANDS_DIR_NAME);
|
|
3023
|
+
if (!existsSync2(commandsDir)) {
|
|
3028
3024
|
this.send({ type: "info", message: `No custom commands directory.
|
|
3029
3025
|
Create: ${commandsDir}/ with .md files.` });
|
|
3030
3026
|
break;
|
|
@@ -3050,7 +3046,7 @@ Add .md files to create commands.` });
|
|
|
3050
3046
|
// ── /plugins ────────────────────────────────────────────────────
|
|
3051
3047
|
case "plugins": {
|
|
3052
3048
|
const configDir = this.config.getConfigDir();
|
|
3053
|
-
const pluginsDir =
|
|
3049
|
+
const pluginsDir = join(configDir, PLUGINS_DIR_NAME);
|
|
3054
3050
|
const pluginTools = this.toolRegistry.listPluginTools();
|
|
3055
3051
|
const lines = [`\u{1F50C} **Plugins:**`, `Dir: ${pluginsDir}`, ""];
|
|
3056
3052
|
if (pluginTools.length === 0) {
|
|
@@ -3247,48 +3243,95 @@ Add .md files to create commands.` });
|
|
|
3247
3243
|
}
|
|
3248
3244
|
memoryShow() {
|
|
3249
3245
|
const configDir = this.config.getConfigDir();
|
|
3250
|
-
const
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
`);
|
|
3259
|
-
}
|
|
3246
|
+
const entries = listMemoryEntries(configDir, { includeExpired: true, includeRejected: true });
|
|
3247
|
+
const content = entries.length === 0 ? "(empty \u2014 no persistent memory entries yet)" : entries.map((entry) => {
|
|
3248
|
+
const status = isMemoryExpired(entry) ? "expired" : entry.approved ? "approved" : "pending";
|
|
3249
|
+
const source = entry.sourceSession ? `session ${entry.sourceSession.slice(0, 8)}` : entry.sourceProject ? `project ${entry.sourceProject}` : "manual/tool";
|
|
3250
|
+
return `## ${entry.id.slice(0, 8)} \xB7 ${status} \xB7 scope:${entry.scope} \xB7 sensitivity:${entry.sensitivity}
|
|
3251
|
+
Source: ${source}
|
|
3252
|
+
${entry.content}`;
|
|
3253
|
+
}).join("\n\n");
|
|
3260
3254
|
this.send({
|
|
3261
3255
|
type: "memory_content",
|
|
3262
|
-
content
|
|
3263
|
-
filePath:
|
|
3256
|
+
content,
|
|
3257
|
+
filePath: memoryStorePath(configDir)
|
|
3264
3258
|
});
|
|
3259
|
+
this.sendMemoryEntries();
|
|
3265
3260
|
}
|
|
3266
3261
|
memoryAdd(text) {
|
|
3267
|
-
const configDir = this.config.getConfigDir();
|
|
3268
|
-
const memPath = join2(configDir, MEMORY_FILE_NAME);
|
|
3269
3262
|
try {
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
this.
|
|
3263
|
+
const entry = addMemoryEntry(this.config.getConfigDir(), text, {
|
|
3264
|
+
scope: "personal",
|
|
3265
|
+
cwd: process.cwd(),
|
|
3266
|
+
redact: true
|
|
3267
|
+
});
|
|
3268
|
+
const status = entry.approved ? "approved" : "pending approval";
|
|
3269
|
+
this.send({ type: "info", message: `\u{1F4DD} Memory entry ${entry.id.slice(0, 8)} added (${status}).` });
|
|
3270
|
+
this.sendMemoryEntries();
|
|
3278
3271
|
} catch (err) {
|
|
3279
3272
|
this.send({ type: "error", message: `Failed to write memory: ${err.message}` });
|
|
3280
3273
|
}
|
|
3281
3274
|
}
|
|
3282
3275
|
memoryClear() {
|
|
3283
3276
|
const configDir = this.config.getConfigDir();
|
|
3284
|
-
const memPath = join2(configDir, MEMORY_FILE_NAME);
|
|
3285
3277
|
try {
|
|
3286
|
-
atomicWriteFileSync(
|
|
3278
|
+
atomicWriteFileSync(memoryStorePath(configDir), "");
|
|
3279
|
+
atomicWriteFileSync(join(configDir, MEMORY_FILE_NAME), "");
|
|
3287
3280
|
this.send({ type: "info", message: "\u{1F5D1}\uFE0F Persistent memory cleared." });
|
|
3281
|
+
this.sendMemoryEntries();
|
|
3288
3282
|
} catch (err) {
|
|
3289
3283
|
this.send({ type: "error", message: `Failed to clear memory: ${err.message}` });
|
|
3290
3284
|
}
|
|
3291
3285
|
}
|
|
3286
|
+
sendMemoryEntries() {
|
|
3287
|
+
const configDir = this.config.getConfigDir();
|
|
3288
|
+
const entries = listMemoryEntries(configDir, { includeExpired: true, includeRejected: true });
|
|
3289
|
+
this.send({
|
|
3290
|
+
type: "memory_entries",
|
|
3291
|
+
storePath: memoryStorePath(configDir),
|
|
3292
|
+
entries: entries.map((entry) => ({
|
|
3293
|
+
id: entry.id,
|
|
3294
|
+
content: entry.content,
|
|
3295
|
+
scope: entry.scope,
|
|
3296
|
+
sourceSession: entry.sourceSession,
|
|
3297
|
+
sourceProject: entry.sourceProject,
|
|
3298
|
+
createdAt: entry.createdAt,
|
|
3299
|
+
updatedAt: entry.updatedAt,
|
|
3300
|
+
expiresAt: entry.expiresAt,
|
|
3301
|
+
sensitivity: entry.sensitivity,
|
|
3302
|
+
approved: entry.approved,
|
|
3303
|
+
expired: isMemoryExpired(entry),
|
|
3304
|
+
redactedKinds: entry.redactedKinds
|
|
3305
|
+
}))
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
handleMemoryManage(action, id, expiresAt) {
|
|
3309
|
+
const configDir = this.config.getConfigDir();
|
|
3310
|
+
try {
|
|
3311
|
+
if (action === "approve" || action === "reject") {
|
|
3312
|
+
if (!id) throw new Error(`${action} requires id`);
|
|
3313
|
+
updateMemoryApproval(configDir, id, action === "approve");
|
|
3314
|
+
} else if (action === "delete") {
|
|
3315
|
+
if (!id) throw new Error("delete requires id");
|
|
3316
|
+
deleteMemoryEntry(configDir, id);
|
|
3317
|
+
} else if (action === "expire") {
|
|
3318
|
+
if (!id) throw new Error("expire requires id");
|
|
3319
|
+
expireMemoryEntry(configDir, id, expiresAt);
|
|
3320
|
+
} else if (action === "export") {
|
|
3321
|
+
this.send({
|
|
3322
|
+
type: "export_data",
|
|
3323
|
+
format: "json",
|
|
3324
|
+
filename: `aicli-memory-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`,
|
|
3325
|
+
content: exportMemoryEntries(configDir, process.cwd())
|
|
3326
|
+
});
|
|
3327
|
+
} else if (action !== "list") {
|
|
3328
|
+
throw new Error(`unknown memory action: ${action}`);
|
|
3329
|
+
}
|
|
3330
|
+
this.sendMemoryEntries();
|
|
3331
|
+
} catch (err) {
|
|
3332
|
+
this.send({ type: "error", message: `Memory management failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3292
3335
|
// ── B4 chat memory recall (v0.4.90+) ──────────────────────────────
|
|
3293
3336
|
// Lazy-imported so the 117 MB embedder stays out of the load path for
|
|
3294
3337
|
// clients that never open the Memory panel.
|
|
@@ -3578,8 +3621,8 @@ async function startWebServer(options = {}) {
|
|
|
3578
3621
|
}
|
|
3579
3622
|
}
|
|
3580
3623
|
let skillManager = null;
|
|
3581
|
-
const skillsDir =
|
|
3582
|
-
if (
|
|
3624
|
+
const skillsDir = join2(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
3625
|
+
if (existsSync3(skillsDir)) {
|
|
3583
3626
|
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
3584
3627
|
skillManager.loadSkills();
|
|
3585
3628
|
const count = skillManager.listSkills().length;
|
|
@@ -3650,18 +3693,18 @@ async function startWebServer(options = {}) {
|
|
|
3650
3693
|
next();
|
|
3651
3694
|
};
|
|
3652
3695
|
const moduleDir = getModuleDir();
|
|
3653
|
-
let clientDir =
|
|
3654
|
-
if (!
|
|
3655
|
-
clientDir =
|
|
3696
|
+
let clientDir = join2(moduleDir, "web", "client");
|
|
3697
|
+
if (!existsSync3(clientDir)) {
|
|
3698
|
+
clientDir = join2(moduleDir, "client");
|
|
3656
3699
|
}
|
|
3657
|
-
if (!
|
|
3658
|
-
clientDir =
|
|
3700
|
+
if (!existsSync3(clientDir)) {
|
|
3701
|
+
clientDir = join2(moduleDir, "..", "..", "src", "web", "client");
|
|
3659
3702
|
}
|
|
3660
|
-
if (!
|
|
3661
|
-
clientDir =
|
|
3703
|
+
if (!existsSync3(clientDir)) {
|
|
3704
|
+
clientDir = join2(process.cwd(), "src", "web", "client");
|
|
3662
3705
|
}
|
|
3663
3706
|
console.log(` Static files: ${clientDir}`);
|
|
3664
|
-
app.use("/vendor", express.static(
|
|
3707
|
+
app.use("/vendor", express.static(join2(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
|
|
3665
3708
|
app.use(express.static(clientDir));
|
|
3666
3709
|
app.get("/api/status", (_req, res) => {
|
|
3667
3710
|
res.json({
|
|
@@ -3728,7 +3771,7 @@ async function startWebServer(options = {}) {
|
|
|
3728
3771
|
app.get("/api/files", requireAuth, (req, res) => {
|
|
3729
3772
|
const cwd = process.cwd();
|
|
3730
3773
|
const prefix = req.query.prefix || "";
|
|
3731
|
-
const targetDir =
|
|
3774
|
+
const targetDir = join2(cwd, prefix);
|
|
3732
3775
|
try {
|
|
3733
3776
|
const canonicalTarget = realpathSync(resolve2(targetDir));
|
|
3734
3777
|
const canonicalCwd = realpathSync(resolve2(cwd));
|
|
@@ -3745,7 +3788,7 @@ async function startWebServer(options = {}) {
|
|
|
3745
3788
|
const entries = readdirSync2(targetDir, { withFileTypes: true });
|
|
3746
3789
|
const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
|
|
3747
3790
|
name: e.name,
|
|
3748
|
-
path: relative(cwd,
|
|
3791
|
+
path: relative(cwd, join2(targetDir, e.name)).replace(/\\/g, "/"),
|
|
3749
3792
|
isDir: e.isDirectory()
|
|
3750
3793
|
}));
|
|
3751
3794
|
res.json({ files });
|
|
@@ -3781,8 +3824,8 @@ async function startWebServer(options = {}) {
|
|
|
3781
3824
|
try {
|
|
3782
3825
|
const authUser = req._authUser;
|
|
3783
3826
|
const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
|
|
3784
|
-
const filePath =
|
|
3785
|
-
if (!
|
|
3827
|
+
const filePath = join2(histDir, `${id}.json`);
|
|
3828
|
+
if (!existsSync3(filePath)) {
|
|
3786
3829
|
res.status(404).json({ error: "Session not found" });
|
|
3787
3830
|
return;
|
|
3788
3831
|
}
|
|
@@ -3797,7 +3840,7 @@ async function startWebServer(options = {}) {
|
|
|
3797
3840
|
res.status(404).json({ error: "Session not found" });
|
|
3798
3841
|
return;
|
|
3799
3842
|
}
|
|
3800
|
-
const data = JSON.parse(
|
|
3843
|
+
const data = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
3801
3844
|
res.json({ session: data });
|
|
3802
3845
|
} catch (err) {
|
|
3803
3846
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
@@ -3810,7 +3853,7 @@ async function startWebServer(options = {}) {
|
|
|
3810
3853
|
return;
|
|
3811
3854
|
}
|
|
3812
3855
|
const cwd = process.cwd();
|
|
3813
|
-
const fullPath = resolve2(
|
|
3856
|
+
const fullPath = resolve2(join2(cwd, filePath));
|
|
3814
3857
|
try {
|
|
3815
3858
|
const canonicalFull = realpathSync(fullPath);
|
|
3816
3859
|
const canonicalCwd = realpathSync(resolve2(cwd));
|
|
@@ -3828,7 +3871,7 @@ async function startWebServer(options = {}) {
|
|
|
3828
3871
|
res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
|
|
3829
3872
|
return;
|
|
3830
3873
|
}
|
|
3831
|
-
const content =
|
|
3874
|
+
const content = readFileSync3(fullPath, "utf-8");
|
|
3832
3875
|
res.json({ content, size: stat.size });
|
|
3833
3876
|
} catch {
|
|
3834
3877
|
res.json({ error: "Cannot read file" });
|
|
@@ -4083,17 +4126,17 @@ function resolveProjectMcpPath() {
|
|
|
4083
4126
|
const cwd = process.cwd();
|
|
4084
4127
|
const gitRoot = getGitRoot(cwd);
|
|
4085
4128
|
const projectRoot = gitRoot ?? cwd;
|
|
4086
|
-
const configPath =
|
|
4087
|
-
return
|
|
4129
|
+
const configPath = join2(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
4130
|
+
return existsSync3(configPath) ? configPath : null;
|
|
4088
4131
|
}
|
|
4089
4132
|
function loadProjectMcpConfig() {
|
|
4090
4133
|
const cwd = process.cwd();
|
|
4091
4134
|
const gitRoot = getGitRoot(cwd);
|
|
4092
4135
|
const projectRoot = gitRoot ?? cwd;
|
|
4093
|
-
const configPath =
|
|
4094
|
-
if (!
|
|
4136
|
+
const configPath = join2(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
4137
|
+
if (!existsSync3(configPath)) return null;
|
|
4095
4138
|
try {
|
|
4096
|
-
const raw = JSON.parse(
|
|
4139
|
+
const raw = JSON.parse(readFileSync3(configPath, "utf-8"));
|
|
4097
4140
|
return raw.mcpServers ?? raw;
|
|
4098
4141
|
} catch {
|
|
4099
4142
|
return null;
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
googleSearchContext,
|
|
5
5
|
truncateOutput
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MGBMNCHG.js";
|
|
7
7
|
import "./chunk-T2NL5ZIA.js";
|
|
8
8
|
import "./chunk-BXP6YZ2P.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-VTH7BLXK.js";
|
|
10
10
|
import {
|
|
11
11
|
runTool
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-SNJAOXFT.js";
|
|
13
13
|
import {
|
|
14
14
|
getDangerLevel,
|
|
15
15
|
runLeanAgentLoop
|
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
import "./chunk-TZQHYZKT.js";
|
|
18
18
|
import {
|
|
19
19
|
SUBAGENT_ALLOWED_TOOLS
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XJGEQIYS.js";
|
|
21
|
+
import "./chunk-HOSJZMQS.js";
|
|
21
22
|
import "./chunk-4BKXL7SM.js";
|
|
22
23
|
import "./chunk-TB4W4Y4T.js";
|
|
23
24
|
import "./chunk-KHYD3WXE.js";
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-E44DTERW.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigManager
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WKOQ5CYC.js";
|
|
12
12
|
import "./chunk-TZQHYZKT.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-XJGEQIYS.js";
|
|
14
14
|
import "./chunk-IW3Q7AE5.js";
|
|
15
15
|
|
|
16
16
|
// src/cli/usage.ts
|
package/dist/web/client/app.js
CHANGED
|
@@ -200,6 +200,7 @@ function handleServerMessage(msg) {
|
|
|
200
200
|
case 'tools_list': renderToolsList(msg); switchSidebarTab('tools'); break;
|
|
201
201
|
case 'export_data': handleExportData(msg); break;
|
|
202
202
|
case 'memory_content': handleMemoryContent(msg); break;
|
|
203
|
+
case 'memory_entries': renderMemoryEntries(msg); break;
|
|
203
204
|
case 'memory_hits': renderMemoryHits(msg); break;
|
|
204
205
|
case 'memory_status': renderMemoryStatus(msg); break;
|
|
205
206
|
case 'memory_rebuild_progress': renderMemoryRebuildProgress(msg); break;
|
|
@@ -2943,7 +2944,9 @@ function initMemoryPanel() {
|
|
|
2943
2944
|
const input = document.getElementById('memory-search-input');
|
|
2944
2945
|
const btnSearch = document.getElementById('btn-memory-search');
|
|
2945
2946
|
const btnRefresh = document.getElementById('btn-memory-refresh');
|
|
2946
|
-
const btnRebuild = document.getElementById('btn-memory-rebuild');
|
|
2947
|
+
const btnRebuild = document.getElementById('btn-memory-rebuild');
|
|
2948
|
+
const btnManagedRefresh = document.getElementById('btn-memory-managed-refresh');
|
|
2949
|
+
const btnManagedExport = document.getElementById('btn-memory-managed-export');
|
|
2947
2950
|
|
|
2948
2951
|
const runSearch = () => {
|
|
2949
2952
|
const q = (input?.value || '').trim();
|
|
@@ -2978,7 +2981,11 @@ function initMemoryPanel() {
|
|
|
2978
2981
|
send({ type: 'memory_rebuild', full: true });
|
|
2979
2982
|
});
|
|
2980
2983
|
|
|
2981
|
-
send({ type: '
|
|
2984
|
+
btnManagedRefresh?.addEventListener('click', () => send({ type: 'memory_manage', action: 'list' }));
|
|
2985
|
+
btnManagedExport?.addEventListener('click', () => send({ type: 'memory_manage', action: 'export' }));
|
|
2986
|
+
|
|
2987
|
+
send({ type: 'memory_status_request' });
|
|
2988
|
+
send({ type: 'memory_manage', action: 'list' });
|
|
2982
2989
|
}
|
|
2983
2990
|
|
|
2984
2991
|
function renderMemoryStatus(msg) {
|
|
@@ -2997,6 +3004,50 @@ function renderMemoryStatus(msg) {
|
|
|
2997
3004
|
el.title = `model: ${msg.model || '-'}`;
|
|
2998
3005
|
}
|
|
2999
3006
|
|
|
3007
|
+
function renderMemoryEntries(msg) {
|
|
3008
|
+
const el = document.getElementById('memory-managed-list');
|
|
3009
|
+
if (!el) return;
|
|
3010
|
+
const entries = msg.entries || [];
|
|
3011
|
+
if (entries.length === 0) {
|
|
3012
|
+
el.innerHTML = '<div class="opacity-40 py-1">No persistent memories.</div>';
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
el.innerHTML = entries.map((m) => {
|
|
3016
|
+
const status = m.expired ? 'expired' : (m.approved ? 'approved' : 'pending');
|
|
3017
|
+
const statusClass = m.expired ? 'badge-ghost' : (m.approved ? 'badge-success' : 'badge-warning');
|
|
3018
|
+
const source = m.sourceSession ? `session ${m.sourceSession.slice(0, 8)}` : (m.sourceProject ? 'project' : 'manual/tool');
|
|
3019
|
+
const preview = m.content.length > 180 ? m.content.slice(0, 180) + '…' : m.content;
|
|
3020
|
+
const actions = [];
|
|
3021
|
+
if (!m.approved && !m.expired) actions.push(`<button class="btn btn-xs btn-ghost memory-managed-approve" title="Approve">Approve</button>`);
|
|
3022
|
+
if (m.approved && !m.expired) actions.push(`<button class="btn btn-xs btn-ghost memory-managed-reject" title="Reject">Reject</button>`);
|
|
3023
|
+
if (!m.expired) actions.push(`<button class="btn btn-xs btn-ghost memory-managed-expire" title="Expire now">Expire</button>`);
|
|
3024
|
+
actions.push(`<button class="btn btn-xs btn-ghost memory-managed-delete" title="Delete">Delete</button>`);
|
|
3025
|
+
return `
|
|
3026
|
+
<div class="memory-managed-item border border-base-content/10 rounded p-2" data-memory-id="${escapeHtml(m.id)}">
|
|
3027
|
+
<div class="flex items-center gap-1 mb-1">
|
|
3028
|
+
<span class="badge badge-xs ${statusClass}">${status}</span>
|
|
3029
|
+
<span class="badge badge-xs badge-ghost">${escapeHtml(m.scope)}</span>
|
|
3030
|
+
<span class="badge badge-xs badge-ghost">${escapeHtml(m.sensitivity)}</span>
|
|
3031
|
+
<span class="opacity-50 truncate flex-1">${escapeHtml(m.id.slice(0, 8))}</span>
|
|
3032
|
+
</div>
|
|
3033
|
+
<div class="opacity-50 mb-1">source: ${escapeHtml(source)} · ${escapeHtml((m.createdAt || '').replace('T', ' ').slice(0, 16))}</div>
|
|
3034
|
+
<div class="whitespace-pre-wrap leading-snug mb-1">${escapeHtml(preview)}</div>
|
|
3035
|
+
<div class="flex flex-wrap gap-1">${actions.join('')}</div>
|
|
3036
|
+
</div>
|
|
3037
|
+
`;
|
|
3038
|
+
}).join('');
|
|
3039
|
+
|
|
3040
|
+
el.querySelectorAll('.memory-managed-item').forEach((card) => {
|
|
3041
|
+
const id = card.getAttribute('data-memory-id');
|
|
3042
|
+
if (!id) return;
|
|
3043
|
+
card.querySelector('.memory-managed-approve')?.addEventListener('click', () => send({ type: 'memory_manage', action: 'approve', id }));
|
|
3044
|
+
card.querySelector('.memory-managed-reject')?.addEventListener('click', () => send({ type: 'memory_manage', action: 'reject', id }));
|
|
3045
|
+
card.querySelector('.memory-managed-expire')?.addEventListener('click', () => send({ type: 'memory_manage', action: 'expire', id }));
|
|
3046
|
+
card.querySelector('.memory-managed-delete')?.addEventListener('click', () => {
|
|
3047
|
+
if (confirm('Delete this memory entry?')) send({ type: 'memory_manage', action: 'delete', id });
|
|
3048
|
+
});
|
|
3049
|
+
});
|
|
3050
|
+
}
|
|
3000
3051
|
function renderMemoryHits(msg) {
|
|
3001
3052
|
const el = document.getElementById('memory-hits');
|
|
3002
3053
|
if (!el) return;
|
|
@@ -192,7 +192,17 @@
|
|
|
192
192
|
<button id="btn-memory-refresh" class="btn btn-xs btn-ghost" title="Incremental refresh">↻</button>
|
|
193
193
|
<button id="btn-memory-rebuild" class="btn btn-xs btn-ghost" title="Full rebuild (slow first run)">⟳ Rebuild</button>
|
|
194
194
|
</div>
|
|
195
|
-
<div id="memory-status" class="text-xs opacity-50 truncate">Loading index status…</div>
|
|
195
|
+
<div id="memory-status" class="text-xs opacity-50 truncate">Loading index status…</div>
|
|
196
|
+
<div id="memory-governance" class="border-t border-base-content/10 pt-2 mt-1">
|
|
197
|
+
<div class="flex items-center gap-1 mb-1">
|
|
198
|
+
<span class="text-xs font-semibold flex-1">Persistent memory</span>
|
|
199
|
+
<button id="btn-memory-managed-refresh" class="btn btn-xs btn-ghost" title="Refresh persistent memory">↻</button>
|
|
200
|
+
<button id="btn-memory-managed-export" class="btn btn-xs btn-ghost" title="Export persistent memory">Export</button>
|
|
201
|
+
</div>
|
|
202
|
+
<div id="memory-managed-list" class="flex flex-col gap-1 max-h-48 overflow-y-auto text-xs">
|
|
203
|
+
<div class="opacity-40 py-1">Loading persistent memory…</div>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
196
206
|
</div>
|
|
197
207
|
<div id="memory-hits" class="flex-1 overflow-y-auto p-2 flex flex-col gap-2 text-sm">
|
|
198
208
|
<div class="text-xs opacity-40 text-center py-4">Type a query above to recall past chats.</div>
|