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