jinzd-ai-cli 0.1.74 → 0.1.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-WRFXLV34.js → chunk-6FYQR6TY.js} +4 -2
- package/dist/{chunk-37AZXVX2.js → chunk-RROTI54R.js} +14 -2
- package/dist/index.js +8 -13
- package/dist/{run-tests-IJDQJJ3N.js → run-tests-W44VYI2J.js} +1 -1
- package/dist/{server-4LKAYB5Y.js → server-HINOHGE2.js} +56 -29
- package/dist/web/client/app.js +14 -3
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { platform } from "os";
|
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/core/constants.ts
|
|
11
|
-
var VERSION = "0.1.
|
|
11
|
+
var VERSION = "0.1.76";
|
|
12
12
|
var APP_NAME = "ai-cli";
|
|
13
13
|
var CONFIG_DIR_NAME = ".aicli";
|
|
14
14
|
var CONFIG_FILE_NAME = "config.json";
|
|
@@ -75,9 +75,11 @@ var CONTEXT_PRESSURE_THRESHOLD = 0.8;
|
|
|
75
75
|
var TEST_TIMEOUT = 3e5;
|
|
76
76
|
var AGENTIC_BEHAVIOR_GUIDELINE = `# Important Behavioral Guidelines
|
|
77
77
|
|
|
78
|
-
**
|
|
78
|
+
**Respond appropriately to the user's intent \u2014 do NOT over-react**:
|
|
79
|
+
- For **greetings and casual chat** (e.g., "hello", "hi", "hey", "\u4F60\u597D", "what's up"): respond naturally with a friendly greeting. Do NOT use any tools. Do NOT explore directories, read files, or start any project work. Just chat.
|
|
79
80
|
- When the user asks you to "read", "understand", "review", "analyze", "examine", or "look at" files or a project, your task is only to **read and summarize**, then wait for the user's next instruction. Do not automatically start executing tasks described in the project.
|
|
80
81
|
- Only begin using write/execute tools when the user **explicitly requests** an action (e.g., "generate", "create", "modify", "run", "start", etc.).
|
|
82
|
+
- Project context files (CLAUDE.md, AICLI.md) provide background information about the project. They are NOT instructions to start working. Only use them as reference when the user asks a project-related question or task.
|
|
81
83
|
- If you are unsure about the user's intent, use the ask_user tool to confirm with the user, rather than assuming and executing on your own.`;
|
|
82
84
|
var AUTHOR = "Jin Zhengdong";
|
|
83
85
|
var AUTHOR_EMAIL = "zhengdong.jin@gmail.com";
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
17
17
|
VERSION,
|
|
18
18
|
runTestsTool
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-6FYQR6TY.js";
|
|
20
20
|
|
|
21
21
|
// src/config/config-manager.ts
|
|
22
22
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -5405,6 +5405,17 @@ var SkillManager = class {
|
|
|
5405
5405
|
}
|
|
5406
5406
|
};
|
|
5407
5407
|
|
|
5408
|
+
// src/core/proxy.ts
|
|
5409
|
+
async function setupProxy(configProxy) {
|
|
5410
|
+
const proxyUrl = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY ?? process.env.https_proxy ?? process.env.http_proxy ?? configProxy;
|
|
5411
|
+
if (!proxyUrl) return;
|
|
5412
|
+
try {
|
|
5413
|
+
const { ProxyAgent, setGlobalDispatcher } = await import("undici");
|
|
5414
|
+
setGlobalDispatcher(new ProxyAgent({ uri: proxyUrl }));
|
|
5415
|
+
} catch {
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
|
|
5408
5419
|
// src/repl/dev-state.ts
|
|
5409
5420
|
import { existsSync as existsSync14, readFileSync as readFileSync8, writeFileSync as writeFileSync7, unlinkSync as unlinkSync2, mkdirSync as mkdirSync8 } from "fs";
|
|
5410
5421
|
import { join as join10 } from "path";
|
|
@@ -5722,5 +5733,6 @@ export {
|
|
|
5722
5733
|
loadDevState,
|
|
5723
5734
|
clearDevState,
|
|
5724
5735
|
McpManager,
|
|
5725
|
-
SkillManager
|
|
5736
|
+
SkillManager,
|
|
5737
|
+
setupProxy
|
|
5726
5738
|
};
|
package/dist/index.js
CHANGED
|
@@ -30,11 +30,12 @@ import {
|
|
|
30
30
|
runHook,
|
|
31
31
|
saveDevState,
|
|
32
32
|
sessionHasMeaningfulContent,
|
|
33
|
+
setupProxy,
|
|
33
34
|
spawnAgentContext,
|
|
34
35
|
theme,
|
|
35
36
|
truncateOutput,
|
|
36
37
|
undoStack
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-RROTI54R.js";
|
|
38
39
|
import {
|
|
39
40
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
40
41
|
AUTHOR,
|
|
@@ -54,7 +55,7 @@ import {
|
|
|
54
55
|
REPO_URL,
|
|
55
56
|
SKILLS_DIR_NAME,
|
|
56
57
|
VERSION
|
|
57
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-6FYQR6TY.js";
|
|
58
59
|
|
|
59
60
|
// src/index.ts
|
|
60
61
|
import { program } from "commander";
|
|
@@ -1903,7 +1904,7 @@ ${hint}` : "")
|
|
|
1903
1904
|
description: "Run project tests and show structured report",
|
|
1904
1905
|
usage: "/test [command|filter]",
|
|
1905
1906
|
async execute(args, _ctx) {
|
|
1906
|
-
const { executeTests } = await import("./run-tests-
|
|
1907
|
+
const { executeTests } = await import("./run-tests-W44VYI2J.js");
|
|
1907
1908
|
const argStr = args.join(" ").trim();
|
|
1908
1909
|
let testArgs = {};
|
|
1909
1910
|
if (argStr) {
|
|
@@ -5290,7 +5291,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5290
5291
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5291
5292
|
process.exit(1);
|
|
5292
5293
|
}
|
|
5293
|
-
const { startWebServer } = await import("./server-
|
|
5294
|
+
const { startWebServer } = await import("./server-HINOHGE2.js");
|
|
5294
5295
|
await startWebServer({ port, host: options.host });
|
|
5295
5296
|
});
|
|
5296
5297
|
program.command("sessions").description("List recent conversation sessions").action(async () => {
|
|
@@ -5314,15 +5315,6 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
5314
5315
|
console.log();
|
|
5315
5316
|
});
|
|
5316
5317
|
program.parse();
|
|
5317
|
-
async function setupProxy(configProxy) {
|
|
5318
|
-
const proxyUrl = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY ?? process.env.https_proxy ?? process.env.http_proxy ?? configProxy;
|
|
5319
|
-
if (!proxyUrl) return;
|
|
5320
|
-
try {
|
|
5321
|
-
const { ProxyAgent, setGlobalDispatcher } = await import("undici");
|
|
5322
|
-
setGlobalDispatcher(new ProxyAgent({ uri: proxyUrl }));
|
|
5323
|
-
} catch {
|
|
5324
|
-
}
|
|
5325
|
-
}
|
|
5326
5318
|
async function readStdin() {
|
|
5327
5319
|
if (process.stdin.isTTY) return "";
|
|
5328
5320
|
return new Promise((resolve3, reject) => {
|
|
@@ -5525,3 +5517,6 @@ Provider '${options.provider}' is not configured. Run: ai-cli config
|
|
|
5525
5517
|
});
|
|
5526
5518
|
await repl.start();
|
|
5527
5519
|
}
|
|
5520
|
+
export {
|
|
5521
|
+
setupProxy
|
|
5522
|
+
};
|
|
@@ -19,11 +19,13 @@ import {
|
|
|
19
19
|
loadDevState,
|
|
20
20
|
renderDiff,
|
|
21
21
|
runHook,
|
|
22
|
+
setupProxy,
|
|
22
23
|
spawnAgentContext,
|
|
23
24
|
truncateOutput
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-RROTI54R.js";
|
|
25
26
|
import {
|
|
26
27
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
28
|
+
CONTEXT_FILE_CANDIDATES,
|
|
27
29
|
DEFAULT_MAX_TOKENS,
|
|
28
30
|
MCP_PROJECT_CONFIG_NAME,
|
|
29
31
|
MEMORY_FILE_NAME,
|
|
@@ -32,13 +34,13 @@ import {
|
|
|
32
34
|
PLAN_MODE_SYSTEM_ADDON,
|
|
33
35
|
SKILLS_DIR_NAME,
|
|
34
36
|
VERSION
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-6FYQR6TY.js";
|
|
36
38
|
|
|
37
39
|
// src/web/server.ts
|
|
38
40
|
import express from "express";
|
|
39
41
|
import { createServer } from "http";
|
|
40
42
|
import { WebSocketServer } from "ws";
|
|
41
|
-
import { join as join3, dirname, resolve } from "path";
|
|
43
|
+
import { join as join3, dirname, resolve as resolve2 } from "path";
|
|
42
44
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
43
45
|
|
|
44
46
|
// src/web/tool-executor-web.ts
|
|
@@ -71,31 +73,31 @@ var ToolExecutorWeb = class {
|
|
|
71
73
|
}
|
|
72
74
|
/** Resolve a pending confirm from client response */
|
|
73
75
|
resolveConfirm(requestId, approved) {
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
+
const resolve3 = this.pendingConfirms.get(requestId);
|
|
77
|
+
if (resolve3) {
|
|
76
78
|
this.pendingConfirms.delete(requestId);
|
|
77
79
|
this.confirming = false;
|
|
78
|
-
|
|
80
|
+
resolve3(approved);
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
/** Resolve a pending batch confirm from client response */
|
|
82
84
|
resolveBatchConfirm(requestId, decision) {
|
|
83
|
-
const
|
|
84
|
-
if (
|
|
85
|
+
const resolve3 = this.pendingBatchConfirms.get(requestId);
|
|
86
|
+
if (resolve3) {
|
|
85
87
|
this.pendingBatchConfirms.delete(requestId);
|
|
86
88
|
this.confirming = false;
|
|
87
89
|
if (decision === "all" || decision === "none") {
|
|
88
|
-
|
|
90
|
+
resolve3(decision);
|
|
89
91
|
} else {
|
|
90
|
-
|
|
92
|
+
resolve3(new Set(decision));
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
/** Cancel all pending confirms (e.g., on disconnect) */
|
|
95
97
|
cancelAll() {
|
|
96
|
-
for (const
|
|
98
|
+
for (const resolve3 of this.pendingConfirms.values()) resolve3(false);
|
|
97
99
|
this.pendingConfirms.clear();
|
|
98
|
-
for (const
|
|
100
|
+
for (const resolve3 of this.pendingBatchConfirms.values()) resolve3("none");
|
|
99
101
|
this.pendingBatchConfirms.clear();
|
|
100
102
|
this.confirming = false;
|
|
101
103
|
}
|
|
@@ -164,8 +166,8 @@ var ToolExecutorWeb = class {
|
|
|
164
166
|
diff: this.getDiffPreview(call)
|
|
165
167
|
};
|
|
166
168
|
this.send(msg);
|
|
167
|
-
return new Promise((
|
|
168
|
-
this.pendingConfirms.set(requestId,
|
|
169
|
+
return new Promise((resolve3) => {
|
|
170
|
+
this.pendingConfirms.set(requestId, resolve3);
|
|
169
171
|
});
|
|
170
172
|
}
|
|
171
173
|
/** WebSocket-based batch confirm */
|
|
@@ -184,8 +186,8 @@ var ToolExecutorWeb = class {
|
|
|
184
186
|
files
|
|
185
187
|
};
|
|
186
188
|
this.send(msg);
|
|
187
|
-
return new Promise((
|
|
188
|
-
this.pendingBatchConfirms.set(requestId,
|
|
189
|
+
return new Promise((resolve3) => {
|
|
190
|
+
this.pendingBatchConfirms.set(requestId, resolve3);
|
|
189
191
|
});
|
|
190
192
|
}
|
|
191
193
|
async execute(call) {
|
|
@@ -387,7 +389,7 @@ function loadMemoryContent(configDir) {
|
|
|
387
389
|
|
|
388
390
|
// src/web/session-handler.ts
|
|
389
391
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
390
|
-
import { join as join2 } from "path";
|
|
392
|
+
import { join as join2, resolve } from "path";
|
|
391
393
|
var MAX_TOOL_ROUNDS = 25;
|
|
392
394
|
var FREE_ROUND_TOOLS = /* @__PURE__ */ new Set(["write_todos"]);
|
|
393
395
|
var MAX_CONSECUTIVE_FREE_ROUNDS = 5;
|
|
@@ -488,10 +490,10 @@ var SessionHandler = class {
|
|
|
488
490
|
return;
|
|
489
491
|
}
|
|
490
492
|
case "ask_user_response": {
|
|
491
|
-
const
|
|
492
|
-
if (
|
|
493
|
+
const resolve3 = this.pendingAskUser.get(msg.requestId);
|
|
494
|
+
if (resolve3) {
|
|
493
495
|
this.pendingAskUser.delete(msg.requestId);
|
|
494
|
-
|
|
496
|
+
resolve3(msg.answer);
|
|
495
497
|
}
|
|
496
498
|
return;
|
|
497
499
|
}
|
|
@@ -508,7 +510,7 @@ var SessionHandler = class {
|
|
|
508
510
|
onDisconnect() {
|
|
509
511
|
this.toolExecutor.cancelAll();
|
|
510
512
|
if (this.abortController) this.abortController.abort();
|
|
511
|
-
for (const
|
|
513
|
+
for (const resolve3 of this.pendingAskUser.values()) resolve3(null);
|
|
512
514
|
this.pendingAskUser.clear();
|
|
513
515
|
this.sessions.save();
|
|
514
516
|
}
|
|
@@ -962,19 +964,43 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
962
964
|
}
|
|
963
965
|
return defs;
|
|
964
966
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
967
|
+
/**
|
|
968
|
+
* Find first matching context file in a directory.
|
|
969
|
+
*/
|
|
970
|
+
findContextFile(dir) {
|
|
971
|
+
for (const name of CONTEXT_FILE_CANDIDATES) {
|
|
972
|
+
const fullPath = join2(dir, name);
|
|
970
973
|
try {
|
|
971
974
|
if (existsSync3(fullPath)) {
|
|
972
|
-
|
|
975
|
+
const content = readFileSync3(fullPath, "utf-8").trim();
|
|
976
|
+
if (content) return content;
|
|
973
977
|
}
|
|
974
978
|
} catch {
|
|
975
979
|
}
|
|
976
980
|
}
|
|
977
|
-
return
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Load hierarchical context files (same as CLI):
|
|
985
|
+
* 1. Global: ~/.aicli/AICLI.md or CLAUDE.md
|
|
986
|
+
* 2. Project: <git-root>/AICLI.md or CLAUDE.md
|
|
987
|
+
* 3. Subdir: <cwd>/AICLI.md or CLAUDE.md (only if cwd ≠ project root)
|
|
988
|
+
*/
|
|
989
|
+
loadContextFiles() {
|
|
990
|
+
const parts = [];
|
|
991
|
+
const cwd = process.cwd();
|
|
992
|
+
const configDir = this.config.getConfigDir();
|
|
993
|
+
const globalCtx = this.findContextFile(configDir);
|
|
994
|
+
if (globalCtx) parts.push(globalCtx);
|
|
995
|
+
const gitRoot = getGitRoot(cwd);
|
|
996
|
+
const projectRoot = gitRoot ?? cwd;
|
|
997
|
+
const projectCtx = this.findContextFile(projectRoot);
|
|
998
|
+
if (projectCtx) parts.push(projectCtx);
|
|
999
|
+
if (resolve(cwd) !== resolve(projectRoot)) {
|
|
1000
|
+
const localCtx = this.findContextFile(cwd);
|
|
1001
|
+
if (localCtx) parts.push(localCtx);
|
|
1002
|
+
}
|
|
1003
|
+
return parts.length > 0 ? parts.join("\n\n---\n\n") : void 0;
|
|
978
1004
|
}
|
|
979
1005
|
};
|
|
980
1006
|
|
|
@@ -988,7 +1014,7 @@ function getModuleDir() {
|
|
|
988
1014
|
}
|
|
989
1015
|
} catch {
|
|
990
1016
|
}
|
|
991
|
-
return
|
|
1017
|
+
return resolve2(".");
|
|
992
1018
|
}
|
|
993
1019
|
async function startWebServer(options = {}) {
|
|
994
1020
|
const port = options.port ?? 3e3;
|
|
@@ -996,6 +1022,7 @@ async function startWebServer(options = {}) {
|
|
|
996
1022
|
console.log(`\u{1F916} ai-cli Web UI v${VERSION}`);
|
|
997
1023
|
console.log(` Initializing...`);
|
|
998
1024
|
const config = new ConfigManager();
|
|
1025
|
+
await setupProxy(config.get("proxy"));
|
|
999
1026
|
const providers = new ProviderRegistry();
|
|
1000
1027
|
const sessions = new SessionManager(config);
|
|
1001
1028
|
const toolRegistry = new ToolRegistry();
|
package/dist/web/client/app.js
CHANGED
|
@@ -424,10 +424,21 @@ function scrollToBottom() {
|
|
|
424
424
|
|
|
425
425
|
function setProcessing(value) {
|
|
426
426
|
processing = value;
|
|
427
|
-
|
|
427
|
+
// During processing: show BOTH send (as interjection) and stop buttons
|
|
428
|
+
// Send button changes style to indicate interjection mode
|
|
428
429
|
btnStop.classList.toggle('hidden', !value);
|
|
429
|
-
|
|
430
|
-
|
|
430
|
+
if (value) {
|
|
431
|
+
btnSend.classList.remove('btn-primary');
|
|
432
|
+
btnSend.classList.add('btn-warning');
|
|
433
|
+
btnSend.title = 'Send interjection (correct/redirect AI)';
|
|
434
|
+
userInput.placeholder = 'Type to interject/correct the AI... (Enter to send)';
|
|
435
|
+
} else {
|
|
436
|
+
btnSend.classList.add('btn-primary');
|
|
437
|
+
btnSend.classList.remove('btn-warning');
|
|
438
|
+
btnSend.title = 'Send';
|
|
439
|
+
userInput.placeholder = 'Type a message... (Shift+Enter for newline)';
|
|
440
|
+
userInput.focus();
|
|
441
|
+
}
|
|
431
442
|
}
|
|
432
443
|
|
|
433
444
|
function updateProviderSelect(currentId) {
|