jinzd-ai-cli 0.4.330 → 0.4.331
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-GXITPLER.js → batch-OOHC5POO.js} +2 -2
- package/dist/{chunk-DX2U6QK4.js → chunk-56ME7PB2.js} +1 -1
- package/dist/{chunk-GWEBO4RF.js → chunk-6BGW25LG.js} +1 -1
- package/dist/{chunk-E2W2MI6H.js → chunk-C6GA7H5D.js} +1 -72
- package/dist/{chunk-QU74ONFF.js → chunk-CM5C7ZSM.js} +1 -1
- package/dist/{chunk-3YVZJHTF.js → chunk-DTVN2LDU.js} +1 -1
- package/dist/{chunk-265M6ZLH.js → chunk-EWARNWJ4.js} +4 -4
- package/dist/{chunk-CCFCPAKN.js → chunk-IJNDIOOQ.js} +1 -1
- package/dist/{chunk-LLXHA2LA.js → chunk-L3FDFFD2.js} +8 -8
- package/dist/{chunk-LUJ4JVMI.js → chunk-MJSK6ZYR.js} +4 -4
- package/dist/{chunk-C2Z77RTU.js → chunk-MN25ELTF.js} +15 -4
- package/dist/{chunk-72AR23R2.js → chunk-NOLK5C4U.js} +54 -2
- package/dist/{chunk-HMQA2R3O.js → chunk-Q26V2PNA.js} +1 -1
- package/dist/{chunk-GEC3MEVQ.js → chunk-QFF2PTI3.js} +6 -4
- package/dist/{chunk-2SYDIWRU.js → chunk-R3XIU7NS.js} +1 -1
- package/dist/{chunk-M5B6G6AY.js → chunk-RZDRBFAB.js} +9 -7
- package/dist/{chunk-DU44SD6A.js → chunk-TF2FNRDZ.js} +1 -1
- package/dist/chunk-W4P2KJZN.js +75 -0
- package/dist/{chunk-AJITHMRE.js → chunk-YCDF6FNR.js} +1 -1
- package/dist/{ci-6K3JNHB4.js → ci-HNYUXJUE.js} +7 -6
- package/dist/{ci-format-2L3RFJVH.js → ci-format-ZLBEAU7Z.js} +2 -2
- package/dist/{constants-DLJECTGQ.js → constants-4EH6Y6VI.js} +1 -1
- package/dist/{constants-J5SJ232X.js → constants-JM6MK5SS.js} +1 -1
- package/dist/{doctor-cli-BHS7G2XY.js → doctor-cli-VCNERMX5.js} +7 -6
- package/dist/electron-server.js +193 -130
- package/dist/{hub-PPG4N6QQ.js → hub-3OXLWTEP.js} +8 -18
- package/dist/{hub-server-JLC7CNP7.js → hub-server-LJWXNEWK.js} +2 -1
- package/dist/index.js +20 -19
- package/dist/{persistent-memory-3XTSZ3QR.js → persistent-memory-LMVWIHMX.js} +2 -2
- package/dist/{persistent-memory-O4T2OTVV.js → persistent-memory-PAS7NAPQ.js} +2 -2
- package/dist/{pr-M6ZY4CEK.js → pr-IMR62OHN.js} +7 -6
- package/dist/{run-tests-H3DIUCDB.js → run-tests-2TVEWCQI.js} +2 -2
- package/dist/{run-tests-WQE3XTUL.js → run-tests-MQVGE6FK.js} +2 -2
- package/dist/{server-J2B26DZK.js → server-55X6MCGX.js} +7 -6
- package/dist/{server-5NQSYQ2T.js → server-6MS2NGEJ.js} +29 -19
- package/dist/{task-orchestrator-CI7EDT25.js → task-orchestrator-KIDJB7NP.js} +9 -7
- package/dist/{usage-AJYZ5A7P.js → usage-X2CQYAUA.js} +2 -2
- package/dist/web/client/app.js +19 -0
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
touchMemoryReferences,
|
|
56
56
|
updateMemoryApproval,
|
|
57
57
|
updateMemoryEntry
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-R3XIU7NS.js";
|
|
59
59
|
import {
|
|
60
60
|
DEFAULT_PATTERNS,
|
|
61
61
|
redactJson,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
recoverGbkMojibake,
|
|
82
82
|
runTestsTool,
|
|
83
83
|
shellInvocation
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-TF2FNRDZ.js";
|
|
85
85
|
import {
|
|
86
86
|
getCurrentSessionKey,
|
|
87
87
|
getExecutionConfigDir,
|
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
124
124
|
VERSION,
|
|
125
125
|
buildUserIdentityPrompt
|
|
126
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-DTVN2LDU.js";
|
|
127
127
|
|
|
128
128
|
// src/web/access.ts
|
|
129
129
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -205,8 +205,8 @@ function imageValidationError(images) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// src/web/server.ts
|
|
208
|
-
import { join as
|
|
209
|
-
import { existsSync as
|
|
208
|
+
import { join as join26, dirname as dirname12, resolve as resolve12, relative as relative6, sep as sep5, extname as extname3, resolve as resolvePath } from "path";
|
|
209
|
+
import { existsSync as existsSync32, readFileSync as readFileSync23, readdirSync as readdirSync16, statSync as statSync16, realpathSync as realpathSync3, createReadStream } from "fs";
|
|
210
210
|
import { networkInterfaces as networkInterfaces2 } from "os";
|
|
211
211
|
|
|
212
212
|
// src/config/config-manager.ts
|
|
@@ -2859,12 +2859,12 @@ function findPhantomClaims(content, extraMessages) {
|
|
|
2859
2859
|
const claimed = extractClaimedFilePaths(content);
|
|
2860
2860
|
if (claimed.length === 0) return [];
|
|
2861
2861
|
const normalize = (p) => p.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
|
|
2862
|
-
const
|
|
2862
|
+
const basename12 = (p) => {
|
|
2863
2863
|
const parts = normalize(p).split("/");
|
|
2864
2864
|
return parts[parts.length - 1] ?? "";
|
|
2865
2865
|
};
|
|
2866
2866
|
const written = extractWrittenFilePaths(extraMessages).map(normalize);
|
|
2867
|
-
const writtenBases = new Set(written.map(
|
|
2867
|
+
const writtenBases = new Set(written.map(basename12));
|
|
2868
2868
|
const writtenFull = new Set(written);
|
|
2869
2869
|
const bashText = extractBashCommands(extraMessages).map((c) => c.replace(/\\/g, "/").toLowerCase()).join("\n");
|
|
2870
2870
|
return claimed.filter((raw) => {
|
|
@@ -2873,8 +2873,8 @@ function findPhantomClaims(content, extraMessages) {
|
|
|
2873
2873
|
for (const w of writtenFull) {
|
|
2874
2874
|
if (w.endsWith("/" + norm2) || norm2.endsWith("/" + w)) return false;
|
|
2875
2875
|
}
|
|
2876
|
-
if (writtenBases.has(
|
|
2877
|
-
const base =
|
|
2876
|
+
if (writtenBases.has(basename12(norm2))) return false;
|
|
2877
|
+
const base = basename12(norm2);
|
|
2878
2878
|
if (base && bashText.includes(base)) return false;
|
|
2879
2879
|
return true;
|
|
2880
2880
|
});
|
|
@@ -16004,8 +16004,12 @@ function stripConvergedMarker(content) {
|
|
|
16004
16004
|
|
|
16005
16005
|
// src/hub/agent.ts
|
|
16006
16006
|
var PASS_MARKER = "[PASS]";
|
|
16007
|
+
function stripThinkBlocks(raw) {
|
|
16008
|
+
const filter = new ThinkTagFilter();
|
|
16009
|
+
return filter.push(raw) + filter.flush();
|
|
16010
|
+
}
|
|
16007
16011
|
function parseTurn(raw) {
|
|
16008
|
-
const trimmed = raw.trim();
|
|
16012
|
+
const trimmed = stripThinkBlocks(raw).trim();
|
|
16009
16013
|
const upper = trimmed.toUpperCase();
|
|
16010
16014
|
if (upper.startsWith(PASS_MARKER) || upper === PASS_MARKER) {
|
|
16011
16015
|
return { content: "", passed: true, converged: false };
|
|
@@ -16085,6 +16089,7 @@ var HubAgent = class {
|
|
|
16085
16089
|
const systemPrompt = this.buildSystemPrompt(topic, round, maxRounds, opts?.voteConverge);
|
|
16086
16090
|
const messages = this.buildMessages(history);
|
|
16087
16091
|
let raw = "";
|
|
16092
|
+
const thinkFilter = new ThinkTagFilter();
|
|
16088
16093
|
const stream = provider.chatStream({
|
|
16089
16094
|
messages,
|
|
16090
16095
|
model: this.modelId,
|
|
@@ -16099,13 +16104,16 @@ var HubAgent = class {
|
|
|
16099
16104
|
for await (const chunk of stream) {
|
|
16100
16105
|
if (chunk.delta) {
|
|
16101
16106
|
raw += chunk.delta;
|
|
16102
|
-
|
|
16107
|
+
const visible = thinkFilter.push(chunk.delta);
|
|
16108
|
+
if (visible) onToken?.(visible);
|
|
16103
16109
|
}
|
|
16104
16110
|
if (opts?.signal?.aborted) break;
|
|
16105
16111
|
}
|
|
16106
16112
|
} catch (error) {
|
|
16107
16113
|
if (!opts?.signal?.aborted) throw error;
|
|
16108
16114
|
}
|
|
16115
|
+
const tail = thinkFilter.flush();
|
|
16116
|
+
if (tail) onToken?.(tail);
|
|
16109
16117
|
const { content, passed, converged } = parseTurn(raw);
|
|
16110
16118
|
return {
|
|
16111
16119
|
speaker: this.role.id,
|
|
@@ -16140,7 +16148,7 @@ var HubAgent = class {
|
|
|
16140
16148
|
maxTokens: 4096,
|
|
16141
16149
|
...this.thinking ?? {}
|
|
16142
16150
|
});
|
|
16143
|
-
return response.content.trim();
|
|
16151
|
+
return stripThinkBlocks(response.content).trim();
|
|
16144
16152
|
}
|
|
16145
16153
|
// ── Private ──────────────────────────────────────────────────────
|
|
16146
16154
|
buildSystemPrompt(topic, round, maxRounds, voteConverge) {
|
|
@@ -16221,7 +16229,7 @@ Produce a structured, decision-oriented synthesis with these exact sections:
|
|
|
16221
16229
|
4. **Action Items** \u2014 concrete next steps as a checklist. For each, suggest which role/expertise should own it, e.g. "- [ ] (\u67B6\u6784\u5E08) \u8BC4\u4F30\u670D\u52A1\u62C6\u5206\u8FB9\u754C".
|
|
16222
16230
|
5. **Risks & Open Questions** \u2014 unresolved issues and what to watch.
|
|
16223
16231
|
|
|
16224
|
-
Keep it tight (within ~600 words). Use the same language as the discussion.`;
|
|
16232
|
+
Keep it tight (within ~600 words). Use the same language as the discussion \u2014 including the section headings (translate them, e.g. \u51B3\u7B56 / \u5EFA\u8BAE\u3001\u5173\u952E\u5171\u8BC6\u3001\u5206\u6B67\u70B9\u3001\u884C\u52A8\u9879\u3001\u98CE\u9669\u4E0E\u5F00\u653E\u95EE\u9898 for a Chinese discussion).`;
|
|
16225
16233
|
}
|
|
16226
16234
|
};
|
|
16227
16235
|
|
|
@@ -16597,8 +16605,57 @@ function resolveRoleProviders(roles, lookup, defaultProvider, defaultModel, avai
|
|
|
16597
16605
|
return { roles: outRoles, assignments, warnings };
|
|
16598
16606
|
}
|
|
16599
16607
|
|
|
16608
|
+
// src/hub/custom-presets.ts
|
|
16609
|
+
import { existsSync as existsSync25, readdirSync as readdirSync12, readFileSync as readFileSync18 } from "fs";
|
|
16610
|
+
import { join as join18, basename as basename10 } from "path";
|
|
16611
|
+
var CUSTOM_PRESET_PREFIX = "custom:";
|
|
16612
|
+
var HUB_ROLES_DIRNAME = "hub-roles";
|
|
16613
|
+
function parseRolesJson(parsed) {
|
|
16614
|
+
const rawRoles = Array.isArray(parsed) ? parsed : parsed?.roles;
|
|
16615
|
+
if (!Array.isArray(rawRoles) || rawRoles.length === 0) {
|
|
16616
|
+
throw new Error("roles must be a non-empty array");
|
|
16617
|
+
}
|
|
16618
|
+
return rawRoles.map((r) => ({
|
|
16619
|
+
id: r.id ?? r.name?.toLowerCase().replace(/\s+/g, "-") ?? "agent",
|
|
16620
|
+
name: r.name ?? r.id ?? "Agent",
|
|
16621
|
+
persona: r.persona ?? r.description ?? `You are ${r.name ?? "an AI assistant"}.`,
|
|
16622
|
+
...r.provider && { provider: r.provider },
|
|
16623
|
+
...r.model && { model: r.model },
|
|
16624
|
+
...r.color && { color: r.color }
|
|
16625
|
+
}));
|
|
16626
|
+
}
|
|
16627
|
+
function loadCustomPresets(configDir) {
|
|
16628
|
+
const dir = join18(configDir, HUB_ROLES_DIRNAME);
|
|
16629
|
+
const presets = [];
|
|
16630
|
+
const warnings = [];
|
|
16631
|
+
if (!existsSync25(dir)) return { presets, warnings };
|
|
16632
|
+
let files;
|
|
16633
|
+
try {
|
|
16634
|
+
files = readdirSync12(dir).filter((f) => f.toLowerCase().endsWith(".json")).sort();
|
|
16635
|
+
} catch (err) {
|
|
16636
|
+
return { presets, warnings: [`${dir}: ${err.message}`] };
|
|
16637
|
+
}
|
|
16638
|
+
for (const file of files) {
|
|
16639
|
+
const stem = basename10(file, file.slice(file.lastIndexOf(".")));
|
|
16640
|
+
try {
|
|
16641
|
+
const parsed = JSON.parse(readFileSync18(join18(dir, file), "utf-8").replace(/^/, ""));
|
|
16642
|
+
const roles = parseRolesJson(parsed);
|
|
16643
|
+
const meta = Array.isArray(parsed) ? {} : parsed;
|
|
16644
|
+
presets.push({
|
|
16645
|
+
id: `${CUSTOM_PRESET_PREFIX}${stem}`,
|
|
16646
|
+
name: typeof meta.name === "string" && meta.name.trim() ? meta.name.trim() : stem,
|
|
16647
|
+
description: typeof meta.description === "string" && meta.description.trim() ? meta.description.trim() : roles.map((r) => r.name).join("\xB7"),
|
|
16648
|
+
roles
|
|
16649
|
+
});
|
|
16650
|
+
} catch (err) {
|
|
16651
|
+
warnings.push(`${HUB_ROLES_DIRNAME}/${file}: ${err.message}`);
|
|
16652
|
+
}
|
|
16653
|
+
}
|
|
16654
|
+
return { presets, warnings };
|
|
16655
|
+
}
|
|
16656
|
+
|
|
16600
16657
|
// src/hub/persist.ts
|
|
16601
|
-
import { join as
|
|
16658
|
+
import { join as join19 } from "path";
|
|
16602
16659
|
function discussionToMessages(state2) {
|
|
16603
16660
|
const out = [];
|
|
16604
16661
|
const t0 = state2.messages[0]?.timestamp ?? /* @__PURE__ */ new Date();
|
|
@@ -16636,7 +16693,7 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
|
|
|
16636
16693
|
session.title = `[Hub] ${state2.topic.slice(0, 48)}`.replace(/\n/g, " ");
|
|
16637
16694
|
session.titleAiGenerated = true;
|
|
16638
16695
|
await sm.save();
|
|
16639
|
-
return { id: session.id, path:
|
|
16696
|
+
return { id: session.id, path: join19(config.getHistoryDir(), `${session.id}.json`) };
|
|
16640
16697
|
}
|
|
16641
16698
|
|
|
16642
16699
|
// src/core/think-command.ts
|
|
@@ -17097,8 +17154,8 @@ function costSourceNote(source2) {
|
|
|
17097
17154
|
}
|
|
17098
17155
|
|
|
17099
17156
|
// src/web/commands/_shared.ts
|
|
17100
|
-
import { existsSync as
|
|
17101
|
-
import { join as
|
|
17157
|
+
import { existsSync as existsSync28, readFileSync as readFileSync20, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync14, statSync as statSync14, createWriteStream } from "fs";
|
|
17158
|
+
import { join as join22, resolve as resolve9, dirname as dirname9 } from "path";
|
|
17102
17159
|
|
|
17103
17160
|
// src/cli/review-prompts.ts
|
|
17104
17161
|
function buildReviewPrompt(diff, gitContextStr, detailed) {
|
|
@@ -17170,47 +17227,47 @@ function readGitDiff(options = {}) {
|
|
|
17170
17227
|
}
|
|
17171
17228
|
|
|
17172
17229
|
// src/diagnostics/doctor-report.ts
|
|
17173
|
-
import { existsSync as
|
|
17174
|
-
import { join as
|
|
17230
|
+
import { existsSync as existsSync27, statSync as statSync13 } from "fs";
|
|
17231
|
+
import { join as join21 } from "path";
|
|
17175
17232
|
import { arch as arch2, platform as platform5, release as release2 } from "os";
|
|
17176
17233
|
|
|
17177
17234
|
// src/diagnostics/crash-log.ts
|
|
17178
17235
|
import {
|
|
17179
|
-
existsSync as
|
|
17236
|
+
existsSync as existsSync26,
|
|
17180
17237
|
mkdirSync as mkdirSync12,
|
|
17181
|
-
readdirSync as
|
|
17182
|
-
readFileSync as
|
|
17238
|
+
readdirSync as readdirSync13,
|
|
17239
|
+
readFileSync as readFileSync19,
|
|
17183
17240
|
statSync as statSync12,
|
|
17184
17241
|
unlinkSync as unlinkSync6,
|
|
17185
17242
|
writeFileSync as writeFileSync2
|
|
17186
17243
|
} from "fs";
|
|
17187
|
-
import { join as
|
|
17244
|
+
import { join as join20 } from "path";
|
|
17188
17245
|
import { homedir as homedir7, platform as platform4, release, arch } from "os";
|
|
17189
17246
|
var LOGS_DIR_NAME = "logs";
|
|
17190
17247
|
var CRASH_LOG_PREFIX = "crash-";
|
|
17191
17248
|
function getLogsDir(configDir) {
|
|
17192
|
-
const base = configDir ??
|
|
17193
|
-
return
|
|
17249
|
+
const base = configDir ?? join20(homedir7(), CONFIG_DIR_NAME);
|
|
17250
|
+
return join20(base, LOGS_DIR_NAME);
|
|
17194
17251
|
}
|
|
17195
17252
|
function truncate(s, n) {
|
|
17196
17253
|
return s.length <= n ? s : s.slice(0, n) + "\u2026";
|
|
17197
17254
|
}
|
|
17198
17255
|
function listRecentCrashes(limit = 10, configDir) {
|
|
17199
17256
|
const dir = getLogsDir(configDir);
|
|
17200
|
-
if (!
|
|
17257
|
+
if (!existsSync26(dir)) return [];
|
|
17201
17258
|
const files = [];
|
|
17202
17259
|
let names;
|
|
17203
17260
|
try {
|
|
17204
|
-
names =
|
|
17261
|
+
names = readdirSync13(dir);
|
|
17205
17262
|
} catch {
|
|
17206
17263
|
return [];
|
|
17207
17264
|
}
|
|
17208
17265
|
for (const name of names) {
|
|
17209
17266
|
if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
|
|
17210
|
-
const full =
|
|
17267
|
+
const full = join20(dir, name);
|
|
17211
17268
|
try {
|
|
17212
17269
|
const st = statSync12(full);
|
|
17213
|
-
const head =
|
|
17270
|
+
const head = readFileSync19(full, "utf-8").split("\n").slice(0, 20);
|
|
17214
17271
|
const tsLine = head.find((l) => l.startsWith("timestamp:"));
|
|
17215
17272
|
const kindLine = head.find((l) => l.startsWith("kind:"));
|
|
17216
17273
|
const msgIdx = head.findIndex((l) => l.trim() === "## message");
|
|
@@ -17229,18 +17286,18 @@ function listRecentCrashes(limit = 10, configDir) {
|
|
|
17229
17286
|
return files.slice(0, limit);
|
|
17230
17287
|
}
|
|
17231
17288
|
function getConfigDirUsage(configDir) {
|
|
17232
|
-
const base = configDir ??
|
|
17233
|
-
if (!
|
|
17289
|
+
const base = configDir ?? join20(homedir7(), CONFIG_DIR_NAME);
|
|
17290
|
+
if (!existsSync26(base)) return { totalBytes: 0, entries: [] };
|
|
17234
17291
|
const entries = [];
|
|
17235
17292
|
let total = 0;
|
|
17236
17293
|
let names;
|
|
17237
17294
|
try {
|
|
17238
|
-
names =
|
|
17295
|
+
names = readdirSync13(base);
|
|
17239
17296
|
} catch {
|
|
17240
17297
|
return { totalBytes: 0, entries: [] };
|
|
17241
17298
|
}
|
|
17242
17299
|
for (const name of names) {
|
|
17243
|
-
const full =
|
|
17300
|
+
const full = join20(base, name);
|
|
17244
17301
|
const bytes = dirSize(full);
|
|
17245
17302
|
entries.push({ name, bytes });
|
|
17246
17303
|
total += bytes;
|
|
@@ -17254,8 +17311,8 @@ function dirSize(path3) {
|
|
|
17254
17311
|
if (st.isFile()) return st.size;
|
|
17255
17312
|
if (!st.isDirectory()) return 0;
|
|
17256
17313
|
let sum = 0;
|
|
17257
|
-
for (const name of
|
|
17258
|
-
sum += dirSize(
|
|
17314
|
+
for (const name of readdirSync13(path3)) {
|
|
17315
|
+
sum += dirSize(join20(path3, name));
|
|
17259
17316
|
}
|
|
17260
17317
|
return sum;
|
|
17261
17318
|
} catch {
|
|
@@ -17265,7 +17322,7 @@ function dirSize(path3) {
|
|
|
17265
17322
|
|
|
17266
17323
|
// src/diagnostics/doctor-report.ts
|
|
17267
17324
|
function checkFile(label, path3) {
|
|
17268
|
-
const exists =
|
|
17325
|
+
const exists = existsSync27(path3);
|
|
17269
17326
|
let sizeBytes = null;
|
|
17270
17327
|
if (exists) {
|
|
17271
17328
|
try {
|
|
@@ -17308,12 +17365,12 @@ function buildDoctorReport(options) {
|
|
|
17308
17365
|
configDir,
|
|
17309
17366
|
providers: options.providers.listAll().map((p) => ({ id: p.id, displayName: p.displayName, configured: p.configured })),
|
|
17310
17367
|
files: [
|
|
17311
|
-
checkFile("config.json",
|
|
17312
|
-
checkFile("memory.md",
|
|
17313
|
-
checkFile("memory.jsonl",
|
|
17314
|
-
checkFile("dev-state.md",
|
|
17315
|
-
checkFile("hooks-trust.json",
|
|
17316
|
-
checkFile("plugin-state.json",
|
|
17368
|
+
checkFile("config.json", join21(configDir, "config.json")),
|
|
17369
|
+
checkFile("memory.md", join21(configDir, MEMORY_FILE_NAME)),
|
|
17370
|
+
checkFile("memory.jsonl", join21(configDir, "memory.jsonl")),
|
|
17371
|
+
checkFile("dev-state.md", join21(configDir, DEV_STATE_FILE_NAME)),
|
|
17372
|
+
checkFile("hooks-trust.json", join21(configDir, "hooks-trust.json")),
|
|
17373
|
+
checkFile("plugin-state.json", join21(configDir, "plugins", "plugin-state.json"))
|
|
17317
17374
|
],
|
|
17318
17375
|
context: {
|
|
17319
17376
|
enabled: contextSetting !== false,
|
|
@@ -17348,7 +17405,7 @@ function buildDoctorReport(options) {
|
|
|
17348
17405
|
disabled: hooks.filter((h) => h.disabled).length
|
|
17349
17406
|
},
|
|
17350
17407
|
plugins: {
|
|
17351
|
-
root:
|
|
17408
|
+
root: join21(configDir, "plugins"),
|
|
17352
17409
|
installed: plugins.length,
|
|
17353
17410
|
active: activeAssets.plugins.length,
|
|
17354
17411
|
invalid: plugins.filter((p) => !p.valid).length,
|
|
@@ -17363,7 +17420,7 @@ function buildDoctorReport(options) {
|
|
|
17363
17420
|
mcp: {
|
|
17364
17421
|
enabled: config.get("mcpEnabled"),
|
|
17365
17422
|
configured: Object.keys(mcpServers).length,
|
|
17366
|
-
projectConfigExists:
|
|
17423
|
+
projectConfigExists: existsSync27(join21(projectRoot, MCP_PROJECT_CONFIG_NAME)),
|
|
17367
17424
|
statuses: options.mcpStatuses ?? []
|
|
17368
17425
|
},
|
|
17369
17426
|
recentCrashes: listRecentCrashes(5, configDir),
|
|
@@ -17885,7 +17942,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
17885
17942
|
Cost: ${formatCost(cost)}` : "";
|
|
17886
17943
|
let memoryLine = "";
|
|
17887
17944
|
try {
|
|
17888
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
17945
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-LMVWIHMX.js");
|
|
17889
17946
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
17890
17947
|
if (pending > 0) memoryLine = `
|
|
17891
17948
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -18626,7 +18683,7 @@ async function handlePlugin(args, ctx) {
|
|
|
18626
18683
|
lines.push("");
|
|
18627
18684
|
}
|
|
18628
18685
|
if (pluginTools.length > 0) {
|
|
18629
|
-
const legacyDir =
|
|
18686
|
+
const legacyDir = join22(configDir, PLUGINS_DIR_NAME);
|
|
18630
18687
|
lines.push(`**Legacy JS tools** (${pluginTools.length}):`);
|
|
18631
18688
|
lines.push(`Dir: ${legacyDir}`);
|
|
18632
18689
|
for (const t of pluginTools) lines.push(` \u2022 ${t.definition.name} \u2014 ${t.definition.description}`);
|
|
@@ -18766,14 +18823,14 @@ ${note}` : head });
|
|
|
18766
18823
|
}
|
|
18767
18824
|
async function handleCommands(_args, ctx) {
|
|
18768
18825
|
const configDir = ctx.config.getConfigDir();
|
|
18769
|
-
const commandsDir =
|
|
18770
|
-
if (!
|
|
18826
|
+
const commandsDir = join22(configDir, CUSTOM_COMMANDS_DIR_NAME);
|
|
18827
|
+
if (!existsSync28(commandsDir)) {
|
|
18771
18828
|
ctx.send({ type: "info", message: `No custom commands directory.
|
|
18772
18829
|
Create: ${commandsDir}/ with .md files.` });
|
|
18773
18830
|
return;
|
|
18774
18831
|
}
|
|
18775
18832
|
try {
|
|
18776
|
-
const files =
|
|
18833
|
+
const files = readdirSync14(commandsDir).filter((f) => f.endsWith(".md"));
|
|
18777
18834
|
if (files.length === 0) {
|
|
18778
18835
|
ctx.send({ type: "info", message: `No custom commands found in ${commandsDir}
|
|
18779
18836
|
Add .md files to create commands.` });
|
|
@@ -18873,7 +18930,7 @@ async function handleTest(args, ctx) {
|
|
|
18873
18930
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
18874
18931
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
18875
18932
|
}
|
|
18876
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
18933
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-MQVGE6FK.js")).executeTests;
|
|
18877
18934
|
const report = await runTests(testArgs);
|
|
18878
18935
|
ctx.send({ type: "info", message: report });
|
|
18879
18936
|
} catch (err) {
|
|
@@ -18897,9 +18954,9 @@ async function handleDiff(args, ctx) {
|
|
|
18897
18954
|
let modifiedFiles = 0;
|
|
18898
18955
|
const diffLines2 = [];
|
|
18899
18956
|
for (const [filePath, { earliest }] of fileMap) {
|
|
18900
|
-
const currentContent =
|
|
18957
|
+
const currentContent = existsSync28(filePath) ? (() => {
|
|
18901
18958
|
try {
|
|
18902
|
-
return
|
|
18959
|
+
return readFileSync20(filePath, "utf-8");
|
|
18903
18960
|
} catch {
|
|
18904
18961
|
return null;
|
|
18905
18962
|
}
|
|
@@ -18934,9 +18991,9 @@ async function handleDiff(args, ctx) {
|
|
|
18934
18991
|
}
|
|
18935
18992
|
async function handleInit(args, ctx) {
|
|
18936
18993
|
const cwd = process.cwd();
|
|
18937
|
-
const targetPath =
|
|
18994
|
+
const targetPath = join22(cwd, "AICLI.md");
|
|
18938
18995
|
const force = args.includes("--force");
|
|
18939
|
-
if (
|
|
18996
|
+
if (existsSync28(targetPath) && !force) {
|
|
18940
18997
|
ctx.send({ type: "info", message: `AICLI.md already exists at ${targetPath}
|
|
18941
18998
|
Use /init --force to overwrite.` });
|
|
18942
18999
|
return;
|
|
@@ -19264,7 +19321,7 @@ async function handleMemory(args, ctx) {
|
|
|
19264
19321
|
}
|
|
19265
19322
|
if (intent.kind === "status") {
|
|
19266
19323
|
const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-RLVLQRRC.js");
|
|
19267
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
19324
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-LMVWIHMX.js");
|
|
19268
19325
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
19269
19326
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
19270
19327
|
const view = buildMemoryStatusView({
|
|
@@ -19287,7 +19344,7 @@ async function handleMemory(args, ctx) {
|
|
|
19287
19344
|
return;
|
|
19288
19345
|
}
|
|
19289
19346
|
if (intent.kind === "recall") {
|
|
19290
|
-
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-
|
|
19347
|
+
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-LMVWIHMX.js");
|
|
19291
19348
|
const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-RLVLQRRC.js");
|
|
19292
19349
|
const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
|
|
19293
19350
|
if (persistentHits.length > 0) {
|
|
@@ -19408,7 +19465,7 @@ async function handleMemory(args, ctx) {
|
|
|
19408
19465
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
19409
19466
|
} else if (intent.kind === "export") {
|
|
19410
19467
|
if (args[1] === "md") {
|
|
19411
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
19468
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-LMVWIHMX.js");
|
|
19412
19469
|
ctx.send({
|
|
19413
19470
|
type: "export_data",
|
|
19414
19471
|
format: "md",
|
|
@@ -19446,7 +19503,7 @@ Use /add-dir remove to clear.` : "No directories added.\nUsage: /add-dir <path>
|
|
|
19446
19503
|
return;
|
|
19447
19504
|
}
|
|
19448
19505
|
const dirPath = resolve9(sub);
|
|
19449
|
-
if (!
|
|
19506
|
+
if (!existsSync28(dirPath)) {
|
|
19450
19507
|
ctx.send({ type: "error", message: `Directory not found: ${dirPath}` });
|
|
19451
19508
|
return;
|
|
19452
19509
|
}
|
|
@@ -20411,16 +20468,16 @@ No tools match "${filter}".
|
|
|
20411
20468
|
usage: "/mcp [reconnect [serverId] | trust-project]",
|
|
20412
20469
|
async execute(args, ctx) {
|
|
20413
20470
|
if (args[0] === "trust-project") {
|
|
20414
|
-
const { join:
|
|
20415
|
-
const { existsSync:
|
|
20471
|
+
const { join: join27 } = await import("path");
|
|
20472
|
+
const { existsSync: existsSync33 } = await import("fs");
|
|
20416
20473
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
|
|
20417
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
20474
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-JM6MK5SS.js");
|
|
20418
20475
|
const { approveProject, hashMcpFile } = await import("./project-trust-6CJB5ZMX.js");
|
|
20419
20476
|
const cwd = process.cwd();
|
|
20420
20477
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
20421
|
-
const mcpPath =
|
|
20478
|
+
const mcpPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME2);
|
|
20422
20479
|
console.log();
|
|
20423
|
-
if (!
|
|
20480
|
+
if (!existsSync33(mcpPath)) {
|
|
20424
20481
|
console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
|
|
20425
20482
|
console.log();
|
|
20426
20483
|
return;
|
|
@@ -20855,12 +20912,12 @@ ${outcome.summary}
|
|
|
20855
20912
|
if (scanAll) {
|
|
20856
20913
|
const metas = ctx.sessions.listSessions();
|
|
20857
20914
|
console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
|
|
20858
|
-
const { readFileSync:
|
|
20859
|
-
const { join:
|
|
20915
|
+
const { readFileSync: readFileSync24 } = await import("fs");
|
|
20916
|
+
const { join: join27 } = await import("path");
|
|
20860
20917
|
const historyDir = ctx.config.getHistoryDir();
|
|
20861
20918
|
for (const m of metas) {
|
|
20862
20919
|
try {
|
|
20863
|
-
const content =
|
|
20920
|
+
const content = readFileSync24(join27(historyDir, `${m.id}.json`), "utf-8");
|
|
20864
20921
|
const hits2 = scanString(content, opts);
|
|
20865
20922
|
if (hits2.length) {
|
|
20866
20923
|
filesWithHits++;
|
|
@@ -20907,8 +20964,8 @@ ${outcome.summary}
|
|
|
20907
20964
|
}
|
|
20908
20965
|
|
|
20909
20966
|
// src/repl/commands/review-commands.ts
|
|
20910
|
-
import { existsSync as
|
|
20911
|
-
import { join as
|
|
20967
|
+
import { existsSync as existsSync29, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "fs";
|
|
20968
|
+
import { join as join23 } from "path";
|
|
20912
20969
|
function createReviewCommands() {
|
|
20913
20970
|
return [
|
|
20914
20971
|
{
|
|
@@ -21267,9 +21324,9 @@ function createReviewCommands() {
|
|
|
21267
21324
|
usage: "/init [--force]",
|
|
21268
21325
|
async execute(args, ctx) {
|
|
21269
21326
|
const cwd = process.cwd();
|
|
21270
|
-
const targetPath =
|
|
21327
|
+
const targetPath = join23(cwd, "AICLI.md");
|
|
21271
21328
|
const force = args.includes("--force");
|
|
21272
|
-
if (
|
|
21329
|
+
if (existsSync29(targetPath) && !force) {
|
|
21273
21330
|
ctx.renderer.printInfo(`AICLI.md already exists at ${targetPath}`);
|
|
21274
21331
|
ctx.renderer.printInfo("Use /init --force to overwrite, or edit it manually.");
|
|
21275
21332
|
return;
|
|
@@ -21333,7 +21390,7 @@ function createReviewCommands() {
|
|
|
21333
21390
|
usage: "/test [command|filter]",
|
|
21334
21391
|
async execute(args, ctx) {
|
|
21335
21392
|
try {
|
|
21336
|
-
const { executeTests } = await import("./run-tests-
|
|
21393
|
+
const { executeTests } = await import("./run-tests-MQVGE6FK.js");
|
|
21337
21394
|
const argStr = args.join(" ").trim();
|
|
21338
21395
|
let testArgs = {};
|
|
21339
21396
|
if (argStr) {
|
|
@@ -21368,9 +21425,9 @@ function createReviewCommands() {
|
|
|
21368
21425
|
let newFiles = 0;
|
|
21369
21426
|
let modifiedFiles = 0;
|
|
21370
21427
|
for (const [filePath, { earliest }] of fileMap) {
|
|
21371
|
-
const currentContent =
|
|
21428
|
+
const currentContent = existsSync29(filePath) ? (() => {
|
|
21372
21429
|
try {
|
|
21373
|
-
return
|
|
21430
|
+
return readFileSync21(filePath, "utf-8");
|
|
21374
21431
|
} catch {
|
|
21375
21432
|
return null;
|
|
21376
21433
|
}
|
|
@@ -22532,17 +22589,17 @@ function createSessionCommands() {
|
|
|
22532
22589
|
}
|
|
22533
22590
|
|
|
22534
22591
|
// src/repl/commands/misc-commands.ts
|
|
22535
|
-
import { basename as
|
|
22592
|
+
import { basename as basename11 } from "path";
|
|
22536
22593
|
import { platform as platform8 } from "os";
|
|
22537
22594
|
|
|
22538
22595
|
// src/repl/clipboard.ts
|
|
22539
22596
|
import { execSync as execSync3 } from "child_process";
|
|
22540
|
-
import { existsSync as
|
|
22597
|
+
import { existsSync as existsSync30, statSync as statSync15, unlinkSync as unlinkSync7 } from "fs";
|
|
22541
22598
|
import { tmpdir as tmpdir3 } from "os";
|
|
22542
|
-
import { join as
|
|
22599
|
+
import { join as join24 } from "path";
|
|
22543
22600
|
var CLIPBOARD_TIMEOUT = 5e3;
|
|
22544
22601
|
function readClipboardImage() {
|
|
22545
|
-
const outPath =
|
|
22602
|
+
const outPath = join24(tmpdir3(), `aicli-paste-${Date.now()}.png`);
|
|
22546
22603
|
try {
|
|
22547
22604
|
if (process.platform === "win32") {
|
|
22548
22605
|
_readWin32(outPath);
|
|
@@ -22555,7 +22612,7 @@ function readClipboardImage() {
|
|
|
22555
22612
|
_cleanup(outPath);
|
|
22556
22613
|
return null;
|
|
22557
22614
|
}
|
|
22558
|
-
if (!
|
|
22615
|
+
if (!existsSync30(outPath) || statSync15(outPath).size === 0) {
|
|
22559
22616
|
_cleanup(outPath);
|
|
22560
22617
|
return null;
|
|
22561
22618
|
}
|
|
@@ -22608,7 +22665,7 @@ function _readLinux(outPath) {
|
|
|
22608
22665
|
}
|
|
22609
22666
|
function _cleanup(path3) {
|
|
22610
22667
|
try {
|
|
22611
|
-
if (
|
|
22668
|
+
if (existsSync30(path3)) unlinkSync7(path3);
|
|
22612
22669
|
} catch {
|
|
22613
22670
|
}
|
|
22614
22671
|
}
|
|
@@ -22878,7 +22935,7 @@ ${hint}` : "")
|
|
|
22878
22935
|
return;
|
|
22879
22936
|
}
|
|
22880
22937
|
const description = args.join(" ").trim() || "Please describe this image";
|
|
22881
|
-
ctx.renderer.printSuccess(`\u{1F4CB} Image loaded: ${
|
|
22938
|
+
ctx.renderer.printSuccess(`\u{1F4CB} Image loaded: ${basename11(imgPath)}`);
|
|
22882
22939
|
await ctx.sendAsChat(`@${imgPath} ${description}`);
|
|
22883
22940
|
}
|
|
22884
22941
|
},
|
|
@@ -23434,6 +23491,11 @@ var SessionHandler = class _SessionHandler {
|
|
|
23434
23491
|
costCnyPerUsd: CNY_PER_USD,
|
|
23435
23492
|
costPricingUnknown,
|
|
23436
23493
|
providers: providerList,
|
|
23494
|
+
hubPresets: loadCustomPresets(this.config.getConfigDir()).presets.map((p) => ({
|
|
23495
|
+
id: p.id,
|
|
23496
|
+
name: p.name,
|
|
23497
|
+
description: p.description
|
|
23498
|
+
})),
|
|
23437
23499
|
branches,
|
|
23438
23500
|
activeBranchId: sess?.activeBranchId ?? "main",
|
|
23439
23501
|
agents: listAgentRuns().slice(0, 20).map((run) => ({
|
|
@@ -23687,7 +23749,8 @@ var SessionHandler = class _SessionHandler {
|
|
|
23687
23749
|
this.send({ type: "error", message: "Hub topic is required." });
|
|
23688
23750
|
return;
|
|
23689
23751
|
}
|
|
23690
|
-
const
|
|
23752
|
+
const presetId = msg.preset ?? "brainstorm";
|
|
23753
|
+
const preset = presetId.startsWith(CUSTOM_PRESET_PREFIX) ? loadCustomPresets(this.config.getConfigDir()).presets.find((p) => p.id === presetId) : getPreset(presetId);
|
|
23691
23754
|
if (!preset) {
|
|
23692
23755
|
this.send({ type: "error", message: `Unknown preset "${msg.preset}".` });
|
|
23693
23756
|
return;
|
|
@@ -24890,8 +24953,8 @@ async function setupProxy(configProxy) {
|
|
|
24890
24953
|
}
|
|
24891
24954
|
|
|
24892
24955
|
// src/web/auth.ts
|
|
24893
|
-
import { existsSync as
|
|
24894
|
-
import { isAbsolute as isAbsolute3, join as
|
|
24956
|
+
import { existsSync as existsSync31, readFileSync as readFileSync22, mkdirSync as mkdirSync16, readdirSync as readdirSync15, openSync, closeSync, unlinkSync as unlinkSync8 } from "fs";
|
|
24957
|
+
import { isAbsolute as isAbsolute3, join as join25, relative as relative5 } from "path";
|
|
24895
24958
|
import { createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2, pbkdf2Sync, pbkdf2 } from "crypto";
|
|
24896
24959
|
var USERS_FILE = "users.json";
|
|
24897
24960
|
var TOKEN_EXPIRY_HOURS = 24;
|
|
@@ -24907,7 +24970,7 @@ var AuthManager = class {
|
|
|
24907
24970
|
loadedRaw;
|
|
24908
24971
|
constructor(baseDir) {
|
|
24909
24972
|
this.baseDir = baseDir;
|
|
24910
|
-
this.usersFile =
|
|
24973
|
+
this.usersFile = join25(baseDir, USERS_FILE);
|
|
24911
24974
|
this.db = this.loadOrCreate();
|
|
24912
24975
|
}
|
|
24913
24976
|
// ── Public API ─────────────────────────────────────────────────
|
|
@@ -24949,10 +25012,10 @@ var AuthManager = class {
|
|
|
24949
25012
|
}
|
|
24950
25013
|
const salt = prepared?.salt ?? randomBytes2(16).toString("hex");
|
|
24951
25014
|
const passwordHash = prepared?.hash ?? this.hashPassword(password, salt);
|
|
24952
|
-
const dataDir =
|
|
24953
|
-
const fullDataDir =
|
|
25015
|
+
const dataDir = join25(USERS_DIR, username);
|
|
25016
|
+
const fullDataDir = join25(this.baseDir, dataDir);
|
|
24954
25017
|
mkdirSync16(fullDataDir, { recursive: true, mode: 448 });
|
|
24955
|
-
mkdirSync16(
|
|
25018
|
+
mkdirSync16(join25(fullDataDir, "history"), { recursive: true, mode: 448 });
|
|
24956
25019
|
const user = {
|
|
24957
25020
|
username,
|
|
24958
25021
|
passwordHash,
|
|
@@ -25112,7 +25175,7 @@ var AuthManager = class {
|
|
|
25112
25175
|
this.refresh();
|
|
25113
25176
|
const user = this.db.users.find((u) => u.username === username);
|
|
25114
25177
|
if (!user) throw new Error(`User not found: ${username}`);
|
|
25115
|
-
return
|
|
25178
|
+
return join25(this.baseDir, user.dataDir);
|
|
25116
25179
|
}
|
|
25117
25180
|
/** List all usernames */
|
|
25118
25181
|
listUsers() {
|
|
@@ -25151,30 +25214,30 @@ var AuthManager = class {
|
|
|
25151
25214
|
const err = this.register(username, password);
|
|
25152
25215
|
if (err) return err;
|
|
25153
25216
|
const userDir = this.getUserDataDir(username);
|
|
25154
|
-
const globalConfig =
|
|
25155
|
-
if (
|
|
25217
|
+
const globalConfig = join25(this.baseDir, "config.json");
|
|
25218
|
+
if (existsSync31(globalConfig)) {
|
|
25156
25219
|
try {
|
|
25157
|
-
const content =
|
|
25158
|
-
atomicWriteFileSync(
|
|
25220
|
+
const content = readFileSync22(globalConfig, "utf-8");
|
|
25221
|
+
atomicWriteFileSync(join25(userDir, "config.json"), content, { mode: 384 });
|
|
25159
25222
|
} catch {
|
|
25160
25223
|
}
|
|
25161
25224
|
}
|
|
25162
|
-
const globalMemory =
|
|
25163
|
-
if (
|
|
25225
|
+
const globalMemory = join25(this.baseDir, "memory.md");
|
|
25226
|
+
if (existsSync31(globalMemory)) {
|
|
25164
25227
|
try {
|
|
25165
|
-
const content =
|
|
25166
|
-
atomicWriteFileSync(
|
|
25228
|
+
const content = readFileSync22(globalMemory, "utf-8");
|
|
25229
|
+
atomicWriteFileSync(join25(userDir, "memory.md"), content, { mode: 384 });
|
|
25167
25230
|
} catch {
|
|
25168
25231
|
}
|
|
25169
25232
|
}
|
|
25170
|
-
const globalHistory =
|
|
25171
|
-
if (
|
|
25233
|
+
const globalHistory = join25(this.baseDir, "history");
|
|
25234
|
+
if (existsSync31(globalHistory)) {
|
|
25172
25235
|
try {
|
|
25173
|
-
const files =
|
|
25174
|
-
const userHistory =
|
|
25236
|
+
const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
|
|
25237
|
+
const userHistory = join25(userDir, "history");
|
|
25175
25238
|
for (const f of files) {
|
|
25176
25239
|
try {
|
|
25177
|
-
atomicWriteFileSync(
|
|
25240
|
+
atomicWriteFileSync(join25(userHistory, f), readFileSync22(join25(globalHistory, f), "utf8"), { mode: 384 });
|
|
25178
25241
|
} catch {
|
|
25179
25242
|
}
|
|
25180
25243
|
}
|
|
@@ -25185,16 +25248,16 @@ var AuthManager = class {
|
|
|
25185
25248
|
}
|
|
25186
25249
|
// ── Private methods ────────────────────────────────────────────
|
|
25187
25250
|
refresh() {
|
|
25188
|
-
const raw =
|
|
25251
|
+
const raw = readFileSync22(this.usersFile, "utf8");
|
|
25189
25252
|
const parsed = JSON.parse(raw);
|
|
25190
25253
|
if (!this.isValidUsersDB(parsed)) throw new Error("Authentication database is invalid; access refused");
|
|
25191
25254
|
this.db = parsed;
|
|
25192
25255
|
this.loadedRaw = raw;
|
|
25193
25256
|
}
|
|
25194
25257
|
loadOrCreate() {
|
|
25195
|
-
if (
|
|
25258
|
+
if (existsSync31(this.usersFile)) {
|
|
25196
25259
|
try {
|
|
25197
|
-
const raw =
|
|
25260
|
+
const raw = readFileSync22(this.usersFile, "utf-8");
|
|
25198
25261
|
const parsed = JSON.parse(raw);
|
|
25199
25262
|
if (!this.isValidUsersDB(parsed)) {
|
|
25200
25263
|
throw new Error("database structure is invalid");
|
|
@@ -25230,7 +25293,7 @@ var AuthManager = class {
|
|
|
25230
25293
|
if (typeof record.username !== "string" || !/^[a-z0-9_-]{2,32}$/.test(record.username) || usernames.has(record.username) || typeof record.passwordHash !== "string" || record.passwordHash.length === 0 || typeof record.salt !== "string" || record.salt.length === 0 || typeof record.createdAt !== "string" || typeof record.dataDir !== "string" || record.dataDir.length === 0 || isAbsolute3(record.dataDir)) {
|
|
25231
25294
|
return false;
|
|
25232
25295
|
}
|
|
25233
|
-
const dataDirFromBase = relative5(this.baseDir,
|
|
25296
|
+
const dataDirFromBase = relative5(this.baseDir, join25(this.baseDir, record.dataDir));
|
|
25234
25297
|
if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
|
|
25235
25298
|
if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
|
|
25236
25299
|
if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
|
|
@@ -25246,7 +25309,7 @@ var AuthManager = class {
|
|
|
25246
25309
|
const lock = this.usersFile + ".lock";
|
|
25247
25310
|
const fd = openSync(lock, "wx", 384);
|
|
25248
25311
|
try {
|
|
25249
|
-
const current =
|
|
25312
|
+
const current = existsSync31(this.usersFile) ? readFileSync22(this.usersFile, "utf8") : void 0;
|
|
25250
25313
|
if (current !== this.loadedRaw) throw new Error("Authentication database changed concurrently; retry the operation");
|
|
25251
25314
|
const raw = JSON.stringify(db, null, 2);
|
|
25252
25315
|
atomicWriteFileSync(this.usersFile, raw, { mode: 384 });
|
|
@@ -25380,8 +25443,8 @@ async function startWebServer(options = {}) {
|
|
|
25380
25443
|
}
|
|
25381
25444
|
}
|
|
25382
25445
|
let skillManager = null;
|
|
25383
|
-
const skillsDir =
|
|
25384
|
-
if (
|
|
25446
|
+
const skillsDir = join26(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
25447
|
+
if (existsSync32(skillsDir)) {
|
|
25385
25448
|
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
25386
25449
|
skillManager.loadSkills(pluginAssets.skillDirs);
|
|
25387
25450
|
const count = skillManager.listSkills().length;
|
|
@@ -25474,15 +25537,15 @@ async function startWebServer(options = {}) {
|
|
|
25474
25537
|
next();
|
|
25475
25538
|
};
|
|
25476
25539
|
const moduleDir = getModuleDir();
|
|
25477
|
-
let clientDir =
|
|
25478
|
-
if (!
|
|
25479
|
-
clientDir =
|
|
25540
|
+
let clientDir = join26(moduleDir, "web", "client");
|
|
25541
|
+
if (!existsSync32(clientDir)) {
|
|
25542
|
+
clientDir = join26(moduleDir, "client");
|
|
25480
25543
|
}
|
|
25481
|
-
if (!
|
|
25482
|
-
clientDir =
|
|
25544
|
+
if (!existsSync32(clientDir)) {
|
|
25545
|
+
clientDir = join26(moduleDir, "..", "..", "src", "web", "client");
|
|
25483
25546
|
}
|
|
25484
|
-
if (!
|
|
25485
|
-
clientDir =
|
|
25547
|
+
if (!existsSync32(clientDir)) {
|
|
25548
|
+
clientDir = join26(process.cwd(), "src", "web", "client");
|
|
25486
25549
|
}
|
|
25487
25550
|
console.log(` Static files: ${clientDir}`);
|
|
25488
25551
|
const PRECOMPRESSED_TYPES = {
|
|
@@ -25502,14 +25565,14 @@ async function startWebServer(options = {}) {
|
|
|
25502
25565
|
const encoding = /\bbr\b/.test(accept) ? "br" : /\bgzip\b/.test(accept) ? "gzip" : null;
|
|
25503
25566
|
if (!encoding) return next();
|
|
25504
25567
|
const target = resolvePath(clientDir, `.${req.path}`) + (encoding === "br" ? ".br" : ".gz");
|
|
25505
|
-
if (!target.startsWith(clientDir) || !
|
|
25568
|
+
if (!target.startsWith(clientDir) || !existsSync32(target)) return next();
|
|
25506
25569
|
res.setHeader("Content-Type", contentType);
|
|
25507
25570
|
res.setHeader("Content-Encoding", encoding);
|
|
25508
25571
|
res.setHeader("Vary", "Accept-Encoding");
|
|
25509
25572
|
if (req.path.startsWith("/vendor/")) res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
25510
25573
|
createReadStream(target).pipe(res);
|
|
25511
25574
|
});
|
|
25512
|
-
app.use("/vendor", express.static(
|
|
25575
|
+
app.use("/vendor", express.static(join26(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
|
|
25513
25576
|
app.use(express.static(clientDir));
|
|
25514
25577
|
app.get("/api/status", (_req, res) => {
|
|
25515
25578
|
res.json({
|
|
@@ -25600,7 +25663,7 @@ async function startWebServer(options = {}) {
|
|
|
25600
25663
|
app.get("/api/files", requireAuth, (req, res) => {
|
|
25601
25664
|
const cwd = process.cwd();
|
|
25602
25665
|
const prefix = req.query.prefix || "";
|
|
25603
|
-
const targetDir =
|
|
25666
|
+
const targetDir = join26(cwd, prefix);
|
|
25604
25667
|
try {
|
|
25605
25668
|
const canonicalTarget = realpathSync3(resolve12(targetDir));
|
|
25606
25669
|
const canonicalCwd = realpathSync3(resolve12(cwd));
|
|
@@ -25614,10 +25677,10 @@ async function startWebServer(options = {}) {
|
|
|
25614
25677
|
}
|
|
25615
25678
|
try {
|
|
25616
25679
|
const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
|
|
25617
|
-
const entries =
|
|
25680
|
+
const entries = readdirSync16(targetDir, { withFileTypes: true });
|
|
25618
25681
|
const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
|
|
25619
25682
|
name: e.name,
|
|
25620
|
-
path: relative6(cwd,
|
|
25683
|
+
path: relative6(cwd, join26(targetDir, e.name)).replace(/\\/g, "/"),
|
|
25621
25684
|
isDir: e.isDirectory()
|
|
25622
25685
|
}));
|
|
25623
25686
|
res.json({ files });
|
|
@@ -25657,8 +25720,8 @@ async function startWebServer(options = {}) {
|
|
|
25657
25720
|
try {
|
|
25658
25721
|
const authUser = req._authUser;
|
|
25659
25722
|
const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
|
|
25660
|
-
const filePath =
|
|
25661
|
-
if (!
|
|
25723
|
+
const filePath = join26(histDir, `${id}.json`);
|
|
25724
|
+
if (!existsSync32(filePath)) {
|
|
25662
25725
|
res.status(404).json({ error: "Session not found" });
|
|
25663
25726
|
return;
|
|
25664
25727
|
}
|
|
@@ -25673,7 +25736,7 @@ async function startWebServer(options = {}) {
|
|
|
25673
25736
|
res.status(404).json({ error: "Session not found" });
|
|
25674
25737
|
return;
|
|
25675
25738
|
}
|
|
25676
|
-
const data = JSON.parse(
|
|
25739
|
+
const data = JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
25677
25740
|
res.json({ session: data });
|
|
25678
25741
|
} catch (err) {
|
|
25679
25742
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
@@ -25686,7 +25749,7 @@ async function startWebServer(options = {}) {
|
|
|
25686
25749
|
return;
|
|
25687
25750
|
}
|
|
25688
25751
|
const cwd = process.cwd();
|
|
25689
|
-
const fullPath = resolve12(
|
|
25752
|
+
const fullPath = resolve12(join26(cwd, filePath));
|
|
25690
25753
|
try {
|
|
25691
25754
|
const canonicalFull = realpathSync3(fullPath);
|
|
25692
25755
|
assertReadablePath(canonicalFull);
|
|
@@ -25705,7 +25768,7 @@ async function startWebServer(options = {}) {
|
|
|
25705
25768
|
res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
|
|
25706
25769
|
return;
|
|
25707
25770
|
}
|
|
25708
|
-
const content =
|
|
25771
|
+
const content = readFileSync23(fullPath, "utf-8");
|
|
25709
25772
|
res.json({ content, size: stat.size });
|
|
25710
25773
|
} catch {
|
|
25711
25774
|
res.json({ error: "Cannot read file" });
|
|
@@ -26042,17 +26105,17 @@ function resolveProjectMcpPath() {
|
|
|
26042
26105
|
const cwd = process.cwd();
|
|
26043
26106
|
const gitRoot = getGitRoot(cwd);
|
|
26044
26107
|
const projectRoot = gitRoot ?? cwd;
|
|
26045
|
-
const configPath =
|
|
26046
|
-
return
|
|
26108
|
+
const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
26109
|
+
return existsSync32(configPath) ? configPath : null;
|
|
26047
26110
|
}
|
|
26048
26111
|
function loadProjectMcpConfig() {
|
|
26049
26112
|
const cwd = process.cwd();
|
|
26050
26113
|
const gitRoot = getGitRoot(cwd);
|
|
26051
26114
|
const projectRoot = gitRoot ?? cwd;
|
|
26052
|
-
const configPath =
|
|
26053
|
-
if (!
|
|
26115
|
+
const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
26116
|
+
if (!existsSync32(configPath)) return null;
|
|
26054
26117
|
try {
|
|
26055
|
-
const raw = JSON.parse(
|
|
26118
|
+
const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
|
|
26056
26119
|
return raw.mcpServers ?? raw;
|
|
26057
26120
|
} catch {
|
|
26058
26121
|
return null;
|