jinzd-ai-cli 0.4.246 → 0.4.248
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-CC3LCNXM.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-DJDEXHOT.js → chunk-23ZIOVZR.js} +4 -4
- package/dist/{chunk-QYQI7ZWK.js → chunk-2QZMITSL.js} +13 -1
- package/dist/{chunk-IGPFYNZA.js → chunk-6RPGQ5CG.js} +1 -1
- package/dist/{chunk-XK22CVID.js → chunk-BIZFOVNA.js} +1 -1
- package/dist/{chunk-YVMACMXW.js → chunk-EWLXBTSC.js} +1 -1
- package/dist/{chunk-OMSOAFXY.js → chunk-G77EIVBY.js} +1 -1
- package/dist/{chunk-K3CF65QH.js → chunk-GLSR2NR3.js} +1 -1
- package/dist/{chunk-CJ3BPLHZ.js → chunk-GS5XW5UJ.js} +1 -1
- package/dist/{chunk-E44DTERW.js → chunk-GUOLPI33.js} +3 -0
- package/dist/{chunk-6Y42RN5H.js → chunk-HTOKVD7R.js} +4 -4
- package/dist/{chunk-DT77O33T.js → chunk-JQXXPTWL.js} +1 -1
- package/dist/{chunk-PJ3ONBWZ.js → chunk-NYNSYLFY.js} +1 -1
- package/dist/{chunk-KWQKQVPH.js → chunk-OBULDJSU.js} +1 -1
- package/dist/{chunk-LEKOBVOQ.js → chunk-OHV7DYIS.js} +4 -5
- package/dist/{chunk-LZGPGPA6.js → chunk-PNFQDFHK.js} +1 -1
- package/dist/{chunk-BNERFXVO.js → chunk-QCG6UU2S.js} +1 -1
- package/dist/{chunk-Z7JROM3J.js → chunk-SAZGFYBU.js} +1 -1
- package/dist/{chunk-P2LB6S4I.js → chunk-SHG2QSQA.js} +1 -1
- package/dist/{chunk-USJF35NB.js → chunk-U3QWCBRG.js} +1 -1
- package/dist/{chunk-GQYRPBIQ.js → chunk-WYRW2W4O.js} +12 -12
- package/dist/{chunk-WYNPWHXB.js → chunk-Z4LVPM3N.js} +1 -1
- package/dist/{chunk-NV63EYFL.js → chunk-ZWEZNKDW.js} +1 -1
- package/dist/{chunk-YQUBYTDR.js → chunk-ZX3ZYRU7.js} +1 -1
- package/dist/{ci-VOGIC6S4.js → ci-KFVU4CHS.js} +5 -5
- package/dist/{ci-format-BHCSMT5U.js → ci-format-IFFCSCCN.js} +2 -2
- package/dist/{constants-J4OLBH72.js → constants-3C4JLZVQ.js} +1 -1
- package/dist/{doctor-cli-IR3E3XHB.js → doctor-cli-XJOK5LJZ.js} +5 -5
- package/dist/electron-server.js +170 -136
- package/dist/{hub-SFFFYMGO.js → hub-6TQFYGZO.js} +2 -2
- package/dist/index.js +31 -32
- 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-JBWBMA56.js} +2 -2
- package/dist/{persistent-memory-3KH2EVHA.js → persistent-memory-QQXFCUNL.js} +2 -2
- package/dist/{pr-BNS3OHDM.js → pr-TMPU2U2P.js} +5 -5
- package/dist/{run-tests-PW4WC4OG.js → run-tests-2A3CASVZ.js} +2 -2
- package/dist/{run-tests-ZKHXKCQB.js → run-tests-NNML2XVV.js} +2 -2
- package/dist/{server-D2ID3GYA.js → server-6L5XRY4K.js} +113 -93
- package/dist/{server-3HLBEWNZ.js → server-ANNA57CP.js} +8 -8
- package/dist/{task-orchestrator-FMCI4RPX.js → task-orchestrator-URY32ZSQ.js} +8 -9
- package/dist/{usage-DPLNMDSJ.js → usage-J46NVHYR.js} +4 -4
- 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-GS5XW5UJ.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-U3QWCBRG.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-PNFQDFHK.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) {
|
|
@@ -3407,6 +3406,7 @@ var KimiProvider = class _KimiProvider extends OpenAICompatibleProvider {
|
|
|
3407
3406
|
* 其他值会收到 400 "invalid temperature: only 1 is allowed for this model"。
|
|
3408
3407
|
*/
|
|
3409
3408
|
static TEMP_1_MODELS = /* @__PURE__ */ new Set([
|
|
3409
|
+
"kimi-k3",
|
|
3410
3410
|
"kimi-k2.6",
|
|
3411
3411
|
"kimi-k2.5",
|
|
3412
3412
|
"kimi-k2-thinking",
|
|
@@ -3433,6 +3433,18 @@ var KimiProvider = class _KimiProvider extends OpenAICompatibleProvider {
|
|
|
3433
3433
|
requiresApiKey: true,
|
|
3434
3434
|
baseUrl: this.defaultBaseUrl,
|
|
3435
3435
|
models: [
|
|
3436
|
+
// Kimi K3(2026-07 旗舰,1M 上下文,多步推理 + 原生 vision)。
|
|
3437
|
+
// 官方文档核实(platform.kimi.ai/docs/guide/kimi-k3-quickstart):
|
|
3438
|
+
// - contextWindow 1M(1048576);code 就是 `kimi-k3`(UI 名 "K3 · Max" ≠ API code)
|
|
3439
|
+
// - temperature 固定 1.0(已并入 TEMP_1_MODELS)
|
|
3440
|
+
// - vision 走 base64 / ms://file-id(不收公网 URL)——本版未接图片输入路径,仅文本/工具
|
|
3441
|
+
// 默认仍保持 kimi-k2.6(K3 输出 $15/MTok 偏贵,按需 /model kimi-k3)。
|
|
3442
|
+
{
|
|
3443
|
+
id: "kimi-k3",
|
|
3444
|
+
displayName: "Kimi K3",
|
|
3445
|
+
contextWindow: 1048576,
|
|
3446
|
+
supportsStreaming: true
|
|
3447
|
+
},
|
|
3436
3448
|
// Kimi K2.6 / K2.5 系列(最新一代,推荐)
|
|
3437
3449
|
{
|
|
3438
3450
|
id: "kimi-k2.6",
|
|
@@ -4996,7 +5008,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
4996
5008
|
const markerStart = `AICLI_MARKER_START:${id}`;
|
|
4997
5009
|
const markerEnd = `AICLI_MARKER_END:${id}`;
|
|
4998
5010
|
const wrappedCmd = IS_WINDOWS2 ? `${WIN_UTF8_PREAMBLE} echo "${markerStart}"; ${command}; echo "${markerEnd}:0"` : `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
|
|
4999
|
-
return new Promise((
|
|
5011
|
+
return new Promise((resolve11) => {
|
|
5000
5012
|
let stdout = "";
|
|
5001
5013
|
let stderr = "";
|
|
5002
5014
|
let timedOut = false;
|
|
@@ -5008,11 +5020,11 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5008
5020
|
stdout += IS_WINDOWS2 ? decodeWindowsBuffer(chunk) : chunk.toString("utf-8");
|
|
5009
5021
|
if (!resolved && stdout.includes(markerEndPattern)) {
|
|
5010
5022
|
const endLine = stdout.split("\n").find((l) => l.includes(markerEndPattern));
|
|
5011
|
-
const exitCode = endLine ? parseEndMarker(endLine
|
|
5023
|
+
const exitCode = endLine ? parseEndMarker(endLine) : null;
|
|
5012
5024
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5013
5025
|
resolved = true;
|
|
5014
5026
|
cleanup();
|
|
5015
|
-
|
|
5027
|
+
resolve11({ stdout, stderr, exitCode, timedOut, aborted });
|
|
5016
5028
|
}
|
|
5017
5029
|
};
|
|
5018
5030
|
const onErr = (chunk) => {
|
|
@@ -5027,7 +5039,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5027
5039
|
resolved = true;
|
|
5028
5040
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5029
5041
|
cleanup();
|
|
5030
|
-
|
|
5042
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5031
5043
|
killProcessTree(proc);
|
|
5032
5044
|
pool.delete(sessionKey);
|
|
5033
5045
|
}, timeout);
|
|
@@ -5037,7 +5049,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5037
5049
|
resolved = true;
|
|
5038
5050
|
cleanup();
|
|
5039
5051
|
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
5040
|
-
|
|
5052
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5041
5053
|
killProcessTree(proc);
|
|
5042
5054
|
pool.delete(sessionKey);
|
|
5043
5055
|
};
|
|
@@ -5052,7 +5064,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5052
5064
|
stderr += `
|
|
5053
5065
|
[pool error] ${err.message}`;
|
|
5054
5066
|
cleanup();
|
|
5055
|
-
|
|
5067
|
+
resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
5056
5068
|
pool.delete(sessionKey);
|
|
5057
5069
|
};
|
|
5058
5070
|
proc.on("error", onError);
|
|
@@ -5065,7 +5077,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5065
5077
|
}
|
|
5066
5078
|
try {
|
|
5067
5079
|
proc.stdin?.write(wrappedCmd + "\n");
|
|
5068
|
-
} catch
|
|
5080
|
+
} catch {
|
|
5069
5081
|
if (!resolved) {
|
|
5070
5082
|
cleanup();
|
|
5071
5083
|
pool.delete(sessionKey);
|
|
@@ -5073,7 +5085,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
5073
5085
|
}
|
|
5074
5086
|
});
|
|
5075
5087
|
}
|
|
5076
|
-
function parseEndMarker(line
|
|
5088
|
+
function parseEndMarker(line) {
|
|
5077
5089
|
const idx = line.lastIndexOf(":");
|
|
5078
5090
|
if (idx < 0) return null;
|
|
5079
5091
|
const code = line.slice(idx + 1).trim();
|
|
@@ -7210,7 +7222,7 @@ var ToolExecutor = class {
|
|
|
7210
7222
|
};
|
|
7211
7223
|
}
|
|
7212
7224
|
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
7213
|
-
this.printToolCall(call);
|
|
7225
|
+
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
7214
7226
|
try {
|
|
7215
7227
|
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
7216
7228
|
const content = truncateOutput(rawContent, call.name);
|
|
@@ -7441,7 +7453,7 @@ var ToolExecutor = class {
|
|
|
7441
7453
|
rl.resume();
|
|
7442
7454
|
process.stdout.write(prompt);
|
|
7443
7455
|
this.confirming = true;
|
|
7444
|
-
return new Promise((
|
|
7456
|
+
return new Promise((resolve11) => {
|
|
7445
7457
|
let completed = false;
|
|
7446
7458
|
const cleanup = (result) => {
|
|
7447
7459
|
if (completed) return;
|
|
@@ -7451,7 +7463,7 @@ var ToolExecutor = class {
|
|
|
7451
7463
|
rl.pause();
|
|
7452
7464
|
rlAny.output = savedOutput;
|
|
7453
7465
|
this.confirming = false;
|
|
7454
|
-
|
|
7466
|
+
resolve11(result);
|
|
7455
7467
|
};
|
|
7456
7468
|
const onLine = (line) => {
|
|
7457
7469
|
const trimmed = line.trim();
|
|
@@ -7625,7 +7637,7 @@ var ToolExecutor = class {
|
|
|
7625
7637
|
rl.resume();
|
|
7626
7638
|
process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
|
|
7627
7639
|
this.confirming = true;
|
|
7628
|
-
return new Promise((
|
|
7640
|
+
return new Promise((resolve11) => {
|
|
7629
7641
|
let completed = false;
|
|
7630
7642
|
const cleanup = (answer) => {
|
|
7631
7643
|
if (completed) return;
|
|
@@ -7635,7 +7647,7 @@ var ToolExecutor = class {
|
|
|
7635
7647
|
rl.pause();
|
|
7636
7648
|
rlAny.output = savedOutput;
|
|
7637
7649
|
this.confirming = false;
|
|
7638
|
-
|
|
7650
|
+
resolve11(answer === "y");
|
|
7639
7651
|
};
|
|
7640
7652
|
const onLine = (line) => {
|
|
7641
7653
|
const trimmed = line.trim();
|
|
@@ -7816,7 +7828,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
|
|
|
7816
7828
|
const mode = appendMode ? "appended" : "written";
|
|
7817
7829
|
void (async () => {
|
|
7818
7830
|
try {
|
|
7819
|
-
const { updateFile } = await import("./indexer-
|
|
7831
|
+
const { updateFile } = await import("./indexer-M2LJGTY2.js");
|
|
7820
7832
|
await updateFile(process.cwd(), filePath);
|
|
7821
7833
|
} catch {
|
|
7822
7834
|
}
|
|
@@ -8884,7 +8896,7 @@ var runInteractiveTool = {
|
|
|
8884
8896
|
PYTHONDONTWRITEBYTECODE: "1"
|
|
8885
8897
|
};
|
|
8886
8898
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
8887
|
-
return new Promise((
|
|
8899
|
+
return new Promise((resolve11) => {
|
|
8888
8900
|
const child = spawn4(executable, cmdArgs.map(String), {
|
|
8889
8901
|
cwd: process.cwd(),
|
|
8890
8902
|
env,
|
|
@@ -8917,22 +8929,22 @@ var runInteractiveTool = {
|
|
|
8917
8929
|
setTimeout(writeNextLine, 400);
|
|
8918
8930
|
const timer = setTimeout(() => {
|
|
8919
8931
|
child.kill();
|
|
8920
|
-
|
|
8932
|
+
resolve11(`${prefixWarnings}[Timeout after ${timeout}ms]
|
|
8921
8933
|
${buildOutput(stdout, stderr)}`);
|
|
8922
8934
|
}, timeout);
|
|
8923
8935
|
child.on("close", (code) => {
|
|
8924
8936
|
clearTimeout(timer);
|
|
8925
8937
|
const output = buildOutput(stdout, stderr);
|
|
8926
8938
|
if (code !== 0 && code !== null) {
|
|
8927
|
-
|
|
8939
|
+
resolve11(`${prefixWarnings}Exit code ${code}:
|
|
8928
8940
|
${output}`);
|
|
8929
8941
|
} else {
|
|
8930
|
-
|
|
8942
|
+
resolve11(`${prefixWarnings}${output || "(no output)"}`);
|
|
8931
8943
|
}
|
|
8932
8944
|
});
|
|
8933
8945
|
child.on("error", (err) => {
|
|
8934
8946
|
clearTimeout(timer);
|
|
8935
|
-
|
|
8947
|
+
resolve11(
|
|
8936
8948
|
`${prefixWarnings}Failed to start process "${executable}": ${err.message}
|
|
8937
8949
|
Hint: On Windows, use the full path to the executable, e.g.:
|
|
8938
8950
|
C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
|
|
@@ -9235,7 +9247,7 @@ var webFetchTool = {
|
|
|
9235
9247
|
} else {
|
|
9236
9248
|
const title = extractTitle(rawHtml);
|
|
9237
9249
|
const desc = extractDescription(rawHtml);
|
|
9238
|
-
|
|
9250
|
+
const body = htmlToText(rawHtml);
|
|
9239
9251
|
const header = [
|
|
9240
9252
|
title ? `# ${title}` : "",
|
|
9241
9253
|
desc ? `> ${desc}` : "",
|
|
@@ -9754,7 +9766,7 @@ function promptUser(rl, question) {
|
|
|
9754
9766
|
console.log();
|
|
9755
9767
|
console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
|
|
9756
9768
|
process.stdout.write(chalk4.cyan("> "));
|
|
9757
|
-
return new Promise((
|
|
9769
|
+
return new Promise((resolve11) => {
|
|
9758
9770
|
let completed = false;
|
|
9759
9771
|
const cleanup = (answer) => {
|
|
9760
9772
|
if (completed) return;
|
|
@@ -9764,7 +9776,7 @@ function promptUser(rl, question) {
|
|
|
9764
9776
|
rl.pause();
|
|
9765
9777
|
rlAny.output = savedOutput;
|
|
9766
9778
|
askUserContext.prompting = false;
|
|
9767
|
-
|
|
9779
|
+
resolve11(answer);
|
|
9768
9780
|
};
|
|
9769
9781
|
const onLine = (line) => {
|
|
9770
9782
|
cleanup(line);
|
|
@@ -12320,7 +12332,7 @@ var McpClient = class {
|
|
|
12320
12332
|
// 内部方法:JSON-RPC 通信
|
|
12321
12333
|
// ══════════════════════════════════════════════════════════════════
|
|
12322
12334
|
sendRequest(method, params) {
|
|
12323
|
-
return new Promise((
|
|
12335
|
+
return new Promise((resolve11, reject) => {
|
|
12324
12336
|
if (!this.process?.stdin?.writable) {
|
|
12325
12337
|
return reject(new Error(`MCP server [${this.serverId}] stdin not writable`));
|
|
12326
12338
|
}
|
|
@@ -12332,19 +12344,18 @@ var McpClient = class {
|
|
|
12332
12344
|
method,
|
|
12333
12345
|
...params !== void 0 ? { params } : {}
|
|
12334
12346
|
};
|
|
12335
|
-
let timer;
|
|
12336
12347
|
const cleanup = () => {
|
|
12337
12348
|
this.pendingRequests.delete(id);
|
|
12338
12349
|
clearTimeout(timer);
|
|
12339
12350
|
};
|
|
12340
|
-
timer = setTimeout(() => {
|
|
12351
|
+
const timer = setTimeout(() => {
|
|
12341
12352
|
cleanup();
|
|
12342
12353
|
reject(new Error(`MCP request [${method}] timed out (internal)`));
|
|
12343
12354
|
}, MCP_CALL_TIMEOUT * 2);
|
|
12344
12355
|
this.pendingRequests.set(id, {
|
|
12345
12356
|
resolve: (result) => {
|
|
12346
12357
|
cleanup();
|
|
12347
|
-
|
|
12358
|
+
resolve11(result);
|
|
12348
12359
|
},
|
|
12349
12360
|
reject: (error) => {
|
|
12350
12361
|
cleanup();
|
|
@@ -12421,13 +12432,13 @@ var McpClient = class {
|
|
|
12421
12432
|
}
|
|
12422
12433
|
/** Promise 超时包装 */
|
|
12423
12434
|
withTimeout(promise, ms, label) {
|
|
12424
|
-
return new Promise((
|
|
12435
|
+
return new Promise((resolve11, reject) => {
|
|
12425
12436
|
const timer = setTimeout(() => {
|
|
12426
12437
|
reject(new Error(`MCP [${this.serverId}] ${label} timed out after ${ms}ms`));
|
|
12427
12438
|
}, ms);
|
|
12428
12439
|
promise.then((val) => {
|
|
12429
12440
|
clearTimeout(timer);
|
|
12430
|
-
|
|
12441
|
+
resolve11(val);
|
|
12431
12442
|
}).catch((err) => {
|
|
12432
12443
|
clearTimeout(timer);
|
|
12433
12444
|
reject(err);
|
|
@@ -12931,33 +12942,33 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
12931
12942
|
}
|
|
12932
12943
|
/** Resolve a pending confirm from client response */
|
|
12933
12944
|
resolveConfirm(requestId, approved) {
|
|
12934
|
-
const
|
|
12935
|
-
if (
|
|
12945
|
+
const resolve11 = this.pendingConfirms.get(requestId);
|
|
12946
|
+
if (resolve11) {
|
|
12936
12947
|
this.clearPendingTimer(requestId);
|
|
12937
12948
|
this.pendingConfirms.delete(requestId);
|
|
12938
12949
|
this.confirming = false;
|
|
12939
|
-
|
|
12950
|
+
resolve11(approved);
|
|
12940
12951
|
}
|
|
12941
12952
|
}
|
|
12942
12953
|
/** Resolve a pending batch confirm from client response */
|
|
12943
12954
|
resolveBatchConfirm(requestId, decision) {
|
|
12944
|
-
const
|
|
12945
|
-
if (
|
|
12955
|
+
const resolve11 = this.pendingBatchConfirms.get(requestId);
|
|
12956
|
+
if (resolve11) {
|
|
12946
12957
|
this.clearPendingTimer(requestId);
|
|
12947
12958
|
this.pendingBatchConfirms.delete(requestId);
|
|
12948
12959
|
this.confirming = false;
|
|
12949
12960
|
if (decision === "all" || decision === "none") {
|
|
12950
|
-
|
|
12961
|
+
resolve11(decision);
|
|
12951
12962
|
} else {
|
|
12952
|
-
|
|
12963
|
+
resolve11(new Set(decision));
|
|
12953
12964
|
}
|
|
12954
12965
|
}
|
|
12955
12966
|
}
|
|
12956
12967
|
/** Cancel all pending confirms (e.g., on disconnect) */
|
|
12957
12968
|
cancelAll() {
|
|
12958
|
-
for (const
|
|
12969
|
+
for (const resolve11 of this.pendingConfirms.values()) resolve11(false);
|
|
12959
12970
|
this.pendingConfirms.clear();
|
|
12960
|
-
for (const
|
|
12971
|
+
for (const resolve11 of this.pendingBatchConfirms.values()) resolve11("none");
|
|
12961
12972
|
this.pendingBatchConfirms.clear();
|
|
12962
12973
|
this.confirming = false;
|
|
12963
12974
|
}
|
|
@@ -13033,8 +13044,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13033
13044
|
diff: this.getDiffPreview(call)
|
|
13034
13045
|
};
|
|
13035
13046
|
this.send(msg);
|
|
13036
|
-
return new Promise((
|
|
13037
|
-
this.pendingConfirms.set(requestId,
|
|
13047
|
+
return new Promise((resolve11) => {
|
|
13048
|
+
this.pendingConfirms.set(requestId, resolve11);
|
|
13038
13049
|
this.pendingTimers.set(requestId, setTimeout(() => {
|
|
13039
13050
|
if (this.pendingConfirms.has(requestId)) {
|
|
13040
13051
|
this.resolveConfirm(requestId, false);
|
|
@@ -13058,8 +13069,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13058
13069
|
files
|
|
13059
13070
|
};
|
|
13060
13071
|
this.send(msg);
|
|
13061
|
-
return new Promise((
|
|
13062
|
-
this.pendingBatchConfirms.set(requestId,
|
|
13072
|
+
return new Promise((resolve11) => {
|
|
13073
|
+
this.pendingBatchConfirms.set(requestId, resolve11);
|
|
13063
13074
|
this.pendingTimers.set(requestId, setTimeout(() => {
|
|
13064
13075
|
if (this.pendingBatchConfirms.has(requestId)) {
|
|
13065
13076
|
this.resolveBatchConfirm(requestId, "none");
|
|
@@ -13169,7 +13180,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13169
13180
|
return { callId: call.id, content: rejectionMsg, isError: true };
|
|
13170
13181
|
}
|
|
13171
13182
|
}
|
|
13172
|
-
this.sendToolCallStart(call);
|
|
13183
|
+
if (!toolCallStarted) this.sendToolCallStart(call);
|
|
13173
13184
|
if (this.sessionAutoMode && networkPermission?.action !== "confirm") {
|
|
13174
13185
|
const classification = defaultActionClassifier.classify(call, dangerLevel, {
|
|
13175
13186
|
workspaceRoot: this.workspaceRoot,
|
|
@@ -13427,6 +13438,9 @@ var PRICING_TABLE = {
|
|
|
13427
13438
|
"moonshot-v1-128k": { input: 0.83, output: 0.83 },
|
|
13428
13439
|
"kimi-k2": { input: 0.6, output: 2.5 },
|
|
13429
13440
|
"kimi-latest": { input: 0.6, output: 2.5 },
|
|
13441
|
+
// Kimi K3(2026-07 旗舰,1M 上下文)官方定价 platform.kimi.ai/pricing/chat-k3:
|
|
13442
|
+
// 输入 cache-miss $3.00 / cache-hit $0.30,输出 $15.00(/MTok)。
|
|
13443
|
+
"kimi-k3": { input: 3, output: 15, cacheRead: 0.3 },
|
|
13430
13444
|
// ── Zhipu GLM ─────────────────────────────────────────────────
|
|
13431
13445
|
"glm-4-plus": { input: 0.7, output: 0.7 },
|
|
13432
13446
|
"glm-4": { input: 0.14, output: 0.14 },
|
|
@@ -13548,7 +13562,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
13548
13562
|
const originalSize = JSON.stringify(session.toJSON()).length;
|
|
13549
13563
|
if (originalSize <= sizeLimit) return false;
|
|
13550
13564
|
const snapshotLen = session.messages.length;
|
|
13551
|
-
|
|
13565
|
+
const working = cloneMessages(session.messages.slice(0, snapshotLen));
|
|
13552
13566
|
let committedSize = originalSize;
|
|
13553
13567
|
let anyTrim = false;
|
|
13554
13568
|
let keepRecent = 10;
|
|
@@ -15113,7 +15127,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
15113
15127
|
Cost: ${formatCost(cost)}` : "";
|
|
15114
15128
|
let memoryLine = "";
|
|
15115
15129
|
try {
|
|
15116
|
-
const { countPendingMemories } = await import("./persistent-memory-
|
|
15130
|
+
const { countPendingMemories } = await import("./persistent-memory-JBWBMA56.js");
|
|
15117
15131
|
const pending = countPendingMemories(ctx.config.getConfigDir());
|
|
15118
15132
|
if (pending > 0) memoryLine = `
|
|
15119
15133
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -15420,7 +15434,7 @@ async function handleBranch(args, ctx) {
|
|
|
15420
15434
|
return;
|
|
15421
15435
|
}
|
|
15422
15436
|
const sub = args[0]?.toLowerCase();
|
|
15423
|
-
const
|
|
15437
|
+
const resolve11 = (ref) => {
|
|
15424
15438
|
const r = session.resolveBranchRef(ref);
|
|
15425
15439
|
if (r.ok) return r.id;
|
|
15426
15440
|
if (r.reason === "ambiguous") {
|
|
@@ -15474,7 +15488,7 @@ async function handleBranch(args, ctx) {
|
|
|
15474
15488
|
ctx.send({ type: "error", message: "Usage: /branch switch <id|title>" });
|
|
15475
15489
|
return;
|
|
15476
15490
|
}
|
|
15477
|
-
const id =
|
|
15491
|
+
const id = resolve11(ref);
|
|
15478
15492
|
if (!id) return;
|
|
15479
15493
|
const ok = session.switchBranch(id);
|
|
15480
15494
|
if (ok) {
|
|
@@ -15494,7 +15508,7 @@ async function handleBranch(args, ctx) {
|
|
|
15494
15508
|
ctx.send({ type: "error", message: "Usage: /branch delete <id|title>" });
|
|
15495
15509
|
return;
|
|
15496
15510
|
}
|
|
15497
|
-
const id =
|
|
15511
|
+
const id = resolve11(ref);
|
|
15498
15512
|
if (!id) return;
|
|
15499
15513
|
const ok = session.deleteBranch(id);
|
|
15500
15514
|
if (ok) {
|
|
@@ -15513,7 +15527,7 @@ async function handleBranch(args, ctx) {
|
|
|
15513
15527
|
ctx.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
|
|
15514
15528
|
return;
|
|
15515
15529
|
}
|
|
15516
|
-
const id =
|
|
15530
|
+
const id = resolve11(ref);
|
|
15517
15531
|
if (!id) return;
|
|
15518
15532
|
const ok = session.renameBranch(id, title);
|
|
15519
15533
|
if (ok) {
|
|
@@ -15531,7 +15545,7 @@ async function handleBranch(args, ctx) {
|
|
|
15531
15545
|
ctx.send({ type: "error", message: "Usage: /branch diff <id|title>" });
|
|
15532
15546
|
return;
|
|
15533
15547
|
}
|
|
15534
|
-
const id =
|
|
15548
|
+
const id = resolve11(ref);
|
|
15535
15549
|
if (!id) return;
|
|
15536
15550
|
const d = session.diffBranches(id);
|
|
15537
15551
|
if (!d) {
|
|
@@ -15573,7 +15587,7 @@ async function handleBranch(args, ctx) {
|
|
|
15573
15587
|
ctx.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
|
|
15574
15588
|
return;
|
|
15575
15589
|
}
|
|
15576
|
-
const id =
|
|
15590
|
+
const id = resolve11(ref);
|
|
15577
15591
|
if (!id) return;
|
|
15578
15592
|
const idx = parseInt(idxStr, 10);
|
|
15579
15593
|
if (Number.isNaN(idx)) {
|
|
@@ -15922,7 +15936,7 @@ async function handleSecurityReview(args, ctx) {
|
|
|
15922
15936
|
async function handleTest(args, ctx) {
|
|
15923
15937
|
ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
15924
15938
|
try {
|
|
15925
|
-
const { executeTests } = await import("./run-tests-
|
|
15939
|
+
const { executeTests } = await import("./run-tests-NNML2XVV.js");
|
|
15926
15940
|
const argStr = args.join(" ").trim();
|
|
15927
15941
|
let testArgs = {};
|
|
15928
15942
|
if (argStr) {
|
|
@@ -16079,7 +16093,7 @@ async function handleIndex(args, ctx) {
|
|
|
16079
16093
|
const sub = (args[0] ?? "status").toLowerCase();
|
|
16080
16094
|
const root = process.cwd();
|
|
16081
16095
|
const { loadIndex: loadIndex2, clearIndex } = await import("./store-VO37H6LS.js");
|
|
16082
|
-
const { indexProject: indexProject2 } = await import("./indexer-
|
|
16096
|
+
const { indexProject: indexProject2 } = await import("./indexer-M2LJGTY2.js");
|
|
16083
16097
|
const { loadVectorStore, clearVectorStore } = await import("./vector-store-JBAE6PS4.js");
|
|
16084
16098
|
if (sub === "status") {
|
|
16085
16099
|
const idx = loadIndex2(root);
|
|
@@ -16186,7 +16200,7 @@ async function handleMemory(args, ctx) {
|
|
|
16186
16200
|
ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
|
|
16187
16201
|
} else if (sub === "export") {
|
|
16188
16202
|
if (args[1] === "md") {
|
|
16189
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
16203
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-JBWBMA56.js");
|
|
16190
16204
|
ctx.send({
|
|
16191
16205
|
type: "export_data",
|
|
16192
16206
|
format: "md",
|
|
@@ -16552,6 +16566,15 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
16552
16566
|
}
|
|
16553
16567
|
|
|
16554
16568
|
// src/web/session-handler.ts
|
|
16569
|
+
var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Set([
|
|
16570
|
+
"copy",
|
|
16571
|
+
"paste",
|
|
16572
|
+
"exit",
|
|
16573
|
+
"quit",
|
|
16574
|
+
"snapshot",
|
|
16575
|
+
"hooks",
|
|
16576
|
+
"hook"
|
|
16577
|
+
]);
|
|
16555
16578
|
var webCommandHandlers = {
|
|
16556
16579
|
provider: handleProvider,
|
|
16557
16580
|
model: handleModel,
|
|
@@ -16789,10 +16812,10 @@ var SessionHandler = class {
|
|
|
16789
16812
|
return;
|
|
16790
16813
|
}
|
|
16791
16814
|
case "ask_user_response": {
|
|
16792
|
-
const
|
|
16793
|
-
if (
|
|
16815
|
+
const resolve11 = this.pendingAskUser.get(msg.requestId);
|
|
16816
|
+
if (resolve11) {
|
|
16794
16817
|
this.pendingAskUser.delete(msg.requestId);
|
|
16795
|
-
|
|
16818
|
+
resolve11(msg.answer);
|
|
16796
16819
|
}
|
|
16797
16820
|
return;
|
|
16798
16821
|
}
|
|
@@ -16805,10 +16828,10 @@ var SessionHandler = class {
|
|
|
16805
16828
|
case "memory_manage":
|
|
16806
16829
|
return this.handleMemoryManage(msg.action, msg.id, msg.expiresAt);
|
|
16807
16830
|
case "auto_pause_response": {
|
|
16808
|
-
const
|
|
16809
|
-
if (
|
|
16831
|
+
const resolve11 = this.pendingAutoPause.get(msg.requestId);
|
|
16832
|
+
if (resolve11) {
|
|
16810
16833
|
this.pendingAutoPause.delete(msg.requestId);
|
|
16811
|
-
|
|
16834
|
+
resolve11({ action: msg.action, message: msg.message });
|
|
16812
16835
|
}
|
|
16813
16836
|
return;
|
|
16814
16837
|
}
|
|
@@ -16823,10 +16846,10 @@ var SessionHandler = class {
|
|
|
16823
16846
|
this.hubOrchestrator?.abort();
|
|
16824
16847
|
return;
|
|
16825
16848
|
case "hub_steer": {
|
|
16826
|
-
const
|
|
16827
|
-
if (
|
|
16849
|
+
const resolve11 = this.pendingHubReview.get(msg.requestId);
|
|
16850
|
+
if (resolve11) {
|
|
16828
16851
|
this.pendingHubReview.delete(msg.requestId);
|
|
16829
|
-
|
|
16852
|
+
resolve11({ action: msg.action, message: msg.message });
|
|
16830
16853
|
}
|
|
16831
16854
|
return;
|
|
16832
16855
|
}
|
|
@@ -16839,9 +16862,9 @@ var SessionHandler = class {
|
|
|
16839
16862
|
runLifecycleHooks(mergePluginHooks(this.config.get("hooks") ?? void 0, this.config.getConfigDir()), "Stop", { sessionId: this.sessions.current?.id }, { configDir: this.config.getConfigDir() });
|
|
16840
16863
|
this.toolExecutor.cancelAll();
|
|
16841
16864
|
if (this.abortController) this.abortController.abort();
|
|
16842
|
-
for (const
|
|
16865
|
+
for (const resolve11 of this.pendingAskUser.values()) resolve11(null);
|
|
16843
16866
|
this.pendingAskUser.clear();
|
|
16844
|
-
for (const
|
|
16867
|
+
for (const resolve11 of this.pendingAutoPause.values()) resolve11({ action: "stop" });
|
|
16845
16868
|
this.pendingAutoPause.clear();
|
|
16846
16869
|
this.saveIfNeeded();
|
|
16847
16870
|
if (this._bashSessionKey) clearBashSession(this._bashSessionKey);
|
|
@@ -16976,9 +16999,9 @@ var SessionHandler = class {
|
|
|
16976
16999
|
this.hubOrchestrator = orchestrator;
|
|
16977
17000
|
orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
|
|
16978
17001
|
if (config.humanSteer) {
|
|
16979
|
-
orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((
|
|
17002
|
+
orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve11) => {
|
|
16980
17003
|
const requestId = `hubrev_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
16981
|
-
this.pendingHubReview.set(requestId,
|
|
17004
|
+
this.pendingHubReview.set(requestId, resolve11);
|
|
16982
17005
|
this.send({ type: "hub_review", requestId, round, maxRounds });
|
|
16983
17006
|
});
|
|
16984
17007
|
}
|
|
@@ -17336,8 +17359,8 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
|
|
|
17336
17359
|
onMcpToolUsed: (name) => this.usedMcpToolNames.add(name),
|
|
17337
17360
|
requestAutoPause: async ({ effectiveRound, maxToolRounds: totalRounds, toolSummary }) => {
|
|
17338
17361
|
const requestId = `pause_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
17339
|
-
const pauseResp = await new Promise((
|
|
17340
|
-
this.pendingAutoPause.set(requestId,
|
|
17362
|
+
const pauseResp = await new Promise((resolve11) => {
|
|
17363
|
+
this.pendingAutoPause.set(requestId, resolve11);
|
|
17341
17364
|
this.send({
|
|
17342
17365
|
type: "auto_pause_request",
|
|
17343
17366
|
requestId,
|
|
@@ -17516,8 +17539,8 @@ ${summaryContent}`,
|
|
|
17516
17539
|
}
|
|
17517
17540
|
if (chunk.done) break;
|
|
17518
17541
|
}
|
|
17519
|
-
await new Promise((
|
|
17520
|
-
fileStream.end((err) => err ? reject(err) :
|
|
17542
|
+
await new Promise((resolve11, reject) => {
|
|
17543
|
+
fileStream.end((err) => err ? reject(err) : resolve11());
|
|
17521
17544
|
});
|
|
17522
17545
|
const verdict = evaluateTeeContent(fullContent, saveToFile, priorContent);
|
|
17523
17546
|
if (verdict.kind === "reject") {
|
|
@@ -17543,7 +17566,7 @@ ${summaryContent}`,
|
|
|
17543
17566
|
} catch (err) {
|
|
17544
17567
|
if (fileStream) {
|
|
17545
17568
|
try {
|
|
17546
|
-
await new Promise((
|
|
17569
|
+
await new Promise((resolve11) => fileStream.end(() => resolve11()));
|
|
17547
17570
|
} catch {
|
|
17548
17571
|
}
|
|
17549
17572
|
}
|
|
@@ -17591,6 +17614,13 @@ ${summaryContent}`,
|
|
|
17591
17614
|
}
|
|
17592
17615
|
// ── Commands ─────────────────────────────────────────────────────
|
|
17593
17616
|
async handleCommand(name, args) {
|
|
17617
|
+
if (CLI_ONLY_WEB_COMMANDS.has(name)) {
|
|
17618
|
+
this.send({
|
|
17619
|
+
type: "error",
|
|
17620
|
+
message: `/${name} is only available in the terminal REPL. Run \`aicli\` in a terminal and use /${name} there.`
|
|
17621
|
+
});
|
|
17622
|
+
return;
|
|
17623
|
+
}
|
|
17594
17624
|
const handler = webCommandHandlers[name];
|
|
17595
17625
|
if (handler) {
|
|
17596
17626
|
await handler(args, this);
|
|
@@ -17866,7 +17896,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17866
17896
|
return;
|
|
17867
17897
|
}
|
|
17868
17898
|
try {
|
|
17869
|
-
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-
|
|
17899
|
+
const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-Q6BKWWAM.js");
|
|
17870
17900
|
const loaded = loadChatIndex2();
|
|
17871
17901
|
if (!loaded || loaded.idx.chunks.length === 0) {
|
|
17872
17902
|
this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
|
|
@@ -17902,7 +17932,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17902
17932
|
}
|
|
17903
17933
|
async handleMemoryStatus() {
|
|
17904
17934
|
try {
|
|
17905
|
-
const { getChatIndexStatus } = await import("./chat-index-
|
|
17935
|
+
const { getChatIndexStatus } = await import("./chat-index-Q6BKWWAM.js");
|
|
17906
17936
|
const s = getChatIndexStatus();
|
|
17907
17937
|
this.send({
|
|
17908
17938
|
type: "memory_status",
|
|
@@ -17927,7 +17957,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
17927
17957
|
type: "info",
|
|
17928
17958
|
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
17959
|
});
|
|
17930
|
-
const { buildChatIndex } = await import("./chat-index-
|
|
17960
|
+
const { buildChatIndex } = await import("./chat-index-Q6BKWWAM.js");
|
|
17931
17961
|
const stats = await buildChatIndex({
|
|
17932
17962
|
full,
|
|
17933
17963
|
onProgress: (p) => {
|
|
@@ -18083,8 +18113,8 @@ async function setupProxy(configProxy) {
|
|
|
18083
18113
|
}
|
|
18084
18114
|
|
|
18085
18115
|
// src/web/auth.ts
|
|
18086
|
-
import { existsSync as
|
|
18087
|
-
import { isAbsolute as isAbsolute3, join as
|
|
18116
|
+
import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync4, mkdirSync as mkdirSync15, readdirSync as readdirSync14, copyFileSync } from "fs";
|
|
18117
|
+
import { isAbsolute as isAbsolute3, join as join24, relative as relative5 } from "path";
|
|
18088
18118
|
import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
|
|
18089
18119
|
var USERS_FILE = "users.json";
|
|
18090
18120
|
var TOKEN_EXPIRY_HOURS = 24;
|
|
@@ -18099,7 +18129,7 @@ var AuthManager = class {
|
|
|
18099
18129
|
db;
|
|
18100
18130
|
constructor(baseDir) {
|
|
18101
18131
|
this.baseDir = baseDir;
|
|
18102
|
-
this.usersFile =
|
|
18132
|
+
this.usersFile = join24(baseDir, USERS_FILE);
|
|
18103
18133
|
this.db = this.loadOrCreate();
|
|
18104
18134
|
}
|
|
18105
18135
|
// ── Public API ─────────────────────────────────────────────────
|
|
@@ -18128,9 +18158,9 @@ var AuthManager = class {
|
|
|
18128
18158
|
}
|
|
18129
18159
|
const salt = randomBytes(16).toString("hex");
|
|
18130
18160
|
const passwordHash = this.hashPassword(password, salt);
|
|
18131
|
-
const dataDir =
|
|
18132
|
-
const fullDataDir =
|
|
18133
|
-
mkdirSync15(
|
|
18161
|
+
const dataDir = join24(USERS_DIR, username);
|
|
18162
|
+
const fullDataDir = join24(this.baseDir, dataDir);
|
|
18163
|
+
mkdirSync15(join24(fullDataDir, "history"), { recursive: true });
|
|
18134
18164
|
const user = {
|
|
18135
18165
|
username,
|
|
18136
18166
|
passwordHash,
|
|
@@ -18245,7 +18275,7 @@ var AuthManager = class {
|
|
|
18245
18275
|
getUserDataDir(username) {
|
|
18246
18276
|
const user = this.db.users.find((u) => u.username === username);
|
|
18247
18277
|
if (!user) throw new Error(`User not found: ${username}`);
|
|
18248
|
-
return
|
|
18278
|
+
return join24(this.baseDir, user.dataDir);
|
|
18249
18279
|
}
|
|
18250
18280
|
/** List all usernames */
|
|
18251
18281
|
listUsers() {
|
|
@@ -18281,30 +18311,30 @@ var AuthManager = class {
|
|
|
18281
18311
|
const err = this.register(username, password);
|
|
18282
18312
|
if (err) return err;
|
|
18283
18313
|
const userDir = this.getUserDataDir(username);
|
|
18284
|
-
const globalConfig =
|
|
18285
|
-
if (
|
|
18314
|
+
const globalConfig = join24(this.baseDir, "config.json");
|
|
18315
|
+
if (existsSync29(globalConfig)) {
|
|
18286
18316
|
try {
|
|
18287
|
-
const content =
|
|
18288
|
-
|
|
18317
|
+
const content = readFileSync22(globalConfig, "utf-8");
|
|
18318
|
+
writeFileSync4(join24(userDir, "config.json"), content, "utf-8");
|
|
18289
18319
|
} catch {
|
|
18290
18320
|
}
|
|
18291
18321
|
}
|
|
18292
|
-
const globalMemory =
|
|
18293
|
-
if (
|
|
18322
|
+
const globalMemory = join24(this.baseDir, "memory.md");
|
|
18323
|
+
if (existsSync29(globalMemory)) {
|
|
18294
18324
|
try {
|
|
18295
|
-
const content =
|
|
18296
|
-
|
|
18325
|
+
const content = readFileSync22(globalMemory, "utf-8");
|
|
18326
|
+
writeFileSync4(join24(userDir, "memory.md"), content, "utf-8");
|
|
18297
18327
|
} catch {
|
|
18298
18328
|
}
|
|
18299
18329
|
}
|
|
18300
|
-
const globalHistory =
|
|
18301
|
-
if (
|
|
18330
|
+
const globalHistory = join24(this.baseDir, "history");
|
|
18331
|
+
if (existsSync29(globalHistory)) {
|
|
18302
18332
|
try {
|
|
18303
|
-
const files =
|
|
18304
|
-
const userHistory =
|
|
18333
|
+
const files = readdirSync14(globalHistory).filter((f) => f.endsWith(".json"));
|
|
18334
|
+
const userHistory = join24(userDir, "history");
|
|
18305
18335
|
for (const f of files) {
|
|
18306
18336
|
try {
|
|
18307
|
-
copyFileSync(
|
|
18337
|
+
copyFileSync(join24(globalHistory, f), join24(userHistory, f));
|
|
18308
18338
|
} catch {
|
|
18309
18339
|
}
|
|
18310
18340
|
}
|
|
@@ -18315,9 +18345,9 @@ var AuthManager = class {
|
|
|
18315
18345
|
}
|
|
18316
18346
|
// ── Private methods ────────────────────────────────────────────
|
|
18317
18347
|
loadOrCreate() {
|
|
18318
|
-
if (
|
|
18348
|
+
if (existsSync29(this.usersFile)) {
|
|
18319
18349
|
try {
|
|
18320
|
-
const parsed = JSON.parse(
|
|
18350
|
+
const parsed = JSON.parse(readFileSync22(this.usersFile, "utf-8"));
|
|
18321
18351
|
if (!this.isValidUsersDB(parsed)) {
|
|
18322
18352
|
throw new Error("database structure is invalid");
|
|
18323
18353
|
}
|
|
@@ -18351,7 +18381,7 @@ var AuthManager = class {
|
|
|
18351
18381
|
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
18382
|
return false;
|
|
18353
18383
|
}
|
|
18354
|
-
const dataDirFromBase = relative5(this.baseDir,
|
|
18384
|
+
const dataDirFromBase = relative5(this.baseDir, join24(this.baseDir, record.dataDir));
|
|
18355
18385
|
if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
|
|
18356
18386
|
if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
|
|
18357
18387
|
if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
|
|
@@ -18399,7 +18429,7 @@ function getModuleDir() {
|
|
|
18399
18429
|
}
|
|
18400
18430
|
} catch {
|
|
18401
18431
|
}
|
|
18402
|
-
return
|
|
18432
|
+
return resolve10(".");
|
|
18403
18433
|
}
|
|
18404
18434
|
async function startWebServer(options = {}) {
|
|
18405
18435
|
const port = options.port ?? 3e3;
|
|
@@ -18467,8 +18497,8 @@ async function startWebServer(options = {}) {
|
|
|
18467
18497
|
}
|
|
18468
18498
|
}
|
|
18469
18499
|
let skillManager = null;
|
|
18470
|
-
const skillsDir =
|
|
18471
|
-
if (
|
|
18500
|
+
const skillsDir = join25(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
18501
|
+
if (existsSync30(skillsDir)) {
|
|
18472
18502
|
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
18473
18503
|
skillManager.loadSkills(pluginAssets.skillDirs);
|
|
18474
18504
|
const count = skillManager.listSkills().length;
|
|
@@ -18519,6 +18549,10 @@ async function startWebServer(options = {}) {
|
|
|
18519
18549
|
console.log(` Auth: ${authManager.listUsers().length} user(s) registered`);
|
|
18520
18550
|
} else {
|
|
18521
18551
|
console.log(` Auth: disabled (no users registered)`);
|
|
18552
|
+
if (host === "0.0.0.0" || host === "::") {
|
|
18553
|
+
console.log(" WARNING: Web UI is reachable from the network without authentication.");
|
|
18554
|
+
console.log(" Create a user first for LAN/team use: aicli user create <name>");
|
|
18555
|
+
}
|
|
18522
18556
|
}
|
|
18523
18557
|
const requireAuth = (req, res, next) => {
|
|
18524
18558
|
if (!authManager.isEnabled()) return next();
|
|
@@ -18539,18 +18573,18 @@ async function startWebServer(options = {}) {
|
|
|
18539
18573
|
next();
|
|
18540
18574
|
};
|
|
18541
18575
|
const moduleDir = getModuleDir();
|
|
18542
|
-
let clientDir =
|
|
18543
|
-
if (!
|
|
18544
|
-
clientDir =
|
|
18576
|
+
let clientDir = join25(moduleDir, "web", "client");
|
|
18577
|
+
if (!existsSync30(clientDir)) {
|
|
18578
|
+
clientDir = join25(moduleDir, "client");
|
|
18545
18579
|
}
|
|
18546
|
-
if (!
|
|
18547
|
-
clientDir =
|
|
18580
|
+
if (!existsSync30(clientDir)) {
|
|
18581
|
+
clientDir = join25(moduleDir, "..", "..", "src", "web", "client");
|
|
18548
18582
|
}
|
|
18549
|
-
if (!
|
|
18550
|
-
clientDir =
|
|
18583
|
+
if (!existsSync30(clientDir)) {
|
|
18584
|
+
clientDir = join25(process.cwd(), "src", "web", "client");
|
|
18551
18585
|
}
|
|
18552
18586
|
console.log(` Static files: ${clientDir}`);
|
|
18553
|
-
app.use("/vendor", express.static(
|
|
18587
|
+
app.use("/vendor", express.static(join25(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
|
|
18554
18588
|
app.use(express.static(clientDir));
|
|
18555
18589
|
app.get("/api/status", (_req, res) => {
|
|
18556
18590
|
res.json({
|
|
@@ -18617,10 +18651,10 @@ async function startWebServer(options = {}) {
|
|
|
18617
18651
|
app.get("/api/files", requireAuth, (req, res) => {
|
|
18618
18652
|
const cwd = process.cwd();
|
|
18619
18653
|
const prefix = req.query.prefix || "";
|
|
18620
|
-
const targetDir =
|
|
18654
|
+
const targetDir = join25(cwd, prefix);
|
|
18621
18655
|
try {
|
|
18622
|
-
const canonicalTarget = realpathSync3(
|
|
18623
|
-
const canonicalCwd = realpathSync3(
|
|
18656
|
+
const canonicalTarget = realpathSync3(resolve10(targetDir));
|
|
18657
|
+
const canonicalCwd = realpathSync3(resolve10(cwd));
|
|
18624
18658
|
if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
|
|
18625
18659
|
res.json({ files: [] });
|
|
18626
18660
|
return;
|
|
@@ -18631,10 +18665,10 @@ async function startWebServer(options = {}) {
|
|
|
18631
18665
|
}
|
|
18632
18666
|
try {
|
|
18633
18667
|
const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
|
|
18634
|
-
const entries =
|
|
18668
|
+
const entries = readdirSync15(targetDir, { withFileTypes: true });
|
|
18635
18669
|
const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
|
|
18636
18670
|
name: e.name,
|
|
18637
|
-
path: relative6(cwd,
|
|
18671
|
+
path: relative6(cwd, join25(targetDir, e.name)).replace(/\\/g, "/"),
|
|
18638
18672
|
isDir: e.isDirectory()
|
|
18639
18673
|
}));
|
|
18640
18674
|
res.json({ files });
|
|
@@ -18674,8 +18708,8 @@ async function startWebServer(options = {}) {
|
|
|
18674
18708
|
try {
|
|
18675
18709
|
const authUser = req._authUser;
|
|
18676
18710
|
const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
|
|
18677
|
-
const filePath =
|
|
18678
|
-
if (!
|
|
18711
|
+
const filePath = join25(histDir, `${id}.json`);
|
|
18712
|
+
if (!existsSync30(filePath)) {
|
|
18679
18713
|
res.status(404).json({ error: "Session not found" });
|
|
18680
18714
|
return;
|
|
18681
18715
|
}
|
|
@@ -18690,7 +18724,7 @@ async function startWebServer(options = {}) {
|
|
|
18690
18724
|
res.status(404).json({ error: "Session not found" });
|
|
18691
18725
|
return;
|
|
18692
18726
|
}
|
|
18693
|
-
const data = JSON.parse(
|
|
18727
|
+
const data = JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
18694
18728
|
res.json({ session: data });
|
|
18695
18729
|
} catch (err) {
|
|
18696
18730
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
@@ -18703,10 +18737,10 @@ async function startWebServer(options = {}) {
|
|
|
18703
18737
|
return;
|
|
18704
18738
|
}
|
|
18705
18739
|
const cwd = process.cwd();
|
|
18706
|
-
const fullPath =
|
|
18740
|
+
const fullPath = resolve10(join25(cwd, filePath));
|
|
18707
18741
|
try {
|
|
18708
18742
|
const canonicalFull = realpathSync3(fullPath);
|
|
18709
|
-
const canonicalCwd = realpathSync3(
|
|
18743
|
+
const canonicalCwd = realpathSync3(resolve10(cwd));
|
|
18710
18744
|
if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
|
|
18711
18745
|
res.json({ error: "Access denied" });
|
|
18712
18746
|
return;
|
|
@@ -18716,12 +18750,12 @@ async function startWebServer(options = {}) {
|
|
|
18716
18750
|
return;
|
|
18717
18751
|
}
|
|
18718
18752
|
try {
|
|
18719
|
-
const stat =
|
|
18753
|
+
const stat = statSync13(fullPath);
|
|
18720
18754
|
if (stat.size > 512 * 1024) {
|
|
18721
18755
|
res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
|
|
18722
18756
|
return;
|
|
18723
18757
|
}
|
|
18724
|
-
const content =
|
|
18758
|
+
const content = readFileSync23(fullPath, "utf-8");
|
|
18725
18759
|
res.json({ content, size: stat.size });
|
|
18726
18760
|
} catch {
|
|
18727
18761
|
res.json({ error: "Cannot read file" });
|
|
@@ -18850,7 +18884,7 @@ async function startWebServer(options = {}) {
|
|
|
18850
18884
|
ws.send(JSON.stringify({ type: "auth_result", success: false, error: err }));
|
|
18851
18885
|
return;
|
|
18852
18886
|
}
|
|
18853
|
-
|
|
18887
|
+
authManager.login(username, password);
|
|
18854
18888
|
authenticatedUser = username;
|
|
18855
18889
|
const userShared = getUserShared(username);
|
|
18856
18890
|
handler = new SessionHandler(ws, userShared);
|
|
@@ -18925,7 +18959,7 @@ async function startWebServer(options = {}) {
|
|
|
18925
18959
|
});
|
|
18926
18960
|
const MAX_PORT_ATTEMPTS = 10;
|
|
18927
18961
|
let actualPort = port;
|
|
18928
|
-
const result = await new Promise((
|
|
18962
|
+
const result = await new Promise((resolve11, reject) => {
|
|
18929
18963
|
const tryListen = (attempt) => {
|
|
18930
18964
|
server.once("error", (err) => {
|
|
18931
18965
|
if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
|
|
@@ -18956,7 +18990,7 @@ async function startWebServer(options = {}) {
|
|
|
18956
18990
|
}
|
|
18957
18991
|
console.log(` Press Ctrl+C to stop
|
|
18958
18992
|
`);
|
|
18959
|
-
|
|
18993
|
+
resolve11({ port: actualPort, host, url });
|
|
18960
18994
|
});
|
|
18961
18995
|
};
|
|
18962
18996
|
tryListen(1);
|
|
@@ -18976,17 +19010,17 @@ function resolveProjectMcpPath() {
|
|
|
18976
19010
|
const cwd = process.cwd();
|
|
18977
19011
|
const gitRoot = getGitRoot(cwd);
|
|
18978
19012
|
const projectRoot = gitRoot ?? cwd;
|
|
18979
|
-
const configPath =
|
|
18980
|
-
return
|
|
19013
|
+
const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
19014
|
+
return existsSync30(configPath) ? configPath : null;
|
|
18981
19015
|
}
|
|
18982
19016
|
function loadProjectMcpConfig() {
|
|
18983
19017
|
const cwd = process.cwd();
|
|
18984
19018
|
const gitRoot = getGitRoot(cwd);
|
|
18985
19019
|
const projectRoot = gitRoot ?? cwd;
|
|
18986
|
-
const configPath =
|
|
18987
|
-
if (!
|
|
19020
|
+
const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
19021
|
+
if (!existsSync30(configPath)) return null;
|
|
18988
19022
|
try {
|
|
18989
|
-
const raw = JSON.parse(
|
|
19023
|
+
const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
|
|
18990
19024
|
return raw.mcpServers ?? raw;
|
|
18991
19025
|
} catch {
|
|
18992
19026
|
return null;
|