jinzd-ai-cli 0.4.246 → 0.4.247
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/README.zh-CN.md +8 -3
- package/dist/{batch-AHW7WALD.js → batch-UE7XQMQB.js} +2 -2
- package/dist/{chat-index-ALUHFJKI.js → chat-index-7MMTGQNA.js} +2 -2
- package/dist/{chat-index-ML5FF5L6.js → chat-index-Q6BKWWAM.js} +1 -1
- package/dist/{chunk-XK22CVID.js → chunk-3IIKIWT2.js} +1 -1
- package/dist/{chunk-WYNPWHXB.js → chunk-3IM53IFO.js} +1 -1
- package/dist/{chunk-LZGPGPA6.js → chunk-4EZWVX7G.js} +1 -1
- package/dist/{chunk-DJDEXHOT.js → chunk-4GKWLTU3.js} +4 -4
- package/dist/{chunk-YQUBYTDR.js → chunk-6Q2XAWKP.js} +1 -1
- package/dist/{chunk-IGPFYNZA.js → chunk-6RPGQ5CG.js} +1 -1
- package/dist/{chunk-K3CF65QH.js → chunk-GLSR2NR3.js} +1 -1
- package/dist/{chunk-USJF35NB.js → chunk-IP7LPVRW.js} +1 -1
- package/dist/{chunk-DT77O33T.js → chunk-JQXXPTWL.js} +1 -1
- package/dist/{chunk-LEKOBVOQ.js → chunk-KPRU6QY3.js} +4 -5
- package/dist/{chunk-PJ3ONBWZ.js → chunk-NYNSYLFY.js} +1 -1
- package/dist/{chunk-KWQKQVPH.js → chunk-OBULDJSU.js} +1 -1
- package/dist/{chunk-GQYRPBIQ.js → chunk-Q2OMGJIQ.js} +12 -12
- package/dist/{chunk-BNERFXVO.js → chunk-QCG6UU2S.js} +1 -1
- package/dist/{chunk-CJ3BPLHZ.js → chunk-REBKFMF3.js} +1 -1
- package/dist/{chunk-Z7JROM3J.js → chunk-RZV6WSER.js} +1 -1
- package/dist/{chunk-QYQI7ZWK.js → chunk-S7ZS7X23.js} +0 -1
- package/dist/{chunk-OMSOAFXY.js → chunk-TBXMRJHS.js} +1 -1
- package/dist/{chunk-P2LB6S4I.js → chunk-VN6OGMSV.js} +1 -1
- package/dist/{chunk-6Y42RN5H.js → chunk-VPM5WRJ2.js} +4 -4
- package/dist/{chunk-NV63EYFL.js → chunk-ZWEZNKDW.js} +1 -1
- package/dist/{ci-VOGIC6S4.js → ci-EY6USUO7.js} +5 -5
- package/dist/{ci-format-BHCSMT5U.js → ci-format-CZNUUWEV.js} +2 -2
- package/dist/{constants-J4OLBH72.js → constants-UDRMWAPN.js} +1 -1
- package/dist/{doctor-cli-IR3E3XHB.js → doctor-cli-GY654USP.js} +5 -5
- package/dist/electron-server.js +154 -136
- package/dist/{hub-SFFFYMGO.js → hub-L2WX4255.js} +2 -2
- package/dist/index.js +29 -30
- package/dist/{indexer-4WWS3VIL.js → indexer-M2LJGTY2.js} +1 -1
- package/dist/{indexer-2AG4G6B5.js → indexer-VZETNE4H.js} +1 -1
- package/dist/{persist-WGIJ6RXY.js → persist-A2QSXYFY.js} +3 -3
- package/dist/{persistent-memory-EKZ2JF7M.js → persistent-memory-G24RJ5LA.js} +2 -2
- package/dist/{persistent-memory-3KH2EVHA.js → persistent-memory-JCX3P2CF.js} +2 -2
- package/dist/{pr-BNS3OHDM.js → pr-B5P2M6DV.js} +5 -5
- package/dist/{run-tests-PW4WC4OG.js → run-tests-N2JQGL4C.js} +2 -2
- package/dist/{run-tests-ZKHXKCQB.js → run-tests-QEIR322E.js} +2 -2
- package/dist/{server-3HLBEWNZ.js → server-4OAE6OEK.js} +8 -8
- package/dist/{server-D2ID3GYA.js → server-QDMMCD3O.js} +112 -92
- package/dist/{task-orchestrator-FMCI4RPX.js → task-orchestrator-VZXU2HK3.js} +8 -9
- package/dist/{usage-DPLNMDSJ.js → usage-LH3LNYAS.js} +2 -2
- package/package.json +5 -4
package/dist/electron-server.js
CHANGED
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
searchCandidates,
|
|
8
8
|
searchChatMemory,
|
|
9
9
|
updateSessionInIndex
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZWEZNKDW.js";
|
|
11
11
|
import {
|
|
12
12
|
fileCheckpoints
|
|
13
13
|
} from "./chunk-SKET65WZ.js";
|
|
14
14
|
import {
|
|
15
15
|
indexProject
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-QCG6UU2S.js";
|
|
17
17
|
import {
|
|
18
18
|
addMemoryEntry,
|
|
19
19
|
clearMemoryEntries,
|
|
@@ -34,14 +34,14 @@ import {
|
|
|
34
34
|
touchMemoryReferences,
|
|
35
35
|
updateMemoryApproval,
|
|
36
36
|
updateMemoryEntry
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-REBKFMF3.js";
|
|
38
38
|
import {
|
|
39
39
|
redactJson,
|
|
40
40
|
scanString
|
|
41
41
|
} from "./chunk-YVTASHS5.js";
|
|
42
42
|
import {
|
|
43
43
|
runTestsTool
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-IP7LPVRW.js";
|
|
45
45
|
import {
|
|
46
46
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
47
47
|
APP_NAME,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
74
74
|
VERSION,
|
|
75
75
|
buildUserIdentityPrompt
|
|
76
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-4EZWVX7G.js";
|
|
77
77
|
import {
|
|
78
78
|
hasSemanticIndex,
|
|
79
79
|
semanticSearch
|
|
@@ -91,8 +91,8 @@ import {
|
|
|
91
91
|
import express from "express";
|
|
92
92
|
import { createServer } from "http";
|
|
93
93
|
import { WebSocketServer } from "ws";
|
|
94
|
-
import { join as
|
|
95
|
-
import { existsSync as
|
|
94
|
+
import { join as join25, dirname as dirname10, resolve as resolve10, relative as relative6, sep as sep4 } from "path";
|
|
95
|
+
import { existsSync as existsSync30, readFileSync as readFileSync23, readdirSync as readdirSync15, statSync as statSync13, realpathSync as realpathSync3 } from "fs";
|
|
96
96
|
import { networkInterfaces } from "os";
|
|
97
97
|
|
|
98
98
|
// src/config/config-manager.ts
|
|
@@ -2982,7 +2982,6 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
2982
2982
|
const message = firstChoice.message;
|
|
2983
2983
|
const finishReason = firstChoice.finish_reason;
|
|
2984
2984
|
const usage = toUsage(response.usage);
|
|
2985
|
-
const contentStr = typeof message.content === "string" ? message.content : "";
|
|
2986
2985
|
const hasToolCalls = !!(message.tool_calls && message.tool_calls.length > 0);
|
|
2987
2986
|
const reasoningContent = message.reasoning_content;
|
|
2988
2987
|
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
@@ -4996,7 +4995,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
4996
4995
|
const markerStart = `AICLI_MARKER_START:${id}`;
|
|
4997
4996
|
const markerEnd = `AICLI_MARKER_END:${id}`;
|
|
4998
4997
|
const wrappedCmd = IS_WINDOWS2 ? `${WIN_UTF8_PREAMBLE} echo "${markerStart}"; ${command}; echo "${markerEnd}:0"` : `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
|
|
4999
|
-
return new Promise((
|
|
4998
|
+
return new Promise((resolve11) => {
|
|
5000
4999
|
let stdout = "";
|
|
5001
5000
|
let stderr = "";
|
|
5002
5001
|
let timedOut = false;
|
|
@@ -5008,11 +5007,11 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5008
5007
|
stdout += IS_WINDOWS2 ? decodeWindowsBuffer(chunk) : chunk.toString("utf-8");
|
|
5009
5008
|
if (!resolved && stdout.includes(markerEndPattern)) {
|
|
5010
5009
|
const endLine = stdout.split("\n").find((l) => l.includes(markerEndPattern));
|
|
5011
|
-
const exitCode = endLine ? parseEndMarker(endLine
|
|
5010
|
+
const exitCode = endLine ? parseEndMarker(endLine) : null;
|
|
5012
5011
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5013
5012
|
resolved = true;
|
|
5014
5013
|
cleanup();
|
|
5015
|
-
|
|
5014
|
+
resolve11({ stdout, stderr, exitCode, timedOut, aborted });
|
|
5016
5015
|
}
|
|
5017
5016
|
};
|
|
5018
5017
|
const onErr = (chunk) => {
|
|
@@ -5027,7 +5026,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5027
5026
|
resolved = true;
|
|
5028
5027
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5029
5028
|
cleanup();
|
|
5030
|
-
|
|
5029
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5031
5030
|
killProcessTree(proc);
|
|
5032
5031
|
pool.delete(sessionKey);
|
|
5033
5032
|
}, timeout);
|
|
@@ -5037,7 +5036,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5037
5036
|
resolved = true;
|
|
5038
5037
|
cleanup();
|
|
5039
5038
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5040
|
-
|
|
5039
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5041
5040
|
killProcessTree(proc);
|
|
5042
5041
|
pool.delete(sessionKey);
|
|
5043
5042
|
};
|
|
@@ -5052,7 +5051,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5052
5051
|
stderr += `
|
|
5053
5052
|
[pool error] ${err.message}`;
|
|
5054
5053
|
cleanup();
|
|
5055
|
-
|
|
5054
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5056
5055
|
pool.delete(sessionKey);
|
|
5057
5056
|
};
|
|
5058
5057
|
proc.on("error", onError);
|
|
@@ -5065,7 +5064,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5065
5064
|
}
|
|
5066
5065
|
try {
|
|
5067
5066
|
proc.stdin?.write(wrappedCmd + "\n");
|
|
5068
|
-
} catch
|
|
5067
|
+
} catch {
|
|
5069
5068
|
if (!resolved) {
|
|
5070
5069
|
cleanup();
|
|
5071
5070
|
pool.delete(sessionKey);
|
|
@@ -5073,7 +5072,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5073
5072
|
}
|
|
5074
5073
|
});
|
|
5075
5074
|
}
|
|
5076
|
-
function parseEndMarker(line
|
|
5075
|
+
function parseEndMarker(line) {
|
|
5077
5076
|
const idx = line.lastIndexOf(":");
|
|
5078
5077
|
if (idx < 0) return null;
|
|
5079
5078
|
const code = line.slice(idx + 1).trim();
|
|
@@ -7210,7 +7209,7 @@ var ToolExecutor = class {
|
|
|
7210
7209
|
};
|
|
7211
7210
|
}
|
|
7212
7211
|
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
7213
|
-
this.printToolCall(call);
|
|
7212
|
+
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
7214
7213
|
try {
|
|
7215
7214
|
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
7216
7215
|
const content = truncateOutput(rawContent, call.name);
|
|
@@ -7441,7 +7440,7 @@ var ToolExecutor = class {
|
|
|
7441
7440
|
rl.resume();
|
|
7442
7441
|
process.stdout.write(prompt);
|
|
7443
7442
|
this.confirming = true;
|
|
7444
|
-
return new Promise((
|
|
7443
|
+
return new Promise((resolve11) => {
|
|
7445
7444
|
let completed = false;
|
|
7446
7445
|
const cleanup = (result) => {
|
|
7447
7446
|
if (completed) return;
|
|
@@ -7451,7 +7450,7 @@ var ToolExecutor = class {
|
|
|
7451
7450
|
rl.pause();
|
|
7452
7451
|
rlAny.output = savedOutput;
|
|
7453
7452
|
this.confirming = false;
|
|
7454
|
-
|
|
7453
|
+
resolve11(result);
|
|
7455
7454
|
};
|
|
7456
7455
|
const onLine = (line) => {
|
|
7457
7456
|
const trimmed = line.trim();
|
|
@@ -7625,7 +7624,7 @@ var ToolExecutor = class {
|
|
|
7625
7624
|
rl.resume();
|
|
7626
7625
|
process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
|
|
7627
7626
|
this.confirming = true;
|
|
7628
|
-
return new Promise((
|
|
7627
|
+
return new Promise((resolve11) => {
|
|
7629
7628
|
let completed = false;
|
|
7630
7629
|
const cleanup = (answer) => {
|
|
7631
7630
|
if (completed) return;
|
|
@@ -7635,7 +7634,7 @@ var ToolExecutor = class {
|
|
|
7635
7634
|
rl.pause();
|
|
7636
7635
|
rlAny.output = savedOutput;
|
|
7637
7636
|
this.confirming = false;
|
|
7638
|
-
|
|
7637
|
+
resolve11(answer === "y");
|
|
7639
7638
|
};
|
|
7640
7639
|
const onLine = (line) => {
|
|
7641
7640
|
const trimmed = line.trim();
|
|
@@ -7816,7 +7815,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
|
|
|
7816
7815
|
const mode = appendMode ? "appended" : "written";
|
|
7817
7816
|
void (async () => {
|
|
7818
7817
|
try {
|
|
7819
|
-
const { updateFile } = await import("./indexer-
|
|
7818
|
+
const { updateFile } = await import("./indexer-M2LJGTY2.js");
|
|
7820
7819
|
await updateFile(process.cwd(), filePath);
|
|
7821
7820
|
} catch {
|
|
7822
7821
|
}
|
|
@@ -8884,7 +8883,7 @@ var runInteractiveTool = {
|
|
|
8884
8883
|
PYTHONDONTWRITEBYTECODE: "1"
|
|
8885
8884
|
};
|
|
8886
8885
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
8887
|
-
return new Promise((
|
|
8886
|
+
return new Promise((resolve11) => {
|
|
8888
8887
|
const child = spawn4(executable, cmdArgs.map(String), {
|
|
8889
8888
|
cwd: process.cwd(),
|
|
8890
8889
|
env,
|
|
@@ -8917,22 +8916,22 @@ var runInteractiveTool = {
|
|
|
8917
8916
|
setTimeout(writeNextLine, 400);
|
|
8918
8917
|
const timer = setTimeout(() => {
|
|
8919
8918
|
child.kill();
|
|
8920
|
-
|
|
8919
|
+
resolve11(`${prefixWarnings}[Timeout after ${timeout}ms]
|
|
8921
8920
|
${buildOutput(stdout, stderr)}`);
|
|
8922
8921
|
}, timeout);
|
|
8923
8922
|
child.on("close", (code) => {
|
|
8924
8923
|
clearTimeout(timer);
|
|
8925
8924
|
const output = buildOutput(stdout, stderr);
|
|
8926
8925
|
if (code !== 0 && code !== null) {
|
|
8927
|
-
|
|
8926
|
+
resolve11(`${prefixWarnings}Exit code ${code}:
|
|
8928
8927
|
${output}`);
|
|
8929
8928
|
} else {
|
|
8930
|
-
|
|
8929
|
+
resolve11(`${prefixWarnings}${output || "(no output)"}`);
|
|
8931
8930
|
}
|
|
8932
8931
|
});
|
|
8933
8932
|
child.on("error", (err) => {
|
|
8934
8933
|
clearTimeout(timer);
|
|
8935
|
-
|
|
8934
|
+
resolve11(
|
|
8936
8935
|
`${prefixWarnings}Failed to start process "${executable}": ${err.message}
|
|
8937
8936
|
Hint: On Windows, use the full path to the executable, e.g.:
|
|
8938
8937
|
C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
|
|
@@ -9235,7 +9234,7 @@ var webFetchTool = {
|
|
|
9235
9234
|
} else {
|
|
9236
9235
|
const title = extractTitle(rawHtml);
|
|
9237
9236
|
const desc = extractDescription(rawHtml);
|
|
9238
|
-
|
|
9237
|
+
const body = htmlToText(rawHtml);
|
|
9239
9238
|
const header = [
|
|
9240
9239
|
title ? `# ${title}` : "",
|
|
9241
9240
|
desc ? `> ${desc}` : "",
|
|
@@ -9754,7 +9753,7 @@ function promptUser(rl, question) {
|
|
|
9754
9753
|
console.log();
|
|
9755
9754
|
console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
|
|
9756
9755
|
process.stdout.write(chalk4.cyan("> "));
|
|
9757
|
-
return new Promise((
|
|
9756
|
+
return new Promise((resolve11) => {
|
|
9758
9757
|
let completed = false;
|
|
9759
9758
|
const cleanup = (answer) => {
|
|
9760
9759
|
if (completed) return;
|
|
@@ -9764,7 +9763,7 @@ function promptUser(rl, question) {
|
|
|
9764
9763
|
rl.pause();
|
|
9765
9764
|
rlAny.output = savedOutput;
|
|
9766
9765
|
askUserContext.prompting = false;
|
|
9767
|
-
|
|
9766
|
+
resolve11(answer);
|
|
9768
9767
|
};
|
|
9769
9768
|
const onLine = (line) => {
|
|
9770
9769
|
cleanup(line);
|
|
@@ -12320,7 +12319,7 @@ var McpClient = class {
|
|
|
12320
12319
|
// 内部方法:JSON-RPC 通信
|
|
12321
12320
|
// ══════════════════════════════════════════════════════════════════
|
|
12322
12321
|
sendRequest(method, params) {
|
|
12323
|
-
return new Promise((
|
|
12322
|
+
return new Promise((resolve11, reject) => {
|
|
12324
12323
|
if (!this.process?.stdin?.writable) {
|
|
12325
12324
|
return reject(new Error(`MCP server [${this.serverId}] stdin not writable`));
|
|
12326
12325
|
}
|
|
@@ -12332,19 +12331,18 @@ var McpClient = class {
|
|
|
12332
12331
|
method,
|
|
12333
12332
|
...params !== void 0 ? { params } : {}
|
|
12334
12333
|
};
|
|
12335
|
-
let timer;
|
|
12336
12334
|
const cleanup = () => {
|
|
12337
12335
|
this.pendingRequests.delete(id);
|
|
12338
12336
|
clearTimeout(timer);
|
|
12339
12337
|
};
|
|
12340
|
-
timer = setTimeout(() => {
|
|
12338
|
+
const timer = setTimeout(() => {
|
|
12341
12339
|
cleanup();
|
|
12342
12340
|
reject(new Error(`MCP request [${method}] timed out (internal)`));
|
|
12343
12341
|
}, MCP_CALL_TIMEOUT * 2);
|
|
12344
12342
|
this.pendingRequests.set(id, {
|
|
12345
12343
|
resolve: (result) => {
|
|
12346
12344
|
cleanup();
|
|
12347
|
-
|
|
12345
|
+
resolve11(result);
|
|
12348
12346
|
},
|
|
12349
12347
|
reject: (error) => {
|
|
12350
12348
|
cleanup();
|
|
@@ -12421,13 +12419,13 @@ var McpClient = class {
|
|
|
12421
12419
|
}
|
|
12422
12420
|
/** Promise 超时包装 */
|
|
12423
12421
|
withTimeout(promise, ms, label) {
|
|
12424
|
-
return new Promise((
|
|
12422
|
+
return new Promise((resolve11, reject) => {
|
|
12425
12423
|
const timer = setTimeout(() => {
|
|
12426
12424
|
reject(new Error(`MCP [${this.serverId}] ${label} timed out after ${ms}ms`));
|
|
12427
12425
|
}, ms);
|
|
12428
12426
|
promise.then((val) => {
|
|
12429
12427
|
clearTimeout(timer);
|
|
12430
|
-
|
|
12428
|
+
resolve11(val);
|
|
12431
12429
|
}).catch((err) => {
|
|
12432
12430
|
clearTimeout(timer);
|
|
12433
12431
|
reject(err);
|
|
@@ -12931,33 +12929,33 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
12931
12929
|
}
|
|
12932
12930
|
/** Resolve a pending confirm from client response */
|
|
12933
12931
|
resolveConfirm(requestId, approved) {
|
|
12934
|
-
const
|
|
12935
|
-
if (
|
|
12932
|
+
const resolve11 = this.pendingConfirms.get(requestId);
|
|
12933
|
+
if (resolve11) {
|
|
12936
12934
|
this.clearPendingTimer(requestId);
|
|
12937
12935
|
this.pendingConfirms.delete(requestId);
|
|
12938
12936
|
this.confirming = false;
|
|
12939
|
-
|
|
12937
|
+
resolve11(approved);
|
|
12940
12938
|
}
|
|
12941
12939
|
}
|
|
12942
12940
|
/** Resolve a pending batch confirm from client response */
|
|
12943
12941
|
resolveBatchConfirm(requestId, decision) {
|
|
12944
|
-
const
|
|
12945
|
-
if (
|
|
12942
|
+
const resolve11 = this.pendingBatchConfirms.get(requestId);
|
|
12943
|
+
if (resolve11) {
|
|
12946
12944
|
this.clearPendingTimer(requestId);
|
|
12947
12945
|
this.pendingBatchConfirms.delete(requestId);
|
|
12948
12946
|
this.confirming = false;
|
|
12949
12947
|
if (decision === "all" || decision === "none") {
|
|
12950
|
-
|
|
12948
|
+
resolve11(decision);
|
|
12951
12949
|
} else {
|
|
12952
|
-
|
|
12950
|
+
resolve11(new Set(decision));
|
|
12953
12951
|
}
|
|
12954
12952
|
}
|
|
12955
12953
|
}
|
|
12956
12954
|
/** Cancel all pending confirms (e.g., on disconnect) */
|
|
12957
12955
|
cancelAll() {
|
|
12958
|
-
for (const
|
|
12956
|
+
for (const resolve11 of this.pendingConfirms.values()) resolve11(false);
|
|
12959
12957
|
this.pendingConfirms.clear();
|
|
12960
|
-
for (const
|
|
12958
|
+
for (const resolve11 of this.pendingBatchConfirms.values()) resolve11("none");
|
|
12961
12959
|
this.pendingBatchConfirms.clear();
|
|
12962
12960
|
this.confirming = false;
|
|
12963
12961
|
}
|
|
@@ -13033,8 +13031,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13033
13031
|
diff: this.getDiffPreview(call)
|
|
13034
13032
|
};
|
|
13035
13033
|
this.send(msg);
|
|
13036
|
-
return new Promise((
|
|
13037
|
-
this.pendingConfirms.set(requestId,
|
|
13034
|
+
return new Promise((resolve11) => {
|
|
13035
|
+
this.pendingConfirms.set(requestId, resolve11);
|
|
13038
13036
|
this.pendingTimers.set(requestId, setTimeout(() => {
|
|
13039
13037
|
if (this.pendingConfirms.has(requestId)) {
|
|
13040
13038
|
this.resolveConfirm(requestId, false);
|
|
@@ -13058,8 +13056,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13058
13056
|
files
|
|
13059
13057
|
};
|
|
13060
13058
|
this.send(msg);
|
|
13061
|
-
return new Promise((
|
|
13062
|
-
this.pendingBatchConfirms.set(requestId,
|
|
13059
|
+
return new Promise((resolve11) => {
|
|
13060
|
+
this.pendingBatchConfirms.set(requestId, resolve11);
|
|
13063
13061
|
this.pendingTimers.set(requestId, setTimeout(() => {
|
|
13064
13062
|
if (this.pendingBatchConfirms.has(requestId)) {
|
|
13065
13063
|
this.resolveBatchConfirm(requestId, "none");
|
|
@@ -13169,7 +13167,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13169
13167
|
return { callId: call.id, content: rejectionMsg, isError: true };
|
|
13170
13168
|
}
|
|
13171
13169
|
}
|
|
13172
|
-
this.sendToolCallStart(call);
|
|
13170
|
+
if (!toolCallStarted) this.sendToolCallStart(call);
|
|
13173
13171
|
if (this.sessionAutoMode && networkPermission?.action !== "confirm") {
|
|
13174
13172
|
const classification = defaultActionClassifier.classify(call, dangerLevel, {
|
|
13175
13173
|
workspaceRoot: this.workspaceRoot,
|
|
@@ -13548,7 +13546,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
13548
13546
|
const originalSize = JSON.stringify(session.toJSON()).length;
|
|
13549
13547
|
if (originalSize <= sizeLimit) return false;
|
|
13550
13548
|
const snapshotLen = session.messages.length;
|
|
13551
|
-
|
|
13549
|
+
const working = cloneMessages(session.messages.slice(0, snapshotLen));
|
|
13552
13550
|
let committedSize = originalSize;
|
|
13553
13551
|
let anyTrim = false;
|
|
13554
13552
|
let keepRecent = 10;
|
|
@@ -15113,7 +15111,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
15113
15111
|
Cost: ${formatCost(cost)}` : "";
|
|
15114
15112
|
let memoryLine = "";
|
|
15115
15113
|
try {
|
|
15116
|
-
const { countPendingMemories } = await import("./persistent-memory-
|
|
15114
|
+
const { countPendingMemories } = await import("./persistent-memory-G24RJ5LA.js");
|
|
15117
15115
|
const pending = countPendingMemories(ctx.config.getConfigDir());
|
|
15118
15116
|
if (pending > 0) memoryLine = `
|
|
15119
15117
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -15420,7 +15418,7 @@ async function handleBranch(args, ctx) {
|
|
|
15420
15418
|
return;
|
|
15421
15419
|
}
|
|
15422
15420
|
const sub = args[0]?.toLowerCase();
|
|
15423
|
-
const
|
|
15421
|
+
const resolve11 = (ref) => {
|
|
15424
15422
|
const r = session.resolveBranchRef(ref);
|
|
15425
15423
|
if (r.ok) return r.id;
|
|
15426
15424
|
if (r.reason === "ambiguous") {
|
|
@@ -15474,7 +15472,7 @@ async function handleBranch(args, ctx) {
|
|
|
15474
15472
|
ctx.send({ type: "error", message: "Usage: /branch switch <id|title>" });
|
|
15475
15473
|
return;
|
|
15476
15474
|
}
|
|
15477
|
-
const id =
|
|
15475
|
+
const id = resolve11(ref);
|
|
15478
15476
|
if (!id) return;
|
|
15479
15477
|
const ok = session.switchBranch(id);
|
|
15480
15478
|
if (ok) {
|
|
@@ -15494,7 +15492,7 @@ async function handleBranch(args, ctx) {
|
|
|
15494
15492
|
ctx.send({ type: "error", message: "Usage: /branch delete <id|title>" });
|
|
15495
15493
|
return;
|
|
15496
15494
|
}
|
|
15497
|
-
const id =
|
|
15495
|
+
const id = resolve11(ref);
|
|
15498
15496
|
if (!id) return;
|
|
15499
15497
|
const ok = session.deleteBranch(id);
|
|
15500
15498
|
if (ok) {
|
|
@@ -15513,7 +15511,7 @@ async function handleBranch(args, ctx) {
|
|
|
15513
15511
|
ctx.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
|
|
15514
15512
|
return;
|
|
15515
15513
|
}
|
|
15516
|
-
const id =
|
|
15514
|
+
const id = resolve11(ref);
|
|
15517
15515
|
if (!id) return;
|
|
15518
15516
|
const ok = session.renameBranch(id, title);
|
|
15519
15517
|
if (ok) {
|
|
@@ -15531,7 +15529,7 @@ async function handleBranch(args, ctx) {
|
|
|
15531
15529
|
ctx.send({ type: "error", message: "Usage: /branch diff <id|title>" });
|
|
15532
15530
|
return;
|
|
15533
15531
|
}
|
|
15534
|
-
const id =
|
|
15532
|
+
const id = resolve11(ref);
|
|
15535
15533
|
if (!id) return;
|
|
15536
15534
|
const d = session.diffBranches(id);
|
|
15537
15535
|
if (!d) {
|
|
@@ -15573,7 +15571,7 @@ async function handleBranch(args, ctx) {
|
|
|
15573
15571
|
ctx.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
|
|
15574
15572
|
return;
|
|
15575
15573
|
}
|
|
15576
|
-
const id =
|
|
15574
|
+
const id = resolve11(ref);
|
|
15577
15575
|
if (!id) return;
|
|
15578
15576
|
const idx = parseInt(idxStr, 10);
|
|
15579
15577
|
if (Number.isNaN(idx)) {
|
|
@@ -15922,7 +15920,7 @@ async function handleSecurityReview(args, ctx) {
|
|
|
15922
15920
|
async function handleTest(args, ctx) {
|
|
15923
15921
|
ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
15924
15922
|
try {
|
|
15925
|
-
const { executeTests } = await import("./run-tests-
|
|
15923
|
+
const { executeTests } = await import("./run-tests-QEIR322E.js");
|
|
15926
15924
|
const argStr = args.join(" ").trim();
|
|
15927
15925
|
let testArgs = {};
|
|
15928
15926
|
if (argStr) {
|
|
@@ -16079,7 +16077,7 @@ async function handleIndex(args, ctx) {
|
|
|
16079
16077
|
const sub = (args[0] ?? "status").toLowerCase();
|
|
16080
16078
|
const root = process.cwd();
|
|
16081
16079
|
const { loadIndex: loadIndex2, clearIndex } = await import("./store-VO37H6LS.js");
|
|
16082
|
-
const { indexProject: indexProject2 } = await import("./indexer-
|
|
16080
|
+
const { indexProject: indexProject2 } = await import("./indexer-M2LJGTY2.js");
|
|
16083
16081
|
const { loadVectorStore, clearVectorStore } = await import("./vector-store-JBAE6PS4.js");
|
|
16084
16082
|
if (sub === "status") {
|
|
16085
16083
|
const idx = loadIndex2(root);
|
|
@@ -16186,7 +16184,7 @@ async function handleMemory(args, ctx) {
|
|
|
16186
16184
|
ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
|
|
16187
16185
|
} else if (sub === "export") {
|
|
16188
16186
|
if (args[1] === "md") {
|
|
16189
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
16187
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-G24RJ5LA.js");
|
|
16190
16188
|
ctx.send({
|
|
16191
16189
|
type: "export_data",
|
|
16192
16190
|
format: "md",
|
|
@@ -16552,6 +16550,15 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
16552
16550
|
}
|
|
16553
16551
|
|
|
16554
16552
|
// src/web/session-handler.ts
|
|
16553
|
+
var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Set([
|
|
16554
|
+
"copy",
|
|
16555
|
+
"paste",
|
|
16556
|
+
"exit",
|
|
16557
|
+
"quit",
|
|
16558
|
+
"snapshot",
|
|
16559
|
+
"hooks",
|
|
16560
|
+
"hook"
|
|
16561
|
+
]);
|
|
16555
16562
|
var webCommandHandlers = {
|
|
16556
16563
|
provider: handleProvider,
|
|
16557
16564
|
model: handleModel,
|
|
@@ -16789,10 +16796,10 @@ var SessionHandler = class {
|
|
|
16789
16796
|
return;
|
|
16790
16797
|
}
|
|
16791
16798
|
case "ask_user_response": {
|
|
16792
|
-
const
|
|
16793
|
-
if (
|
|
16799
|
+
const resolve11 = this.pendingAskUser.get(msg.requestId);
|
|
16800
|
+
if (resolve11) {
|
|
16794
16801
|
this.pendingAskUser.delete(msg.requestId);
|
|
16795
|
-
|
|
16802
|
+
resolve11(msg.answer);
|
|
16796
16803
|
}
|
|
16797
16804
|
return;
|
|
16798
16805
|
}
|
|
@@ -16805,10 +16812,10 @@ var SessionHandler = class {
|
|
|
16805
16812
|
case "memory_manage":
|
|
16806
16813
|
return this.handleMemoryManage(msg.action, msg.id, msg.expiresAt);
|
|
16807
16814
|
case "auto_pause_response": {
|
|
16808
|
-
const
|
|
16809
|
-
if (
|
|
16815
|
+
const resolve11 = this.pendingAutoPause.get(msg.requestId);
|
|
16816
|
+
if (resolve11) {
|
|
16810
16817
|
this.pendingAutoPause.delete(msg.requestId);
|
|
16811
|
-
|
|
16818
|
+
resolve11({ action: msg.action, message: msg.message });
|
|
16812
16819
|
}
|
|
16813
16820
|
return;
|
|
16814
16821
|
}
|
|
@@ -16823,10 +16830,10 @@ var SessionHandler = class {
|
|
|
16823
16830
|
this.hubOrchestrator?.abort();
|
|
16824
16831
|
return;
|
|
16825
16832
|
case "hub_steer": {
|
|
16826
|
-
const
|
|
16827
|
-
if (
|
|
16833
|
+
const resolve11 = this.pendingHubReview.get(msg.requestId);
|
|
16834
|
+
if (resolve11) {
|
|
16828
16835
|
this.pendingHubReview.delete(msg.requestId);
|
|
16829
|
-
|
|
16836
|
+
resolve11({ action: msg.action, message: msg.message });
|
|
16830
16837
|
}
|
|
16831
16838
|
return;
|
|
16832
16839
|
}
|
|
@@ -16839,9 +16846,9 @@ var SessionHandler = class {
|
|
|
16839
16846
|
runLifecycleHooks(mergePluginHooks(this.config.get("hooks") ?? void 0, this.config.getConfigDir()), "Stop", { sessionId: this.sessions.current?.id }, { configDir: this.config.getConfigDir() });
|
|
16840
16847
|
this.toolExecutor.cancelAll();
|
|
16841
16848
|
if (this.abortController) this.abortController.abort();
|
|
16842
|
-
for (const
|
|
16849
|
+
for (const resolve11 of this.pendingAskUser.values()) resolve11(null);
|
|
16843
16850
|
this.pendingAskUser.clear();
|
|
16844
|
-
for (const
|
|
16851
|
+
for (const resolve11 of this.pendingAutoPause.values()) resolve11({ action: "stop" });
|
|
16845
16852
|
this.pendingAutoPause.clear();
|
|
16846
16853
|
this.saveIfNeeded();
|
|
16847
16854
|
if (this._bashSessionKey) clearBashSession(this._bashSessionKey);
|
|
@@ -16976,9 +16983,9 @@ var SessionHandler = class {
|
|
|
16976
16983
|
this.hubOrchestrator = orchestrator;
|
|
16977
16984
|
orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
|
|
16978
16985
|
if (config.humanSteer) {
|
|
16979
|
-
orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((
|
|
16986
|
+
orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve11) => {
|
|
16980
16987
|
const requestId = `hubrev_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
16981
|
-
this.pendingHubReview.set(requestId,
|
|
16988
|
+
this.pendingHubReview.set(requestId, resolve11);
|
|
16982
16989
|
this.send({ type: "hub_review", requestId, round, maxRounds });
|
|
16983
16990
|
});
|
|
16984
16991
|
}
|
|
@@ -17336,8 +17343,8 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
|
|
|
17336
17343
|
onMcpToolUsed: (name) => this.usedMcpToolNames.add(name),
|
|
17337
17344
|
requestAutoPause: async ({ effectiveRound, maxToolRounds: totalRounds, toolSummary }) => {
|
|
17338
17345
|
const requestId = `pause_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
17339
|
-
const pauseResp = await new Promise((
|
|
17340
|
-
this.pendingAutoPause.set(requestId,
|
|
17346
|
+
const pauseResp = await new Promise((resolve11) => {
|
|
17347
|
+
this.pendingAutoPause.set(requestId, resolve11);
|
|
17341
17348
|
this.send({
|
|
17342
17349
|
type: "auto_pause_request",
|
|
17343
17350
|
requestId,
|
|
@@ -17516,8 +17523,8 @@ ${summaryContent}`,
|
|
|
17516
17523
|
}
|
|
17517
17524
|
if (chunk.done) break;
|
|
17518
17525
|
}
|
|
17519
|
-
await new Promise((
|
|
17520
|
-
fileStream.end((err) => err ? reject(err) :
|
|
17526
|
+
await new Promise((resolve11, reject) => {
|
|
17527
|
+
fileStream.end((err) => err ? reject(err) : resolve11());
|
|
17521
17528
|
});
|
|
17522
17529
|
const verdict = evaluateTeeContent(fullContent, saveToFile, priorContent);
|
|
17523
17530
|
if (verdict.kind === "reject") {
|
|
@@ -17543,7 +17550,7 @@ ${summaryContent}`,
|
|
|
17543
17550
|
} catch (err) {
|
|
17544
17551
|
if (fileStream) {
|
|
17545
17552
|
try {
|
|
17546
|
-
await new Promise((
|
|
17553
|
+
await new Promise((resolve11) => fileStream.end(() => resolve11()));
|
|
17547
17554
|
} catch {
|
|
17548
17555
|
}
|
|
17549
17556
|
}
|
|
@@ -17591,6 +17598,13 @@ ${summaryContent}`,
|
|
|
17591
17598
|
}
|
|
17592
17599
|
// ── Commands ─────────────────────────────────────────────────────
|
|
17593
17600
|
async handleCommand(name, args) {
|
|
17601
|
+
if (CLI_ONLY_WEB_COMMANDS.has(name)) {
|
|
17602
|
+
this.send({
|
|
17603
|
+
type: "error",
|
|
17604
|
+
message: `/${name} is only available in the terminal REPL. Run \`aicli\` in a terminal and use /${name} there.`
|
|
17605
|
+
});
|
|
17606
|
+
return;
|
|
17607
|
+
}
|
|
17594
17608
|
const handler = webCommandHandlers[name];
|
|
17595
17609
|
if (handler) {
|
|
17596
17610
|
await handler(args, this);
|
|
@@ -17866,7 +17880,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17866
17880
|
return;
|
|
17867
17881
|
}
|
|
17868
17882
|
try {
|
|
17869
|
-
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-
|
|
17883
|
+
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-Q6BKWWAM.js");
|
|
17870
17884
|
const loaded = loadChatIndex2();
|
|
17871
17885
|
if (!loaded || loaded.idx.chunks.length === 0) {
|
|
17872
17886
|
this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
|
|
@@ -17902,7 +17916,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17902
17916
|
}
|
|
17903
17917
|
async handleMemoryStatus() {
|
|
17904
17918
|
try {
|
|
17905
|
-
const { getChatIndexStatus } = await import("./chat-index-
|
|
17919
|
+
const { getChatIndexStatus } = await import("./chat-index-Q6BKWWAM.js");
|
|
17906
17920
|
const s = getChatIndexStatus();
|
|
17907
17921
|
this.send({
|
|
17908
17922
|
type: "memory_status",
|
|
@@ -17927,7 +17941,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17927
17941
|
type: "info",
|
|
17928
17942
|
message: full ? "\u{1F9E0} Rebuilding chat memory index (this may take a while on first run \u2014 ~117 MB embedder)." : "\u{1F9E0} Refreshing chat memory index (incremental)\u2026"
|
|
17929
17943
|
});
|
|
17930
|
-
const { buildChatIndex } = await import("./chat-index-
|
|
17944
|
+
const { buildChatIndex } = await import("./chat-index-Q6BKWWAM.js");
|
|
17931
17945
|
const stats = await buildChatIndex({
|
|
17932
17946
|
full,
|
|
17933
17947
|
onProgress: (p) => {
|
|
@@ -18083,8 +18097,8 @@ async function setupProxy(configProxy) {
|
|
|
18083
18097
|
}
|
|
18084
18098
|
|
|
18085
18099
|
// src/web/auth.ts
|
|
18086
|
-
import { existsSync as
|
|
18087
|
-
import { isAbsolute as isAbsolute3, join as
|
|
18100
|
+
import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync4, mkdirSync as mkdirSync15, readdirSync as readdirSync14, copyFileSync } from "fs";
|
|
18101
|
+
import { isAbsolute as isAbsolute3, join as join24, relative as relative5 } from "path";
|
|
18088
18102
|
import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
|
|
18089
18103
|
var USERS_FILE = "users.json";
|
|
18090
18104
|
var TOKEN_EXPIRY_HOURS = 24;
|
|
@@ -18099,7 +18113,7 @@ var AuthManager = class {
|
|
|
18099
18113
|
db;
|
|
18100
18114
|
constructor(baseDir) {
|
|
18101
18115
|
this.baseDir = baseDir;
|
|
18102
|
-
this.usersFile =
|
|
18116
|
+
this.usersFile = join24(baseDir, USERS_FILE);
|
|
18103
18117
|
this.db = this.loadOrCreate();
|
|
18104
18118
|
}
|
|
18105
18119
|
// ── Public API ─────────────────────────────────────────────────
|
|
@@ -18128,9 +18142,9 @@ var AuthManager = class {
|
|
|
18128
18142
|
}
|
|
18129
18143
|
const salt = randomBytes(16).toString("hex");
|
|
18130
18144
|
const passwordHash = this.hashPassword(password, salt);
|
|
18131
|
-
const dataDir =
|
|
18132
|
-
const fullDataDir =
|
|
18133
|
-
mkdirSync15(
|
|
18145
|
+
const dataDir = join24(USERS_DIR, username);
|
|
18146
|
+
const fullDataDir = join24(this.baseDir, dataDir);
|
|
18147
|
+
mkdirSync15(join24(fullDataDir, "history"), { recursive: true });
|
|
18134
18148
|
const user = {
|
|
18135
18149
|
username,
|
|
18136
18150
|
passwordHash,
|
|
@@ -18245,7 +18259,7 @@ var AuthManager = class {
|
|
|
18245
18259
|
getUserDataDir(username) {
|
|
18246
18260
|
const user = this.db.users.find((u) => u.username === username);
|
|
18247
18261
|
if (!user) throw new Error(`User not found: ${username}`);
|
|
18248
|
-
return
|
|
18262
|
+
return join24(this.baseDir, user.dataDir);
|
|
18249
18263
|
}
|
|
18250
18264
|
/** List all usernames */
|
|
18251
18265
|
listUsers() {
|
|
@@ -18281,30 +18295,30 @@ var AuthManager = class {
|
|
|
18281
18295
|
const err = this.register(username, password);
|
|
18282
18296
|
if (err) return err;
|
|
18283
18297
|
const userDir = this.getUserDataDir(username);
|
|
18284
|
-
const globalConfig =
|
|
18285
|
-
if (
|
|
18298
|
+
const globalConfig = join24(this.baseDir, "config.json");
|
|
18299
|
+
if (existsSync29(globalConfig)) {
|
|
18286
18300
|
try {
|
|
18287
|
-
const content =
|
|
18288
|
-
|
|
18301
|
+
const content = readFileSync22(globalConfig, "utf-8");
|
|
18302
|
+
writeFileSync4(join24(userDir, "config.json"), content, "utf-8");
|
|
18289
18303
|
} catch {
|
|
18290
18304
|
}
|
|
18291
18305
|
}
|
|
18292
|
-
const globalMemory =
|
|
18293
|
-
if (
|
|
18306
|
+
const globalMemory = join24(this.baseDir, "memory.md");
|
|
18307
|
+
if (existsSync29(globalMemory)) {
|
|
18294
18308
|
try {
|
|
18295
|
-
const content =
|
|
18296
|
-
|
|
18309
|
+
const content = readFileSync22(globalMemory, "utf-8");
|
|
18310
|
+
writeFileSync4(join24(userDir, "memory.md"), content, "utf-8");
|
|
18297
18311
|
} catch {
|
|
18298
18312
|
}
|
|
18299
18313
|
}
|
|
18300
|
-
const globalHistory =
|
|
18301
|
-
if (
|
|
18314
|
+
const globalHistory = join24(this.baseDir, "history");
|
|
18315
|
+
if (existsSync29(globalHistory)) {
|
|
18302
18316
|
try {
|
|
18303
|
-
const files =
|
|
18304
|
-
const userHistory =
|
|
18317
|
+
const files = readdirSync14(globalHistory).filter((f) => f.endsWith(".json"));
|
|
18318
|
+
const userHistory = join24(userDir, "history");
|
|
18305
18319
|
for (const f of files) {
|
|
18306
18320
|
try {
|
|
18307
|
-
copyFileSync(
|
|
18321
|
+
copyFileSync(join24(globalHistory, f), join24(userHistory, f));
|
|
18308
18322
|
} catch {
|
|
18309
18323
|
}
|
|
18310
18324
|
}
|
|
@@ -18315,9 +18329,9 @@ var AuthManager = class {
|
|
|
18315
18329
|
}
|
|
18316
18330
|
// ── Private methods ────────────────────────────────────────────
|
|
18317
18331
|
loadOrCreate() {
|
|
18318
|
-
if (
|
|
18332
|
+
if (existsSync29(this.usersFile)) {
|
|
18319
18333
|
try {
|
|
18320
|
-
const parsed = JSON.parse(
|
|
18334
|
+
const parsed = JSON.parse(readFileSync22(this.usersFile, "utf-8"));
|
|
18321
18335
|
if (!this.isValidUsersDB(parsed)) {
|
|
18322
18336
|
throw new Error("database structure is invalid");
|
|
18323
18337
|
}
|
|
@@ -18351,7 +18365,7 @@ var AuthManager = class {
|
|
|
18351
18365
|
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)) {
|
|
18352
18366
|
return false;
|
|
18353
18367
|
}
|
|
18354
|
-
const dataDirFromBase = relative5(this.baseDir,
|
|
18368
|
+
const dataDirFromBase = relative5(this.baseDir, join24(this.baseDir, record.dataDir));
|
|
18355
18369
|
if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
|
|
18356
18370
|
if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
|
|
18357
18371
|
if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
|
|
@@ -18399,7 +18413,7 @@ function getModuleDir() {
|
|
|
18399
18413
|
}
|
|
18400
18414
|
} catch {
|
|
18401
18415
|
}
|
|
18402
|
-
return
|
|
18416
|
+
return resolve10(".");
|
|
18403
18417
|
}
|
|
18404
18418
|
async function startWebServer(options = {}) {
|
|
18405
18419
|
const port = options.port ?? 3e3;
|
|
@@ -18467,8 +18481,8 @@ async function startWebServer(options = {}) {
|
|
|
18467
18481
|
}
|
|
18468
18482
|
}
|
|
18469
18483
|
let skillManager = null;
|
|
18470
|
-
const skillsDir =
|
|
18471
|
-
if (
|
|
18484
|
+
const skillsDir = join25(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
18485
|
+
if (existsSync30(skillsDir)) {
|
|
18472
18486
|
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
18473
18487
|
skillManager.loadSkills(pluginAssets.skillDirs);
|
|
18474
18488
|
const count = skillManager.listSkills().length;
|
|
@@ -18519,6 +18533,10 @@ async function startWebServer(options = {}) {
|
|
|
18519
18533
|
console.log(` Auth: ${authManager.listUsers().length} user(s) registered`);
|
|
18520
18534
|
} else {
|
|
18521
18535
|
console.log(` Auth: disabled (no users registered)`);
|
|
18536
|
+
if (host === "0.0.0.0" || host === "::") {
|
|
18537
|
+
console.log(" WARNING: Web UI is reachable from the network without authentication.");
|
|
18538
|
+
console.log(" Create a user first for LAN/team use: aicli user create <name>");
|
|
18539
|
+
}
|
|
18522
18540
|
}
|
|
18523
18541
|
const requireAuth = (req, res, next) => {
|
|
18524
18542
|
if (!authManager.isEnabled()) return next();
|
|
@@ -18539,18 +18557,18 @@ async function startWebServer(options = {}) {
|
|
|
18539
18557
|
next();
|
|
18540
18558
|
};
|
|
18541
18559
|
const moduleDir = getModuleDir();
|
|
18542
|
-
let clientDir =
|
|
18543
|
-
if (!
|
|
18544
|
-
clientDir =
|
|
18560
|
+
let clientDir = join25(moduleDir, "web", "client");
|
|
18561
|
+
if (!existsSync30(clientDir)) {
|
|
18562
|
+
clientDir = join25(moduleDir, "client");
|
|
18545
18563
|
}
|
|
18546
|
-
if (!
|
|
18547
|
-
clientDir =
|
|
18564
|
+
if (!existsSync30(clientDir)) {
|
|
18565
|
+
clientDir = join25(moduleDir, "..", "..", "src", "web", "client");
|
|
18548
18566
|
}
|
|
18549
|
-
if (!
|
|
18550
|
-
clientDir =
|
|
18567
|
+
if (!existsSync30(clientDir)) {
|
|
18568
|
+
clientDir = join25(process.cwd(), "src", "web", "client");
|
|
18551
18569
|
}
|
|
18552
18570
|
console.log(` Static files: ${clientDir}`);
|
|
18553
|
-
app.use("/vendor", express.static(
|
|
18571
|
+
app.use("/vendor", express.static(join25(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
|
|
18554
18572
|
app.use(express.static(clientDir));
|
|
18555
18573
|
app.get("/api/status", (_req, res) => {
|
|
18556
18574
|
res.json({
|
|
@@ -18617,10 +18635,10 @@ async function startWebServer(options = {}) {
|
|
|
18617
18635
|
app.get("/api/files", requireAuth, (req, res) => {
|
|
18618
18636
|
const cwd = process.cwd();
|
|
18619
18637
|
const prefix = req.query.prefix || "";
|
|
18620
|
-
const targetDir =
|
|
18638
|
+
const targetDir = join25(cwd, prefix);
|
|
18621
18639
|
try {
|
|
18622
|
-
const canonicalTarget = realpathSync3(
|
|
18623
|
-
const canonicalCwd = realpathSync3(
|
|
18640
|
+
const canonicalTarget = realpathSync3(resolve10(targetDir));
|
|
18641
|
+
const canonicalCwd = realpathSync3(resolve10(cwd));
|
|
18624
18642
|
if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
|
|
18625
18643
|
res.json({ files: [] });
|
|
18626
18644
|
return;
|
|
@@ -18631,10 +18649,10 @@ async function startWebServer(options = {}) {
|
|
|
18631
18649
|
}
|
|
18632
18650
|
try {
|
|
18633
18651
|
const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
|
|
18634
|
-
const entries =
|
|
18652
|
+
const entries = readdirSync15(targetDir, { withFileTypes: true });
|
|
18635
18653
|
const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
|
|
18636
18654
|
name: e.name,
|
|
18637
|
-
path: relative6(cwd,
|
|
18655
|
+
path: relative6(cwd, join25(targetDir, e.name)).replace(/\\/g, "/"),
|
|
18638
18656
|
isDir: e.isDirectory()
|
|
18639
18657
|
}));
|
|
18640
18658
|
res.json({ files });
|
|
@@ -18674,8 +18692,8 @@ async function startWebServer(options = {}) {
|
|
|
18674
18692
|
try {
|
|
18675
18693
|
const authUser = req._authUser;
|
|
18676
18694
|
const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
|
|
18677
|
-
const filePath =
|
|
18678
|
-
if (!
|
|
18695
|
+
const filePath = join25(histDir, `${id}.json`);
|
|
18696
|
+
if (!existsSync30(filePath)) {
|
|
18679
18697
|
res.status(404).json({ error: "Session not found" });
|
|
18680
18698
|
return;
|
|
18681
18699
|
}
|
|
@@ -18690,7 +18708,7 @@ async function startWebServer(options = {}) {
|
|
|
18690
18708
|
res.status(404).json({ error: "Session not found" });
|
|
18691
18709
|
return;
|
|
18692
18710
|
}
|
|
18693
|
-
const data = JSON.parse(
|
|
18711
|
+
const data = JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
18694
18712
|
res.json({ session: data });
|
|
18695
18713
|
} catch (err) {
|
|
18696
18714
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
@@ -18703,10 +18721,10 @@ async function startWebServer(options = {}) {
|
|
|
18703
18721
|
return;
|
|
18704
18722
|
}
|
|
18705
18723
|
const cwd = process.cwd();
|
|
18706
|
-
const fullPath =
|
|
18724
|
+
const fullPath = resolve10(join25(cwd, filePath));
|
|
18707
18725
|
try {
|
|
18708
18726
|
const canonicalFull = realpathSync3(fullPath);
|
|
18709
|
-
const canonicalCwd = realpathSync3(
|
|
18727
|
+
const canonicalCwd = realpathSync3(resolve10(cwd));
|
|
18710
18728
|
if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
|
|
18711
18729
|
res.json({ error: "Access denied" });
|
|
18712
18730
|
return;
|
|
@@ -18716,12 +18734,12 @@ async function startWebServer(options = {}) {
|
|
|
18716
18734
|
return;
|
|
18717
18735
|
}
|
|
18718
18736
|
try {
|
|
18719
|
-
const stat =
|
|
18737
|
+
const stat = statSync13(fullPath);
|
|
18720
18738
|
if (stat.size > 512 * 1024) {
|
|
18721
18739
|
res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
|
|
18722
18740
|
return;
|
|
18723
18741
|
}
|
|
18724
|
-
const content =
|
|
18742
|
+
const content = readFileSync23(fullPath, "utf-8");
|
|
18725
18743
|
res.json({ content, size: stat.size });
|
|
18726
18744
|
} catch {
|
|
18727
18745
|
res.json({ error: "Cannot read file" });
|
|
@@ -18850,7 +18868,7 @@ async function startWebServer(options = {}) {
|
|
|
18850
18868
|
ws.send(JSON.stringify({ type: "auth_result", success: false, error: err }));
|
|
18851
18869
|
return;
|
|
18852
18870
|
}
|
|
18853
|
-
|
|
18871
|
+
authManager.login(username, password);
|
|
18854
18872
|
authenticatedUser = username;
|
|
18855
18873
|
const userShared = getUserShared(username);
|
|
18856
18874
|
handler = new SessionHandler(ws, userShared);
|
|
@@ -18925,7 +18943,7 @@ async function startWebServer(options = {}) {
|
|
|
18925
18943
|
});
|
|
18926
18944
|
const MAX_PORT_ATTEMPTS = 10;
|
|
18927
18945
|
let actualPort = port;
|
|
18928
|
-
const result = await new Promise((
|
|
18946
|
+
const result = await new Promise((resolve11, reject) => {
|
|
18929
18947
|
const tryListen = (attempt) => {
|
|
18930
18948
|
server.once("error", (err) => {
|
|
18931
18949
|
if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
|
|
@@ -18956,7 +18974,7 @@ async function startWebServer(options = {}) {
|
|
|
18956
18974
|
}
|
|
18957
18975
|
console.log(` Press Ctrl+C to stop
|
|
18958
18976
|
`);
|
|
18959
|
-
|
|
18977
|
+
resolve11({ port: actualPort, host, url });
|
|
18960
18978
|
});
|
|
18961
18979
|
};
|
|
18962
18980
|
tryListen(1);
|
|
@@ -18976,17 +18994,17 @@ function resolveProjectMcpPath() {
|
|
|
18976
18994
|
const cwd = process.cwd();
|
|
18977
18995
|
const gitRoot = getGitRoot(cwd);
|
|
18978
18996
|
const projectRoot = gitRoot ?? cwd;
|
|
18979
|
-
const configPath =
|
|
18980
|
-
return
|
|
18997
|
+
const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
18998
|
+
return existsSync30(configPath) ? configPath : null;
|
|
18981
18999
|
}
|
|
18982
19000
|
function loadProjectMcpConfig() {
|
|
18983
19001
|
const cwd = process.cwd();
|
|
18984
19002
|
const gitRoot = getGitRoot(cwd);
|
|
18985
19003
|
const projectRoot = gitRoot ?? cwd;
|
|
18986
|
-
const configPath =
|
|
18987
|
-
if (!
|
|
19004
|
+
const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
19005
|
+
if (!existsSync30(configPath)) return null;
|
|
18988
19006
|
try {
|
|
18989
|
-
const raw = JSON.parse(
|
|
19007
|
+
const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
|
|
18990
19008
|
return raw.mcpServers ?? raw;
|
|
18991
19009
|
} catch {
|
|
18992
19010
|
return null;
|