jinzd-ai-cli 0.4.263 → 0.4.265
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 +59 -37
- package/README.zh-CN.md +63 -41
- package/dist/{batch-AN47AYCZ.js → batch-C7SHXRQ2.js} +2 -2
- package/dist/{chunk-VT6NRDD2.js → chunk-23SJVOQD.js} +6 -2
- package/dist/{chunk-QMB7QYZC.js → chunk-2MR7EP24.js} +1 -1
- package/dist/chunk-5C76XDDF.js +78 -0
- package/dist/chunk-6YZEZFX5.js +40 -0
- package/dist/{chunk-TL5MD5XU.js → chunk-AUEX6RNY.js} +17 -1
- package/dist/{chunk-MTZ6XHJD.js → chunk-CVI3LSGR.js} +2 -2
- package/dist/{chunk-B27MLWFJ.js → chunk-E3JRGJCJ.js} +4 -4
- package/dist/{chunk-MJICIIBW.js → chunk-IFTUBTDA.js} +1 -1
- package/dist/{chunk-VUZAKIZ5.js → chunk-LZBD2VGJ.js} +1 -1
- package/dist/{chunk-3RHY2HF7.js → chunk-M2RKBTVZ.js} +1 -1
- package/dist/{chunk-7YCA2BD3.js → chunk-NJLPA6S4.js} +1 -1
- package/dist/{chunk-GMZTY7DA.js → chunk-NOS3QV7G.js} +13 -8
- package/dist/{chunk-GKI7B4BD.js → chunk-TJBG4F2R.js} +24 -95
- package/dist/{chunk-QG4NG7KJ.js → chunk-V4D7YD24.js} +9 -2
- package/dist/{chunk-3ARPAVNV.js → chunk-VOIOUJXI.js} +11 -3
- package/dist/{chunk-WM4VTGAF.js → chunk-X6NWK2YK.js} +1 -1
- package/dist/{chunk-VKBGOFEO.js → chunk-Y7KJPNQI.js} +1 -1
- package/dist/{chunk-XST4N2JM.js → chunk-YDTYBUAB.js} +1 -1
- package/dist/{chunk-5K2LFD7D.js → chunk-YXYOLPDB.js} +1 -1
- package/dist/{ci-JTO7LN5S.js → ci-TDXLI3OM.js} +6 -5
- package/dist/{ci-format-2VGHOLBA.js → ci-format-AFX2LP4Y.js} +2 -2
- package/dist/{constants-HLSJL5HQ.js → constants-66TQEDGO.js} +1 -1
- package/dist/{doctor-cli-JML4FGH4.js → doctor-cli-GMCOGCDR.js} +5 -5
- package/dist/electron-server.js +57 -12
- package/dist/{hub-6EYFGJRT.js → hub-2YXETHPY.js} +8 -4
- package/dist/{hub-server-QGUSMN22.js → hub-server-RF6LURXY.js} +3 -1
- package/dist/index.js +123 -546
- package/dist/{persistent-memory-MPBPSZDN.js → persistent-memory-2DKCETB7.js} +2 -2
- package/dist/{persistent-memory-ANIMO5CF.js → persistent-memory-WTZO5CQ7.js} +2 -2
- package/dist/{pr-XE7NGT6U.js → pr-Y2LDG3R7.js} +15 -10
- package/dist/{run-tests-TF7UPUWW.js → run-tests-FIUGDIDL.js} +2 -2
- package/dist/{run-tests-ME5KED57.js → run-tests-PWTNSUVP.js} +2 -2
- package/dist/{server-VKA4FR2Z.js → server-OZ4RFDFH.js} +25 -15
- package/dist/{server-BIYJEJK3.js → server-ZCG5QD6P.js} +6 -5
- package/dist/setup-wizard-S55ICNHH.js +483 -0
- package/dist/{task-orchestrator-2RAKLFWN.js → task-orchestrator-Q2L6JEUX.js} +10 -7
- package/dist/{usage-5F5Q3GGR.js → usage-SDL5Z4CS.js} +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
CostTracker
|
|
4
|
-
} from "./chunk-QG4NG7KJ.js";
|
|
5
2
|
import {
|
|
6
3
|
McpManager,
|
|
7
4
|
SNAPSHOT_PROMPT,
|
|
@@ -17,7 +14,10 @@ import {
|
|
|
17
14
|
scanProject,
|
|
18
15
|
sessionHasMeaningfulContent,
|
|
19
16
|
setupProxy
|
|
20
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-CVI3LSGR.js";
|
|
18
|
+
import {
|
|
19
|
+
CostTracker
|
|
20
|
+
} from "./chunk-V4D7YD24.js";
|
|
21
21
|
import {
|
|
22
22
|
computeCost,
|
|
23
23
|
formatCost,
|
|
@@ -27,6 +27,12 @@ import {
|
|
|
27
27
|
buildReviewPrompt,
|
|
28
28
|
buildSecurityReviewPrompt
|
|
29
29
|
} from "./chunk-HLWUDRBO.js";
|
|
30
|
+
import {
|
|
31
|
+
NO_THINKING,
|
|
32
|
+
applyThinkingFlag,
|
|
33
|
+
chatParamsFrom,
|
|
34
|
+
thinkingParamsFor
|
|
35
|
+
} from "./chunk-6YZEZFX5.js";
|
|
30
36
|
import {
|
|
31
37
|
ToolExecutor,
|
|
32
38
|
ToolRegistry,
|
|
@@ -38,7 +44,6 @@ import {
|
|
|
38
44
|
formatPermissionProfileWarning,
|
|
39
45
|
getRecentlyDeniedAutoActions,
|
|
40
46
|
googleSearchContext,
|
|
41
|
-
initTheme,
|
|
42
47
|
isInterrupted,
|
|
43
48
|
lastResponseStore,
|
|
44
49
|
renderDiff,
|
|
@@ -48,9 +53,8 @@ import {
|
|
|
48
53
|
setContextWindow,
|
|
49
54
|
setMaxOutputCap,
|
|
50
55
|
spawnAgentContext,
|
|
51
|
-
theme,
|
|
52
56
|
undoStack
|
|
53
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-TJBG4F2R.js";
|
|
54
58
|
import {
|
|
55
59
|
addMemoryEntry,
|
|
56
60
|
backupMemoryStore,
|
|
@@ -76,11 +80,15 @@ import {
|
|
|
76
80
|
touchMemoryReferences,
|
|
77
81
|
updateMemoryApproval,
|
|
78
82
|
updateMemoryEntry
|
|
79
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-LZBD2VGJ.js";
|
|
80
84
|
import "./chunk-GLSR2NR3.js";
|
|
81
85
|
import "./chunk-UUSRWSSX.js";
|
|
82
86
|
import "./chunk-CKH4KQ4E.js";
|
|
83
87
|
import "./chunk-BXP6YZ2P.js";
|
|
88
|
+
import {
|
|
89
|
+
initTheme,
|
|
90
|
+
theme
|
|
91
|
+
} from "./chunk-5C76XDDF.js";
|
|
84
92
|
import {
|
|
85
93
|
SessionManager,
|
|
86
94
|
getContentText
|
|
@@ -90,14 +98,14 @@ import {
|
|
|
90
98
|
formatDoctorReport,
|
|
91
99
|
loadContextFiles,
|
|
92
100
|
writeCrashLog
|
|
93
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-E3JRGJCJ.js";
|
|
94
102
|
import {
|
|
95
103
|
ProviderRegistry,
|
|
96
104
|
listBuiltInProviderMetadata
|
|
97
|
-
} from "./chunk-
|
|
105
|
+
} from "./chunk-AUEX6RNY.js";
|
|
98
106
|
import {
|
|
99
107
|
ConfigManager
|
|
100
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-X6NWK2YK.js";
|
|
101
109
|
import {
|
|
102
110
|
describePlugin,
|
|
103
111
|
getActivePluginAssets,
|
|
@@ -114,7 +122,7 @@ import {
|
|
|
114
122
|
trustHook,
|
|
115
123
|
trustPlugin,
|
|
116
124
|
untrustHook
|
|
117
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-2MR7EP24.js";
|
|
118
126
|
import {
|
|
119
127
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
120
128
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -148,7 +156,7 @@ import {
|
|
|
148
156
|
import {
|
|
149
157
|
fileCheckpoints
|
|
150
158
|
} from "./chunk-4BKXL7SM.js";
|
|
151
|
-
import "./chunk-
|
|
159
|
+
import "./chunk-YDTYBUAB.js";
|
|
152
160
|
import {
|
|
153
161
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
154
162
|
AUTHOR,
|
|
@@ -167,7 +175,7 @@ import {
|
|
|
167
175
|
SKILLS_DIR_NAME,
|
|
168
176
|
VERSION,
|
|
169
177
|
buildUserIdentityPrompt
|
|
170
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-Y7KJPNQI.js";
|
|
171
179
|
import {
|
|
172
180
|
buildChatIndex,
|
|
173
181
|
clearChatIndex,
|
|
@@ -237,7 +245,10 @@ Now produce the title (\u2264 12 Chinese chars or \u2264 6 English words):`,
|
|
|
237
245
|
systemPrompt: SYSTEM_PROMPT,
|
|
238
246
|
stream: false,
|
|
239
247
|
maxTokens: 40,
|
|
240
|
-
temperature: 0.3
|
|
248
|
+
temperature: 0.3,
|
|
249
|
+
// 生成标题不值得付推理成本;显式关而不是靠「未配置即关」的默认兜底——
|
|
250
|
+
// 默认值是产品决策,哪天再变,靠默认的调用点会跟着一起变贵(审计 P0-01)。
|
|
251
|
+
...NO_THINKING
|
|
241
252
|
});
|
|
242
253
|
const title = sanitizeTitle(resp.content);
|
|
243
254
|
if (!title) return;
|
|
@@ -1166,9 +1177,22 @@ function createProviderCommands() {
|
|
|
1166
1177
|
}
|
|
1167
1178
|
if (sub === "status") {
|
|
1168
1179
|
const mode = ctx.getThinkingMode();
|
|
1169
|
-
const
|
|
1180
|
+
const effective = mode ?? ctx.getConfiguredThinking() ?? false;
|
|
1181
|
+
const origin = mode !== null ? "runtime override" : ctx.getConfiguredThinking() !== void 0 ? "from config" : "default";
|
|
1182
|
+
const label = effective ? theme.accent(`ON (${origin})`) : theme.dim(`OFF (${origin})`);
|
|
1170
1183
|
console.log(` Extended Thinking: ${label}`);
|
|
1171
|
-
|
|
1184
|
+
if (effective) {
|
|
1185
|
+
const supportsEffort = ctx.getProviderSupportsReasoningEffort();
|
|
1186
|
+
if (supportsEffort) {
|
|
1187
|
+
const effort = ctx.getThinkingEffort() ?? ctx.getConfiguredThinkingEffort();
|
|
1188
|
+
console.log(` Reasoning effort: ${effort ?? "high (provider default)"}`);
|
|
1189
|
+
} else {
|
|
1190
|
+
console.log(theme.dim(` Reasoning effort: n/a for ${ctx.getCurrentProvider()}`));
|
|
1191
|
+
}
|
|
1192
|
+
} else {
|
|
1193
|
+
console.log(theme.dim(" Enable with /think on | low | high | max, or set"));
|
|
1194
|
+
console.log(theme.dim(" modelParams.<model>.thinking in ~/.aicli/config.json"));
|
|
1195
|
+
}
|
|
1172
1196
|
console.log();
|
|
1173
1197
|
return;
|
|
1174
1198
|
}
|
|
@@ -1340,12 +1364,12 @@ No tools match "${filter}".
|
|
|
1340
1364
|
return;
|
|
1341
1365
|
}
|
|
1342
1366
|
if (sub === "install") {
|
|
1343
|
-
const
|
|
1344
|
-
if (!
|
|
1367
|
+
const input = args[1];
|
|
1368
|
+
if (!input) {
|
|
1345
1369
|
ctx.renderer.printInfo("Usage: /plugin install <path-to-plugin-dir>");
|
|
1346
1370
|
return;
|
|
1347
1371
|
}
|
|
1348
|
-
const plugin = installPlugin(configDir,
|
|
1372
|
+
const plugin = installPlugin(configDir, input);
|
|
1349
1373
|
ctx.renderer.printSuccess(`Installed plugin ${plugin.name}@${plugin.manifest.version}. Run /plugin trust ${plugin.name}, then /plugin enable ${plugin.name}.`);
|
|
1350
1374
|
return;
|
|
1351
1375
|
}
|
|
@@ -1407,7 +1431,7 @@ No tools match "${filter}".
|
|
|
1407
1431
|
const { join: join6 } = await import("path");
|
|
1408
1432
|
const { existsSync: existsSync6 } = await import("fs");
|
|
1409
1433
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
|
|
1410
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1434
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-66TQEDGO.js");
|
|
1411
1435
|
const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
|
|
1412
1436
|
const cwd = process.cwd();
|
|
1413
1437
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -2395,7 +2419,7 @@ function createReviewCommands() {
|
|
|
2395
2419
|
usage: "/test [command|filter]",
|
|
2396
2420
|
async execute(args, ctx) {
|
|
2397
2421
|
try {
|
|
2398
|
-
const { executeTests } = await import("./run-tests-
|
|
2422
|
+
const { executeTests } = await import("./run-tests-PWTNSUVP.js");
|
|
2399
2423
|
const argStr = args.join(" ").trim();
|
|
2400
2424
|
let testArgs = {};
|
|
2401
2425
|
if (argStr) {
|
|
@@ -3782,17 +3806,20 @@ ${text}
|
|
|
3782
3806
|
}
|
|
3783
3807
|
const provider = ctx.getCurrentProvider();
|
|
3784
3808
|
const model = ctx.getCurrentModel();
|
|
3785
|
-
const cost = computeCost(provider, model, usage);
|
|
3786
3809
|
const pricing = getPricing(provider, model);
|
|
3810
|
+
const accrued = ctx.getSessionAccruedCost();
|
|
3811
|
+
const usedAccrual = accrued.usd > 0;
|
|
3812
|
+
const cost = usedAccrual ? accrued.usd : computeCost(provider, model, usage);
|
|
3787
3813
|
let savings = null;
|
|
3788
|
-
|
|
3814
|
+
const liveCost = computeCost(provider, model, usage);
|
|
3815
|
+
if (liveCost != null && pricing && cacheRead > 0) {
|
|
3789
3816
|
const costWithoutCache = computeCost(provider, model, {
|
|
3790
3817
|
inputTokens: usage.inputTokens + cacheRead,
|
|
3791
3818
|
outputTokens: usage.outputTokens,
|
|
3792
3819
|
cacheCreationTokens: cacheCreate,
|
|
3793
3820
|
cacheReadTokens: 0
|
|
3794
3821
|
});
|
|
3795
|
-
if (costWithoutCache != null) savings = costWithoutCache -
|
|
3822
|
+
if (costWithoutCache != null) savings = costWithoutCache - liveCost;
|
|
3796
3823
|
}
|
|
3797
3824
|
console.log();
|
|
3798
3825
|
console.log(theme.heading(" \u{1F4B0} Session Cost & Token Usage"));
|
|
@@ -3812,6 +3839,11 @@ ${text}
|
|
|
3812
3839
|
console.log(theme.dim(" " + "\u2500".repeat(48)));
|
|
3813
3840
|
if (cost != null) {
|
|
3814
3841
|
console.log(theme.dim(" Cost : ") + chalk3.bold.cyan(formatCost(cost).padStart(12)));
|
|
3842
|
+
if (usedAccrual && accrued.incomplete) {
|
|
3843
|
+
console.log(theme.dim(" (partial \u2014 some turns had unknown pricing)"));
|
|
3844
|
+
} else if (!usedAccrual) {
|
|
3845
|
+
console.log(theme.dim(" (estimated at current rates)"));
|
|
3846
|
+
}
|
|
3815
3847
|
if (savings != null && savings > 0) {
|
|
3816
3848
|
console.log(
|
|
3817
3849
|
theme.dim(" Cache savings : ") + chalk3.green(`-${formatCost(savings)}`.padStart(12)) + theme.dim(` (vs no cache)`)
|
|
@@ -4484,482 +4516,6 @@ var streamToFileContext = {
|
|
|
4484
4516
|
extraMessages: []
|
|
4485
4517
|
};
|
|
4486
4518
|
|
|
4487
|
-
// src/repl/setup-wizard.ts
|
|
4488
|
-
import { password, select, input, confirm } from "@inquirer/prompts";
|
|
4489
|
-
var PROVIDERS = [
|
|
4490
|
-
{ value: "claude", name: "Claude (Anthropic)" },
|
|
4491
|
-
{ value: "gemini", name: "Gemini (Google)" },
|
|
4492
|
-
{ value: "deepseek", name: "DeepSeek" },
|
|
4493
|
-
{ value: "zhipu", name: "Zhipu (GLM)" },
|
|
4494
|
-
{ value: "kimi", name: "Kimi (Moonshot AI)" },
|
|
4495
|
-
{ value: "minimax", name: "MiniMax (\u6D77\u87BA)" },
|
|
4496
|
-
{ value: "qwen", name: "Qwen (Alibaba Cloud)" },
|
|
4497
|
-
{ value: "openai", name: "OpenAI" },
|
|
4498
|
-
{ value: "openrouter", name: "OpenRouter" },
|
|
4499
|
-
{ value: "ollama", name: "Ollama (Local)" }
|
|
4500
|
-
];
|
|
4501
|
-
var NO_KEY_PROVIDERS = /* @__PURE__ */ new Set(["ollama"]);
|
|
4502
|
-
var OLLAMA_DEFAULT_HOST = "http://localhost:11434";
|
|
4503
|
-
function maskKey(key) {
|
|
4504
|
-
if (key.length <= 10) return "****";
|
|
4505
|
-
return key.slice(0, 6) + "****" + key.slice(-4);
|
|
4506
|
-
}
|
|
4507
|
-
function errorMessage(err) {
|
|
4508
|
-
if (err instanceof Error && err.message) return err.message;
|
|
4509
|
-
return String(err ?? "unknown error");
|
|
4510
|
-
}
|
|
4511
|
-
var SetupWizard = class {
|
|
4512
|
-
constructor(config) {
|
|
4513
|
-
this.config = config;
|
|
4514
|
-
}
|
|
4515
|
-
config;
|
|
4516
|
-
async runFirstRun() {
|
|
4517
|
-
console.log(theme.heading("\nWelcome to ai-cli!\n"));
|
|
4518
|
-
console.log("Let's get to know you first, then set up your AI provider.\n");
|
|
4519
|
-
try {
|
|
4520
|
-
await this.setupProfile();
|
|
4521
|
-
console.log();
|
|
4522
|
-
const providerId = await select({
|
|
4523
|
-
message: "Which AI provider do you want to set up first?",
|
|
4524
|
-
choices: PROVIDERS
|
|
4525
|
-
});
|
|
4526
|
-
await this.setupProvider(providerId);
|
|
4527
|
-
this.config.set("defaultProvider", providerId);
|
|
4528
|
-
this.config.save();
|
|
4529
|
-
const nickname = this.config.get("userProfile")?.nickname;
|
|
4530
|
-
const greeting = nickname ? `Setup complete, ${nickname}!` : "Setup complete!";
|
|
4531
|
-
console.log(theme.success(`
|
|
4532
|
-
${greeting} Starting ai-cli...
|
|
4533
|
-
`));
|
|
4534
|
-
return true;
|
|
4535
|
-
} catch (err) {
|
|
4536
|
-
const message = errorMessage(err);
|
|
4537
|
-
const canceled = /user force closed|interrupted|cancel|aborted/i.test(message);
|
|
4538
|
-
if (canceled) {
|
|
4539
|
-
console.log(theme.warning("\nSetup canceled. Run aicli config to try again.\n"));
|
|
4540
|
-
} else {
|
|
4541
|
-
console.log(theme.error(`
|
|
4542
|
-
First-run setup failed: ${message}`));
|
|
4543
|
-
console.log(theme.dim(`Config directory: ${this.config.getConfigDir()}`));
|
|
4544
|
-
console.log(theme.dim("Run aicli config to retry, or aicli doctor to inspect provider/config health.\n"));
|
|
4545
|
-
}
|
|
4546
|
-
return false;
|
|
4547
|
-
}
|
|
4548
|
-
}
|
|
4549
|
-
async runFull() {
|
|
4550
|
-
console.log(theme.heading("\nai-cli Configuration\n"));
|
|
4551
|
-
let running = true;
|
|
4552
|
-
while (running) {
|
|
4553
|
-
const currentProxy = this.config.get("proxy") ?? "";
|
|
4554
|
-
const proxyStatus = currentProxy ? theme.success(`[${currentProxy}]`) : theme.dim("[not configured]");
|
|
4555
|
-
const googleKeyStatus = this.config.getApiKey("google-search") ? theme.success("[configured]") : theme.dim("[not configured]");
|
|
4556
|
-
const profileName = this.config.get("userProfile")?.nickname || this.config.get("userProfile")?.name;
|
|
4557
|
-
const profileStatus = profileName ? theme.success(`[${profileName}]`) : theme.dim("[not configured]");
|
|
4558
|
-
const yoloOn = this.config.get("alwaysYolo") === true;
|
|
4559
|
-
const mcpOff = this.config.get("mcpEnabled") === false;
|
|
4560
|
-
const behaviorFlags = [];
|
|
4561
|
-
if (yoloOn) behaviorFlags.push("YOLO on");
|
|
4562
|
-
if (mcpOff) behaviorFlags.push("MCP off");
|
|
4563
|
-
const behaviorStatus = behaviorFlags.length ? theme.warning(`[${behaviorFlags.join(", ")}]`) : theme.dim("[default]");
|
|
4564
|
-
const action = await select({
|
|
4565
|
-
message: "What would you like to configure?",
|
|
4566
|
-
choices: [
|
|
4567
|
-
{ value: "profile", name: `Edit your profile (identity) ${profileStatus}` },
|
|
4568
|
-
{ value: "apikey", name: "Manage API key for a provider" },
|
|
4569
|
-
{ value: "default", name: "Change default provider" },
|
|
4570
|
-
{ value: "proxy", name: `Configure proxy (HTTP/HTTPS) ${proxyStatus}` },
|
|
4571
|
-
{ value: "google", name: `Configure Google Search (API Key + CX) ${googleKeyStatus}` },
|
|
4572
|
-
{ value: "behavior", name: `Behavior toggles (YOLO, MCP, ...) ${behaviorStatus}` },
|
|
4573
|
-
{ value: "preset", name: "Apply task preset (safe review, workspace coding, local-only, team web)" },
|
|
4574
|
-
{ value: "done", name: "Done" }
|
|
4575
|
-
]
|
|
4576
|
-
});
|
|
4577
|
-
if (action === "profile") {
|
|
4578
|
-
await this.setupProfile();
|
|
4579
|
-
} else if (action === "proxy") {
|
|
4580
|
-
await this.setupProxy();
|
|
4581
|
-
} else if (action === "google") {
|
|
4582
|
-
await this.setupGoogleSearch();
|
|
4583
|
-
} else if (action === "behavior") {
|
|
4584
|
-
await this.setupBehavior();
|
|
4585
|
-
} else if (action === "preset") {
|
|
4586
|
-
await this.setupPreset();
|
|
4587
|
-
} else if (action === "apikey") {
|
|
4588
|
-
const choicesWithStatus = PROVIDERS.map((p) => {
|
|
4589
|
-
if (NO_KEY_PROVIDERS.has(p.value)) {
|
|
4590
|
-
return { value: p.value, name: `${p.name} ${theme.dim("[no API key needed]")}` };
|
|
4591
|
-
}
|
|
4592
|
-
const existingKey = this.config.getApiKey(p.value);
|
|
4593
|
-
const status = existingKey ? theme.success(`[${maskKey(existingKey)}]`) : theme.dim("[not configured]");
|
|
4594
|
-
return { value: p.value, name: `${p.name} ${status}` };
|
|
4595
|
-
});
|
|
4596
|
-
const providerId = await select({
|
|
4597
|
-
message: "Select provider:",
|
|
4598
|
-
choices: choicesWithStatus
|
|
4599
|
-
});
|
|
4600
|
-
await this.setupProvider(providerId);
|
|
4601
|
-
} else if (action === "default") {
|
|
4602
|
-
const providerId = await select({
|
|
4603
|
-
message: "Select default provider:",
|
|
4604
|
-
choices: PROVIDERS
|
|
4605
|
-
});
|
|
4606
|
-
this.config.set("defaultProvider", providerId);
|
|
4607
|
-
this.config.save();
|
|
4608
|
-
console.log(theme.success(`Default provider set to: ${providerId}
|
|
4609
|
-
`));
|
|
4610
|
-
} else {
|
|
4611
|
-
running = false;
|
|
4612
|
-
}
|
|
4613
|
-
}
|
|
4614
|
-
}
|
|
4615
|
-
async setupPreset() {
|
|
4616
|
-
const preset = await select({
|
|
4617
|
-
message: "Choose a task-oriented preset:",
|
|
4618
|
-
choices: [
|
|
4619
|
-
{ value: "safe-review", name: "Safe review only - read-only tools, network confirm" },
|
|
4620
|
-
{ value: "workspace-coding", name: "Workspace coding - write in workspace with confirmations" },
|
|
4621
|
-
{ value: "local-ollama", name: "Local-only Ollama - local provider, external network denied" },
|
|
4622
|
-
{ value: "team-web", name: "Team Web UI - workspace coding plus auth reminder" }
|
|
4623
|
-
]
|
|
4624
|
-
});
|
|
4625
|
-
const currentNetwork = this.config.get("networkPolicy");
|
|
4626
|
-
if (preset === "safe-review") {
|
|
4627
|
-
this.config.set("defaultPermissionProfile", "read-only");
|
|
4628
|
-
this.config.set("alwaysYolo", false);
|
|
4629
|
-
this.config.set("networkPolicy", { ...currentNetwork, enabled: true, defaultAction: "confirm", tools: { ...currentNetwork.tools, shell: "confirm", web_fetch: "confirm", web_search: "confirm", google_search: "confirm", mcp: "confirm" } });
|
|
4630
|
-
console.log(theme.success("Preset applied: Safe review only. Writes require denial/confirmation according to the read-only profile."));
|
|
4631
|
-
} else if (preset === "workspace-coding") {
|
|
4632
|
-
this.config.set("defaultPermissionProfile", "workspace-write");
|
|
4633
|
-
this.config.set("alwaysYolo", false);
|
|
4634
|
-
this.config.set("networkPolicy", { ...currentNetwork, enabled: true, defaultAction: "confirm", tools: { ...currentNetwork.tools, shell: "confirm", web_fetch: "confirm", web_search: "confirm", google_search: "confirm", mcp: "confirm" } });
|
|
4635
|
-
console.log(theme.success("Preset applied: Workspace coding. File writes stay inside the workspace and sensitive actions still ask."));
|
|
4636
|
-
} else if (preset === "local-ollama") {
|
|
4637
|
-
this.config.set("defaultProvider", "ollama");
|
|
4638
|
-
this.config.set("defaultPermissionProfile", "workspace-write");
|
|
4639
|
-
this.config.set("alwaysYolo", false);
|
|
4640
|
-
this.config.set("networkPolicy", { ...currentNetwork, enabled: true, defaultAction: "deny", allowPrivateNetwork: true, tools: { ...currentNetwork.tools, shell: "confirm", web_fetch: "deny", web_search: "deny", google_search: "deny", mcp: "confirm" } });
|
|
4641
|
-
console.log(theme.success("Preset applied: Local-only Ollama. External web/search is denied; private network is allowed for local services."));
|
|
4642
|
-
} else {
|
|
4643
|
-
this.config.set("defaultPermissionProfile", "workspace-write");
|
|
4644
|
-
this.config.set("alwaysYolo", false);
|
|
4645
|
-
this.config.set("networkPolicy", { ...currentNetwork, enabled: true, defaultAction: "confirm", tools: { ...currentNetwork.tools, shell: "confirm", web_fetch: "confirm", web_search: "confirm", google_search: "confirm", mcp: "confirm" } });
|
|
4646
|
-
console.log(theme.warning("Preset applied: Team Web UI. Start Web with auth enabled and put it behind your normal TLS/reverse proxy boundary."));
|
|
4647
|
-
}
|
|
4648
|
-
this.config.save();
|
|
4649
|
-
console.log(theme.dim("Review changes with aicli doctor or aicli config.\n"));
|
|
4650
|
-
}
|
|
4651
|
-
async setupProvider(providerId) {
|
|
4652
|
-
if (NO_KEY_PROVIDERS.has(providerId)) {
|
|
4653
|
-
await this.setupOllama();
|
|
4654
|
-
return;
|
|
4655
|
-
}
|
|
4656
|
-
const provider = PROVIDERS.find((p) => p.value === providerId);
|
|
4657
|
-
const displayName = provider?.name ?? providerId;
|
|
4658
|
-
const existingKey = this.config.getApiKey(providerId);
|
|
4659
|
-
console.log(`
|
|
4660
|
-
Managing ${displayName} API Key`);
|
|
4661
|
-
if (existingKey) {
|
|
4662
|
-
console.log(theme.dim(` Current: ${maskKey(existingKey)}`));
|
|
4663
|
-
} else {
|
|
4664
|
-
console.log(theme.dim(" Current: (not configured)"));
|
|
4665
|
-
}
|
|
4666
|
-
const choices = existingKey ? [
|
|
4667
|
-
{ value: "keep", name: "Keep current key" },
|
|
4668
|
-
{ value: "fingerprint", name: `Copy masked fingerprint (${maskKey(existingKey)})` },
|
|
4669
|
-
{ value: "change", name: "Update key" }
|
|
4670
|
-
] : [{ value: "change", name: "Enter key" }, { value: "skip", name: "Skip" }];
|
|
4671
|
-
const action = await select({
|
|
4672
|
-
message: "Action:",
|
|
4673
|
-
choices
|
|
4674
|
-
});
|
|
4675
|
-
if (action === "fingerprint" && existingKey) {
|
|
4676
|
-
console.log(theme.dim(`
|
|
4677
|
-
Fingerprint: ${maskKey(existingKey)}`));
|
|
4678
|
-
console.log(theme.dim(" Full secrets are not printed. Use Update key to replace it.\n"));
|
|
4679
|
-
return;
|
|
4680
|
-
} else if (action === "keep" || action === "skip") {
|
|
4681
|
-
return;
|
|
4682
|
-
}
|
|
4683
|
-
const newKey = await password({
|
|
4684
|
-
message: `Enter ${displayName} API key:`,
|
|
4685
|
-
validate: (val) => val.length > 0 || "API key cannot be empty"
|
|
4686
|
-
});
|
|
4687
|
-
this.config.setApiKey(providerId, newKey);
|
|
4688
|
-
console.log(theme.success(`API key saved for ${displayName}: ${maskKey(newKey)}
|
|
4689
|
-
`));
|
|
4690
|
-
}
|
|
4691
|
-
/** Ollama 专用配置:检测连通性、发现本地模型、可选自定义地址 */
|
|
4692
|
-
async setupOllama() {
|
|
4693
|
-
console.log(theme.heading("\n\u{1F999} Ollama (Local) Configuration"));
|
|
4694
|
-
console.log(theme.dim(" Ollama runs AI models locally \u2014 no API key needed."));
|
|
4695
|
-
console.log(theme.dim(" Install: https://ollama.com\n"));
|
|
4696
|
-
const customBaseUrls = this.config.get("customBaseUrls") ?? {};
|
|
4697
|
-
const currentHost = customBaseUrls["ollama"] ? customBaseUrls["ollama"].replace(/\/v1\/?$/, "") : OLLAMA_DEFAULT_HOST;
|
|
4698
|
-
const ollamaHost = await input({
|
|
4699
|
-
message: "Ollama server address:",
|
|
4700
|
-
default: currentHost,
|
|
4701
|
-
validate: (val) => {
|
|
4702
|
-
if (!val) return "Address cannot be empty";
|
|
4703
|
-
if (!val.startsWith("http://") && !val.startsWith("https://")) {
|
|
4704
|
-
return "Must start with http:// or https://";
|
|
4705
|
-
}
|
|
4706
|
-
return true;
|
|
4707
|
-
}
|
|
4708
|
-
});
|
|
4709
|
-
const host = ollamaHost.replace(/\/+$/, "");
|
|
4710
|
-
console.log(theme.dim(`
|
|
4711
|
-
Connecting to ${host}...`));
|
|
4712
|
-
let models = [];
|
|
4713
|
-
try {
|
|
4714
|
-
const res = await fetch(`${host}/api/tags`, { signal: AbortSignal.timeout(5e3) });
|
|
4715
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4716
|
-
const data = await res.json();
|
|
4717
|
-
models = data.models ?? [];
|
|
4718
|
-
} catch {
|
|
4719
|
-
console.log(theme.error(` \u2717 Cannot connect to Ollama at ${host}`));
|
|
4720
|
-
console.log(theme.dim(" Make sure Ollama is running: ollama serve\n"));
|
|
4721
|
-
return;
|
|
4722
|
-
}
|
|
4723
|
-
if (models.length === 0) {
|
|
4724
|
-
console.log(theme.warning(" \u26A0 Ollama is running but no models installed."));
|
|
4725
|
-
console.log(theme.dim(" Install a model: ollama pull llama3.1\n"));
|
|
4726
|
-
return;
|
|
4727
|
-
}
|
|
4728
|
-
console.log(theme.success(` \u2713 Connected! Found ${models.length} model(s):
|
|
4729
|
-
`));
|
|
4730
|
-
for (const m of models) {
|
|
4731
|
-
const size = m.details?.parameter_size ?? `${(m.size / 1e9).toFixed(1)}GB`;
|
|
4732
|
-
console.log(` \u2022 ${m.name} ${theme.dim(`(${size})`)}`);
|
|
4733
|
-
}
|
|
4734
|
-
console.log();
|
|
4735
|
-
if (host !== OLLAMA_DEFAULT_HOST) {
|
|
4736
|
-
const urls = { ...customBaseUrls, ollama: `${host}/v1` };
|
|
4737
|
-
this.config.set("customBaseUrls", urls);
|
|
4738
|
-
}
|
|
4739
|
-
this.config.save();
|
|
4740
|
-
console.log(theme.success(" Ollama configured! Use /provider ollama to switch.\n"));
|
|
4741
|
-
}
|
|
4742
|
-
async setupProxy() {
|
|
4743
|
-
const current = this.config.get("proxy") ?? "";
|
|
4744
|
-
console.log("\nHTTP/HTTPS Proxy Configuration");
|
|
4745
|
-
console.log(theme.dim(" Used for providers that require a proxy (e.g. Gemini in China)"));
|
|
4746
|
-
if (current) {
|
|
4747
|
-
console.log(theme.dim(` Current: ${current}`));
|
|
4748
|
-
}
|
|
4749
|
-
const action = await select({
|
|
4750
|
-
message: "Action:",
|
|
4751
|
-
choices: current ? [
|
|
4752
|
-
{ value: "keep", name: "Keep current" },
|
|
4753
|
-
{ value: "change", name: "Update" },
|
|
4754
|
-
{ value: "clear", name: "Remove proxy" }
|
|
4755
|
-
] : [
|
|
4756
|
-
{ value: "change", name: "Set proxy" },
|
|
4757
|
-
{ value: "skip", name: "Skip" }
|
|
4758
|
-
]
|
|
4759
|
-
});
|
|
4760
|
-
if (action === "keep" || action === "skip") return;
|
|
4761
|
-
if (action === "clear") {
|
|
4762
|
-
this.config.set("proxy", void 0);
|
|
4763
|
-
this.config.save();
|
|
4764
|
-
console.log(theme.success("Proxy cleared.\n"));
|
|
4765
|
-
return;
|
|
4766
|
-
}
|
|
4767
|
-
const proxyUrl = await input({
|
|
4768
|
-
message: "Enter proxy URL (e.g. http://127.0.0.1:10809):",
|
|
4769
|
-
default: current || void 0,
|
|
4770
|
-
validate: (val) => {
|
|
4771
|
-
if (!val) return "Proxy URL cannot be empty";
|
|
4772
|
-
if (!val.startsWith("http://") && !val.startsWith("https://")) {
|
|
4773
|
-
return "Must start with http:// or https://";
|
|
4774
|
-
}
|
|
4775
|
-
return true;
|
|
4776
|
-
}
|
|
4777
|
-
});
|
|
4778
|
-
this.config.set("proxy", proxyUrl);
|
|
4779
|
-
this.config.save();
|
|
4780
|
-
console.log(theme.success(`Proxy saved: ${proxyUrl}
|
|
4781
|
-
`));
|
|
4782
|
-
}
|
|
4783
|
-
/** Behavior toggles — alwaysYolo, mcpEnabled, and friends (v0.4.126+). */
|
|
4784
|
-
async setupBehavior() {
|
|
4785
|
-
let running = true;
|
|
4786
|
-
while (running) {
|
|
4787
|
-
const yoloOn = this.config.get("alwaysYolo") === true;
|
|
4788
|
-
const mcpEnabled = this.config.get("mcpEnabled") !== false;
|
|
4789
|
-
const yoloStatus = yoloOn ? theme.warning("[ON]") : theme.dim("[off]");
|
|
4790
|
-
const mcpStatus = mcpEnabled ? theme.success("[enabled]") : theme.warning("[disabled]");
|
|
4791
|
-
console.log(theme.heading("\n\u2699 Behavior Toggles\n"));
|
|
4792
|
-
const action = await select({
|
|
4793
|
-
message: "Which toggle?",
|
|
4794
|
-
choices: [
|
|
4795
|
-
{ value: "yolo", name: `alwaysYolo ${yoloStatus}` },
|
|
4796
|
-
{ value: "mcp", name: `mcpEnabled ${mcpStatus}` },
|
|
4797
|
-
{ value: "done", name: "Done" }
|
|
4798
|
-
]
|
|
4799
|
-
});
|
|
4800
|
-
if (action === "yolo") {
|
|
4801
|
-
await this.toggleAlwaysYolo();
|
|
4802
|
-
} else if (action === "mcp") {
|
|
4803
|
-
await this.toggleMcpEnabled();
|
|
4804
|
-
} else {
|
|
4805
|
-
running = false;
|
|
4806
|
-
}
|
|
4807
|
-
}
|
|
4808
|
-
}
|
|
4809
|
-
async toggleAlwaysYolo() {
|
|
4810
|
-
const current = this.config.get("alwaysYolo") === true;
|
|
4811
|
-
console.log(" alwaysYolo: " + (current ? theme.warning("ON") : theme.dim("off")));
|
|
4812
|
-
console.log(
|
|
4813
|
-
theme.dim(
|
|
4814
|
-
" When ON, REPL starts with sessionAutoApprove enabled \u2014 write\n tools (write_file/edit_file, etc.) run without confirmation prompts. Destructive tools still require confirmation. Only enable this\n if you fully trust the working directory you run aicli in.\n"
|
|
4815
|
-
)
|
|
4816
|
-
);
|
|
4817
|
-
const next = await confirm({
|
|
4818
|
-
message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip write confirmations; destructive still confirms)?",
|
|
4819
|
-
default: current
|
|
4820
|
-
});
|
|
4821
|
-
if (next === current) {
|
|
4822
|
-
console.log(theme.dim(" No change.\n"));
|
|
4823
|
-
return;
|
|
4824
|
-
}
|
|
4825
|
-
this.config.set("alwaysYolo", next);
|
|
4826
|
-
this.config.save();
|
|
4827
|
-
if (next) {
|
|
4828
|
-
console.log(theme.warning(" \u26A1 alwaysYolo enabled \u2014 confirmations will be skipped on next REPL start.\n"));
|
|
4829
|
-
} else {
|
|
4830
|
-
console.log(theme.success(" alwaysYolo disabled \u2014 confirmations restored on next REPL start.\n"));
|
|
4831
|
-
}
|
|
4832
|
-
}
|
|
4833
|
-
async toggleMcpEnabled() {
|
|
4834
|
-
const current = this.config.get("mcpEnabled") !== false;
|
|
4835
|
-
console.log(" mcpEnabled: " + (current ? theme.success("enabled") : theme.warning("disabled")));
|
|
4836
|
-
console.log(
|
|
4837
|
-
theme.dim(
|
|
4838
|
-
" Global switch for the MCP (Model Context Protocol) subsystem. When disabled,\n REPL startup skips loadProjectMcpConfig() and mcpManager.connectAll() \u2014\n no MCP servers are spawned, no MCP tools appear in the tool list, faster boot.\n Per-server entries in config.mcpServers are preserved but ignored. Disable this\n if you don't use MCP and want a leaner startup / smaller tool schema.\n"
|
|
4839
|
-
)
|
|
4840
|
-
);
|
|
4841
|
-
const next = await confirm({
|
|
4842
|
-
message: current ? "Keep MCP enabled?" : "Re-enable MCP?",
|
|
4843
|
-
default: current
|
|
4844
|
-
});
|
|
4845
|
-
if (next === current) {
|
|
4846
|
-
console.log(theme.dim(" No change.\n"));
|
|
4847
|
-
return;
|
|
4848
|
-
}
|
|
4849
|
-
this.config.set("mcpEnabled", next);
|
|
4850
|
-
this.config.save();
|
|
4851
|
-
if (next) {
|
|
4852
|
-
console.log(theme.success(" MCP enabled \u2014 servers will connect on next REPL start.\n"));
|
|
4853
|
-
} else {
|
|
4854
|
-
console.log(theme.warning(" \u{1F50C} MCP disabled \u2014 no MCP servers will load on next REPL start.\n"));
|
|
4855
|
-
}
|
|
4856
|
-
}
|
|
4857
|
-
async setupGoogleSearch() {
|
|
4858
|
-
console.log("\nGoogle Custom Search Configuration");
|
|
4859
|
-
console.log(theme.dim(" Enables AI to search the web via google_search tool"));
|
|
4860
|
-
console.log(theme.dim(" Requires: API Key + Search Engine ID (cx)"));
|
|
4861
|
-
console.log(theme.dim(" Get API Key: https://console.cloud.google.com/apis/credentials"));
|
|
4862
|
-
console.log(theme.dim(" Get CX: https://programmablesearchengine.google.com/"));
|
|
4863
|
-
const existingKey = this.config.getApiKey("google-search");
|
|
4864
|
-
if (existingKey) {
|
|
4865
|
-
console.log(theme.dim(`
|
|
4866
|
-
API Key: ${maskKey(existingKey)}`));
|
|
4867
|
-
} else {
|
|
4868
|
-
console.log(theme.dim("\n API Key: (not configured)"));
|
|
4869
|
-
}
|
|
4870
|
-
const keyAction = await select({
|
|
4871
|
-
message: "API Key:",
|
|
4872
|
-
choices: existingKey ? [
|
|
4873
|
-
{ value: "keep", name: "Keep current" },
|
|
4874
|
-
{ value: "change", name: "Update API Key" }
|
|
4875
|
-
] : [
|
|
4876
|
-
{ value: "change", name: "Enter API Key" },
|
|
4877
|
-
{ value: "skip", name: "Skip" }
|
|
4878
|
-
]
|
|
4879
|
-
});
|
|
4880
|
-
if (keyAction === "change") {
|
|
4881
|
-
const newKey = await password({
|
|
4882
|
-
message: "Enter Google API Key:",
|
|
4883
|
-
validate: (val) => val.length > 0 || "API key cannot be empty"
|
|
4884
|
-
});
|
|
4885
|
-
this.config.setApiKey("google-search", newKey);
|
|
4886
|
-
console.log(theme.success(` API Key saved: ${maskKey(newKey)}`));
|
|
4887
|
-
}
|
|
4888
|
-
const existingCx = this.config.get("googleSearchEngineId") ?? "";
|
|
4889
|
-
if (existingCx) {
|
|
4890
|
-
console.log(theme.dim(`
|
|
4891
|
-
Search Engine ID: ${existingCx}`));
|
|
4892
|
-
} else {
|
|
4893
|
-
console.log(theme.dim("\n Search Engine ID: (not configured)"));
|
|
4894
|
-
}
|
|
4895
|
-
const cxAction = await select({
|
|
4896
|
-
message: "Search Engine ID (cx):",
|
|
4897
|
-
choices: existingCx ? [
|
|
4898
|
-
{ value: "keep", name: "Keep current" },
|
|
4899
|
-
{ value: "change", name: "Update CX" }
|
|
4900
|
-
] : [
|
|
4901
|
-
{ value: "change", name: "Enter CX" },
|
|
4902
|
-
{ value: "skip", name: "Skip" }
|
|
4903
|
-
]
|
|
4904
|
-
});
|
|
4905
|
-
if (cxAction === "change") {
|
|
4906
|
-
const newCx = await input({
|
|
4907
|
-
message: "Enter Search Engine ID (cx):",
|
|
4908
|
-
default: existingCx || void 0,
|
|
4909
|
-
validate: (val) => val.length > 0 || "Search Engine ID cannot be empty"
|
|
4910
|
-
});
|
|
4911
|
-
this.config.set("googleSearchEngineId", newCx);
|
|
4912
|
-
this.config.save();
|
|
4913
|
-
console.log(theme.success(` Search Engine ID saved: ${newCx}`));
|
|
4914
|
-
}
|
|
4915
|
-
console.log();
|
|
4916
|
-
}
|
|
4917
|
-
/** 收集用户身份档案 — aicli 的 "灵魂" 功能 */
|
|
4918
|
-
async setupProfile() {
|
|
4919
|
-
const existing = this.config.get("userProfile") ?? {};
|
|
4920
|
-
console.log(theme.heading("\n\u{1F464} Your Profile"));
|
|
4921
|
-
console.log(theme.dim(" This helps AI know who you are \u2014 across all providers and sessions.\n"));
|
|
4922
|
-
const name = await input({
|
|
4923
|
-
message: "Your name:",
|
|
4924
|
-
default: existing.name || void 0
|
|
4925
|
-
});
|
|
4926
|
-
const nickname = await input({
|
|
4927
|
-
message: "Preferred nickname (AI will call you this):",
|
|
4928
|
-
default: existing.nickname || void 0
|
|
4929
|
-
});
|
|
4930
|
-
const role = await input({
|
|
4931
|
-
message: 'Your role (e.g. "Full-stack developer", "Student"):',
|
|
4932
|
-
default: existing.role || void 0
|
|
4933
|
-
});
|
|
4934
|
-
const bio = await input({
|
|
4935
|
-
message: "Brief intro (1-2 sentences about your background):",
|
|
4936
|
-
default: existing.bio || void 0
|
|
4937
|
-
});
|
|
4938
|
-
const interestsStr = await input({
|
|
4939
|
-
message: "Interests / tech stack (comma-separated):",
|
|
4940
|
-
default: existing.interests?.join(", ") || void 0
|
|
4941
|
-
});
|
|
4942
|
-
const locale = await input({
|
|
4943
|
-
message: 'Preferred language (e.g. "zh-CN", "en", "ja"):',
|
|
4944
|
-
default: existing.locale || void 0
|
|
4945
|
-
});
|
|
4946
|
-
const profile = {};
|
|
4947
|
-
if (name) profile.name = name;
|
|
4948
|
-
if (nickname) profile.nickname = nickname;
|
|
4949
|
-
if (role) profile.role = role;
|
|
4950
|
-
if (bio) profile.bio = bio;
|
|
4951
|
-
if (interestsStr) profile.interests = interestsStr.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4952
|
-
if (locale) profile.locale = locale;
|
|
4953
|
-
if (existing.extra) profile.extra = existing.extra;
|
|
4954
|
-
this.config.set("userProfile", profile);
|
|
4955
|
-
this.config.save();
|
|
4956
|
-
const displayName = nickname || name || "User";
|
|
4957
|
-
console.log(theme.success(`
|
|
4958
|
-
Profile saved! AI will know you as "${displayName}".
|
|
4959
|
-
`));
|
|
4960
|
-
}
|
|
4961
|
-
};
|
|
4962
|
-
|
|
4963
4519
|
// src/repl/custom-commands.ts
|
|
4964
4520
|
import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync, mkdirSync as mkdirSync3 } from "fs";
|
|
4965
4521
|
import { join as join3, extname } from "path";
|
|
@@ -5225,12 +4781,12 @@ var IMAGE_MIME = {
|
|
|
5225
4781
|
};
|
|
5226
4782
|
var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
5227
4783
|
var MAX_PATH_SPACE_TOKENS = 8;
|
|
5228
|
-
function expandUnquotedPath(
|
|
4784
|
+
function expandUnquotedPath(input, pathStart, rawPath, cwd) {
|
|
5229
4785
|
const plain = { raw: rawPath, consumed: rawPath.length };
|
|
5230
4786
|
if (existsSync4(resolve2(cwd, rawPath))) return plain;
|
|
5231
4787
|
let acc = rawPath;
|
|
5232
4788
|
let consumed = rawPath.length;
|
|
5233
|
-
let rest =
|
|
4789
|
+
let rest = input.slice(pathStart + rawPath.length);
|
|
5234
4790
|
for (let i = 0; i < MAX_PATH_SPACE_TOKENS; i++) {
|
|
5235
4791
|
const next = /^([ \t]+)(\S+)/.exec(rest);
|
|
5236
4792
|
if (!next) break;
|
|
@@ -5241,18 +4797,18 @@ function expandUnquotedPath(input2, pathStart, rawPath, cwd) {
|
|
|
5241
4797
|
}
|
|
5242
4798
|
return plain;
|
|
5243
4799
|
}
|
|
5244
|
-
function parseAtReferences(
|
|
4800
|
+
function parseAtReferences(input, cwd) {
|
|
5245
4801
|
const atPattern = /@(?:"([^"]+)"|'([^']+)'|(\S+))/g;
|
|
5246
4802
|
const refs = [];
|
|
5247
4803
|
const imageParts = [];
|
|
5248
|
-
let textBody =
|
|
4804
|
+
let textBody = input;
|
|
5249
4805
|
let match;
|
|
5250
|
-
while ((match = atPattern.exec(
|
|
4806
|
+
while ((match = atPattern.exec(input)) !== null) {
|
|
5251
4807
|
let rawPath = match[1] ?? match[2] ?? match[3] ?? "";
|
|
5252
4808
|
let matchedText = match[0];
|
|
5253
4809
|
if (match[3] !== void 0) {
|
|
5254
4810
|
const pathStart = match.index + 1;
|
|
5255
|
-
const expanded = expandUnquotedPath(
|
|
4811
|
+
const expanded = expandUnquotedPath(input, pathStart, rawPath, cwd);
|
|
5256
4812
|
if (expanded.consumed > rawPath.length) {
|
|
5257
4813
|
rawPath = expanded.raw;
|
|
5258
4814
|
matchedText = "@" + expanded.raw;
|
|
@@ -5321,7 +4877,7 @@ function removePreviousGrapheme(line, cursor) {
|
|
|
5321
4877
|
cursor: start
|
|
5322
4878
|
};
|
|
5323
4879
|
}
|
|
5324
|
-
function installUnicodeBackspaceRepair(
|
|
4880
|
+
function installUnicodeBackspaceRepair(input, rl, shouldHandle = () => true) {
|
|
5325
4881
|
const editable = rl;
|
|
5326
4882
|
let previous = { line: editable.line, cursor: editable.cursor };
|
|
5327
4883
|
const onKeypress = (_character, key) => {
|
|
@@ -5336,20 +4892,8 @@ function installUnicodeBackspaceRepair(input2, rl, shouldHandle = () => true) {
|
|
|
5336
4892
|
}
|
|
5337
4893
|
previous = current;
|
|
5338
4894
|
};
|
|
5339
|
-
|
|
5340
|
-
return () =>
|
|
5341
|
-
}
|
|
5342
|
-
|
|
5343
|
-
// src/repl/chat-params.ts
|
|
5344
|
-
function chatParamsFrom(params) {
|
|
5345
|
-
return {
|
|
5346
|
-
temperature: params.temperature,
|
|
5347
|
-
maxTokens: params.maxTokens,
|
|
5348
|
-
timeout: params.timeout,
|
|
5349
|
-
thinking: params.thinking,
|
|
5350
|
-
thinkingEffort: params.thinkingEffort,
|
|
5351
|
-
thinkingBudget: params.thinkingBudget
|
|
5352
|
-
};
|
|
4895
|
+
input.on("keypress", onKeypress);
|
|
4896
|
+
return () => input.off("keypress", onKeypress);
|
|
5353
4897
|
}
|
|
5354
4898
|
|
|
5355
4899
|
// src/core/model-router.ts
|
|
@@ -5721,6 +5265,13 @@ var Repl = class {
|
|
|
5721
5265
|
/** 本次会话累计 token 用量 */
|
|
5722
5266
|
sessionTokenUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
5723
5267
|
unknownPricingWarnings = /* @__PURE__ */ new Set();
|
|
5268
|
+
/**
|
|
5269
|
+
* 本会话按**调用时刻**费率累计的成本(美元)。峰谷计价下,事后拿聚合用量现算
|
|
5270
|
+
* 会给出错的数字——闲时跑的会话在峰时查看会被按峰价显示(审计 P3-01)。
|
|
5271
|
+
*/
|
|
5272
|
+
sessionAccruedCostUsd = 0;
|
|
5273
|
+
/** 本会话是否出现过定价未知的调用(此时累计值不完整,展示层需据实说明) */
|
|
5274
|
+
sessionCostIncomplete = false;
|
|
5724
5275
|
/** Fold a single-request TokenUsage (with optional cache fields) into sessionTokenUsage + cost tracker.
|
|
5725
5276
|
* modelOverride lets the smart router attribute cost to the actually-used model
|
|
5726
5277
|
* when it differs from the UI-selected currentModel. */
|
|
@@ -5738,7 +5289,9 @@ var Repl = class {
|
|
|
5738
5289
|
this.renderer.printInfo(`Cost notice: pricing is unknown for ${key}. Tokens are tracked, but cost is excluded from totals. Run aicli usage to review unknown-priced models.`);
|
|
5739
5290
|
}
|
|
5740
5291
|
}
|
|
5741
|
-
this.costTracker.addCost(this.currentProvider, effectiveModel, u);
|
|
5292
|
+
const priced = this.costTracker.addCost(this.currentProvider, effectiveModel, u);
|
|
5293
|
+
if (priced === null) this.sessionCostIncomplete = true;
|
|
5294
|
+
else this.sessionAccruedCostUsd += priced;
|
|
5742
5295
|
}
|
|
5743
5296
|
/** 启动时检测到的 Git 分支(无 git 仓库时为 null) */
|
|
5744
5297
|
gitBranch = null;
|
|
@@ -6160,7 +5713,8 @@ ${ctxLine}` : "")
|
|
|
6160
5713
|
const skillTag = activeSkill ? theme.toolCall(`[${activeSkill.meta.name}]`) : "";
|
|
6161
5714
|
const planTag = this.planMode ? theme.warning("[PLAN]") : "";
|
|
6162
5715
|
const modelParams = this.getModelParams();
|
|
6163
|
-
const
|
|
5716
|
+
const showsEffort = this.providers.get(this.currentProvider)?.supportsReasoningEffort ?? false;
|
|
5717
|
+
const thinkTag = modelParams.thinking ? theme.accent(showsEffort ? `[THINK:${modelParams.thinkingEffort ?? "high"}]` : "[THINK]") : "";
|
|
6164
5718
|
const promptStr = theme.success(`[${this.currentProvider}]`) + skillTag + planTag + thinkTag + chalk5.white(" > ");
|
|
6165
5719
|
this.rl.setPrompt(promptStr);
|
|
6166
5720
|
}
|
|
@@ -6488,8 +6042,8 @@ Session '${this.resumeSessionId}' not found.
|
|
|
6488
6042
|
let processing = false;
|
|
6489
6043
|
let pasteTimer = null;
|
|
6490
6044
|
const PASTE_DEBOUNCE_MS = 50;
|
|
6491
|
-
const processInput = async (
|
|
6492
|
-
if (!
|
|
6045
|
+
const processInput = async (input) => {
|
|
6046
|
+
if (!input) {
|
|
6493
6047
|
this.showPrompt();
|
|
6494
6048
|
return;
|
|
6495
6049
|
}
|
|
@@ -6499,10 +6053,10 @@ Session '${this.resumeSessionId}' not found.
|
|
|
6499
6053
|
const savedOutput = rlAny.output;
|
|
6500
6054
|
rlAny.output = null;
|
|
6501
6055
|
try {
|
|
6502
|
-
if (
|
|
6503
|
-
await this.handleCommand(
|
|
6056
|
+
if (input.startsWith("/")) {
|
|
6057
|
+
await this.handleCommand(input);
|
|
6504
6058
|
} else {
|
|
6505
|
-
await this.handleChat(
|
|
6059
|
+
await this.handleChat(input);
|
|
6506
6060
|
}
|
|
6507
6061
|
} catch (err) {
|
|
6508
6062
|
this.renderer.renderError(err);
|
|
@@ -7169,7 +6723,13 @@ Session '${this.resumeSessionId}' not found.
|
|
|
7169
6723
|
spinner.stop();
|
|
7170
6724
|
this.renderer.renderResponse(response.content);
|
|
7171
6725
|
lastResponseStore.content = response.content;
|
|
7172
|
-
session.addMessage({
|
|
6726
|
+
session.addMessage({
|
|
6727
|
+
role: "assistant",
|
|
6728
|
+
content: response.content,
|
|
6729
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
6730
|
+
// 非流式路径同样要落 reasoningContent,否则 V4 thinking 的多轮推理断链(审计 P1-02)
|
|
6731
|
+
...response.reasoningContent ? { reasoningContent: response.reasoningContent } : {}
|
|
6732
|
+
});
|
|
7173
6733
|
this.events.emit("message.after", { content: response.content });
|
|
7174
6734
|
if (response.usage) {
|
|
7175
6735
|
this.addSessionUsage(response.usage, effectiveModel);
|
|
@@ -7852,8 +7412,8 @@ Tip: You can continue the conversation by asking the AI to proceed.`
|
|
|
7852
7412
|
await this.checkContextPressure();
|
|
7853
7413
|
}
|
|
7854
7414
|
}
|
|
7855
|
-
async handleCommand(
|
|
7856
|
-
const parts =
|
|
7415
|
+
async handleCommand(input) {
|
|
7416
|
+
const parts = input.slice(1).split(" ");
|
|
7857
7417
|
const cmdName = parts[0].toLowerCase();
|
|
7858
7418
|
const args = parts.slice(1);
|
|
7859
7419
|
const cmd = this.commands.get(cmdName);
|
|
@@ -7949,7 +7509,10 @@ Tip: You can continue the conversation by asking the AI to proceed.`
|
|
|
7949
7509
|
cacheCreationTokens: 0,
|
|
7950
7510
|
cacheReadTokens: 0
|
|
7951
7511
|
};
|
|
7512
|
+
this.sessionAccruedCostUsd = 0;
|
|
7513
|
+
this.sessionCostIncomplete = false;
|
|
7952
7514
|
},
|
|
7515
|
+
getSessionAccruedCost: () => ({ usd: this.sessionAccruedCostUsd, incomplete: this.sessionCostIncomplete }),
|
|
7953
7516
|
getGitBranch: () => this.gitBranch,
|
|
7954
7517
|
getLastResponse: () => lastResponseStore.content,
|
|
7955
7518
|
runSetupWizard: async () => {
|
|
@@ -7957,6 +7520,7 @@ Tip: You can continue the conversation by asking the AI to proceed.`
|
|
|
7957
7520
|
rlAny.output = process.stdout;
|
|
7958
7521
|
process.stdin.resume();
|
|
7959
7522
|
try {
|
|
7523
|
+
const { SetupWizard } = await import("./setup-wizard-S55ICNHH.js");
|
|
7960
7524
|
const wizard = new SetupWizard(this.config);
|
|
7961
7525
|
await wizard.runFull();
|
|
7962
7526
|
} finally {
|
|
@@ -7977,6 +7541,9 @@ Tip: You can continue the conversation by asking the AI to proceed.`
|
|
|
7977
7541
|
this.runtimeThinking = value;
|
|
7978
7542
|
this.refreshPrompt();
|
|
7979
7543
|
},
|
|
7544
|
+
getProviderSupportsReasoningEffort: () => this.providers.get(this.currentProvider)?.supportsReasoningEffort ?? false,
|
|
7545
|
+
getConfiguredThinking: () => this.config.get("modelParams")[this.currentModel]?.thinking,
|
|
7546
|
+
getConfiguredThinkingEffort: () => this.config.get("modelParams")[this.currentModel]?.thinkingEffort,
|
|
7980
7547
|
getThinkingEffort: () => this.runtimeThinkingEffort,
|
|
7981
7548
|
setThinkingEffort: (value) => {
|
|
7982
7549
|
this.runtimeThinkingEffort = value;
|
|
@@ -8115,7 +7682,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
8115
7682
|
});
|
|
8116
7683
|
var builtInProviderIds = listBuiltInProviderMetadata().map(({ id }) => id).join("/");
|
|
8117
7684
|
program.name("aicli").description("Cross-platform REPL-style AI CLI with multi-provider support").version(VERSION);
|
|
8118
|
-
program.option("--provider <name>", `AI provider to use (${builtInProviderIds}, or any custom provider)`).option("-m, --model <name>", "Model to use").option("-p, --prompt <text>", "Headless mode: send a single prompt and exit (reads stdin as context if piped)").option("--system <prompt>", "System prompt override (headless mode)").option("--json", "Output result as JSON object (headless mode only)").option("--output-format <format>", "Output format: text (default) | streaming-json (NDJSON per-chunk, headless only)").option("--no-stream", "Disable streaming output").option("--allowed-tools <tools>", "Comma-separated whitelist of tools (e.g. bash,read_file)").option("--blocked-tools <tools>", "Comma-separated blacklist of tools (e.g. bash,write_file)").option("--resume <id>", "Resume a previous session by ID (prefix match supported)").option("--max-tool-rounds <n>", "Max agentic tool-call rounds per conversation (default: 200)").action(async (options) => {
|
|
7685
|
+
program.option("--provider <name>", `AI provider to use (${builtInProviderIds}, or any custom provider)`).option("-m, --model <name>", "Model to use").option("-p, --prompt <text>", "Headless mode: send a single prompt and exit (reads stdin as context if piped)").option("--system <prompt>", "System prompt override (headless mode)").option("--json", "Output result as JSON object (headless mode only)").option("--output-format <format>", "Output format: text (default) | streaming-json (NDJSON per-chunk, headless only)").option("--no-stream", "Disable streaming output").option("--allowed-tools <tools>", "Comma-separated whitelist of tools (e.g. bash,read_file)").option("--blocked-tools <tools>", "Comma-separated blacklist of tools (e.g. bash,write_file)").option("--resume <id>", "Resume a previous session by ID (prefix match supported)").option("--max-tool-rounds <n>", "Max agentic tool-call rounds per conversation (default: 200)").option("--think <mode>", "Thinking for this run: off | on | low | high | max (default: follow config)").action(async (options) => {
|
|
8119
7686
|
if (options.prompt !== void 0) {
|
|
8120
7687
|
await runHeadless(options);
|
|
8121
7688
|
} else {
|
|
@@ -8124,6 +7691,7 @@ program.option("--provider <name>", `AI provider to use (${builtInProviderIds},
|
|
|
8124
7691
|
});
|
|
8125
7692
|
program.command("config").description("Configure API keys and preferences").action(async () => {
|
|
8126
7693
|
const config = new ConfigManager();
|
|
7694
|
+
const { SetupWizard } = await import("./setup-wizard-S55ICNHH.js");
|
|
8127
7695
|
const wizard = new SetupWizard(config);
|
|
8128
7696
|
await wizard.runFull();
|
|
8129
7697
|
console.log("Configuration saved.");
|
|
@@ -8162,7 +7730,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
8162
7730
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
8163
7731
|
process.exit(1);
|
|
8164
7732
|
}
|
|
8165
|
-
const { startWebServer } = await import("./server-
|
|
7733
|
+
const { startWebServer } = await import("./server-OZ4RFDFH.js");
|
|
8166
7734
|
await startWebServer({ port, host: options.host });
|
|
8167
7735
|
});
|
|
8168
7736
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -8329,11 +7897,11 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
8329
7897
|
console.log(footer + "\n");
|
|
8330
7898
|
});
|
|
8331
7899
|
program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
|
|
8332
|
-
const { runUsageCli } = await import("./usage-
|
|
7900
|
+
const { runUsageCli } = await import("./usage-SDL5Z4CS.js");
|
|
8333
7901
|
await runUsageCli(options);
|
|
8334
7902
|
});
|
|
8335
7903
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
8336
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7904
|
+
const { runDoctorCli } = await import("./doctor-cli-GMCOGCDR.js");
|
|
8337
7905
|
const argv = process.argv.slice(2);
|
|
8338
7906
|
await runDoctorCli({
|
|
8339
7907
|
json: !!options.json || argv.includes("--json"),
|
|
@@ -8342,7 +7910,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
|
|
|
8342
7910
|
});
|
|
8343
7911
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
8344
7912
|
try {
|
|
8345
|
-
const batch = await import("./batch-
|
|
7913
|
+
const batch = await import("./batch-C7SHXRQ2.js");
|
|
8346
7914
|
switch (action) {
|
|
8347
7915
|
case "submit":
|
|
8348
7916
|
if (!arg) {
|
|
@@ -8385,7 +7953,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
8385
7953
|
}
|
|
8386
7954
|
});
|
|
8387
7955
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
8388
|
-
const { startMcpServer } = await import("./server-
|
|
7956
|
+
const { startMcpServer } = await import("./server-ZCG5QD6P.js");
|
|
8389
7957
|
await startMcpServer({
|
|
8390
7958
|
allowDestructive: !!options.allowDestructive,
|
|
8391
7959
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -8398,7 +7966,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
8398
7966
|
console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
|
|
8399
7967
|
process.exit(1);
|
|
8400
7968
|
}
|
|
8401
|
-
const { runPrCli } = await import("./pr-
|
|
7969
|
+
const { runPrCli } = await import("./pr-Y2LDG3R7.js");
|
|
8402
7970
|
const result = await runPrCli({
|
|
8403
7971
|
action,
|
|
8404
7972
|
target,
|
|
@@ -8418,8 +7986,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
8418
7986
|
process.exit(result.exitCode);
|
|
8419
7987
|
});
|
|
8420
7988
|
program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).option("--base <ref>", "Base ref for git diff <ref>...HEAD (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
|
|
8421
|
-
const { runCi } = await import("./ci-
|
|
8422
|
-
const { formatCiResult } = await import("./ci-format-
|
|
7989
|
+
const { runCi } = await import("./ci-TDXLI3OM.js");
|
|
7990
|
+
const { formatCiResult } = await import("./ci-format-AFX2LP4Y.js");
|
|
8423
7991
|
const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
|
|
8424
7992
|
if (formats > 1) {
|
|
8425
7993
|
console.error("Choose only one output format: --json, --markdown, or --sarif.");
|
|
@@ -8577,7 +8145,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
8577
8145
|
config.get("customProviders"),
|
|
8578
8146
|
config.getConfigDir()
|
|
8579
8147
|
);
|
|
8580
|
-
const { startHub } = await import("./hub-
|
|
8148
|
+
const { startHub } = await import("./hub-2YXETHPY.js");
|
|
8581
8149
|
await startHub(
|
|
8582
8150
|
{
|
|
8583
8151
|
topic: topic ?? "",
|
|
@@ -8679,6 +8247,10 @@ ${options.prompt}` : options.prompt;
|
|
|
8679
8247
|
const maxTokens = modelParams.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
8680
8248
|
const timeout = modelParams.timeout ?? 6e4;
|
|
8681
8249
|
const temperature = modelParams.temperature;
|
|
8250
|
+
const thinkingParams = applyThinkingFlag(
|
|
8251
|
+
thinkingParamsFor(allModelParams, model),
|
|
8252
|
+
options.think
|
|
8253
|
+
);
|
|
8682
8254
|
let systemPrompt = options.system;
|
|
8683
8255
|
if (!systemPrompt) {
|
|
8684
8256
|
const contextConfig = config.get("context");
|
|
@@ -8711,7 +8283,8 @@ ${loaded.mergedContent}` : void 0
|
|
|
8711
8283
|
stream: true,
|
|
8712
8284
|
temperature,
|
|
8713
8285
|
maxTokens,
|
|
8714
|
-
timeout
|
|
8286
|
+
timeout,
|
|
8287
|
+
...thinkingParams
|
|
8715
8288
|
});
|
|
8716
8289
|
let fullContent = "";
|
|
8717
8290
|
let finalUsage;
|
|
@@ -8741,7 +8314,8 @@ ${loaded.mergedContent}` : void 0
|
|
|
8741
8314
|
stream: false,
|
|
8742
8315
|
temperature,
|
|
8743
8316
|
maxTokens,
|
|
8744
|
-
timeout
|
|
8317
|
+
timeout,
|
|
8318
|
+
...thinkingParams
|
|
8745
8319
|
});
|
|
8746
8320
|
const out = {
|
|
8747
8321
|
content: response.content,
|
|
@@ -8758,7 +8332,8 @@ ${loaded.mergedContent}` : void 0
|
|
|
8758
8332
|
stream: true,
|
|
8759
8333
|
temperature,
|
|
8760
8334
|
maxTokens,
|
|
8761
|
-
timeout
|
|
8335
|
+
timeout,
|
|
8336
|
+
...thinkingParams
|
|
8762
8337
|
});
|
|
8763
8338
|
for await (const chunk of stream) {
|
|
8764
8339
|
if (chunk.done) break;
|
|
@@ -8773,7 +8348,8 @@ ${loaded.mergedContent}` : void 0
|
|
|
8773
8348
|
stream: false,
|
|
8774
8349
|
temperature,
|
|
8775
8350
|
maxTokens,
|
|
8776
|
-
timeout
|
|
8351
|
+
timeout,
|
|
8352
|
+
...thinkingParams
|
|
8777
8353
|
});
|
|
8778
8354
|
process.stdout.write(response.content + "\n");
|
|
8779
8355
|
}
|
|
@@ -8789,6 +8365,7 @@ async function startRepl(options) {
|
|
|
8789
8365
|
const config = new ConfigManager();
|
|
8790
8366
|
await setupProxy(config.get("proxy"));
|
|
8791
8367
|
if (config.isFirstRun()) {
|
|
8368
|
+
const { SetupWizard } = await import("./setup-wizard-S55ICNHH.js");
|
|
8792
8369
|
const wizard = new SetupWizard(config);
|
|
8793
8370
|
const configured = await wizard.runFirstRun();
|
|
8794
8371
|
if (!configured) {
|