jinzd-ai-cli 0.4.10 → 0.4.12

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.
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.10";
9
+ var VERSION = "0.4.12";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -6,7 +6,7 @@ import {
6
6
  SUBAGENT_DEFAULT_MAX_ROUNDS,
7
7
  SUBAGENT_MAX_ROUNDS_LIMIT,
8
8
  runTestsTool
9
- } from "./chunk-4EUTAZ6Q.js";
9
+ } from "./chunk-Z5IRVRGL.js";
10
10
 
11
11
  // src/tools/builtin/bash.ts
12
12
  import { execSync } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  EnvLoader,
4
4
  schemaToJsonSchema
5
- } from "./chunk-IIVTIEWB.js";
5
+ } from "./chunk-A3S7PUMM.js";
6
6
  import {
7
7
  APP_NAME,
8
8
  CONFIG_DIR_NAME,
@@ -15,7 +15,7 @@ import {
15
15
  MCP_TOOL_PREFIX,
16
16
  PLUGINS_DIR_NAME,
17
17
  VERSION
18
- } from "./chunk-4EUTAZ6Q.js";
18
+ } from "./chunk-Z5IRVRGL.js";
19
19
 
20
20
  // src/config/config-manager.ts
21
21
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -1331,6 +1331,9 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1331
1331
  }
1332
1332
  yield { type: "done" };
1333
1333
  } catch (err) {
1334
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1335
+ throw err;
1336
+ }
1334
1337
  throw this.wrapError(err);
1335
1338
  }
1336
1339
  }
@@ -2073,7 +2076,7 @@ var ProviderRegistry = class {
2073
2076
  };
2074
2077
 
2075
2078
  // src/session/session-manager.ts
2076
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, unlinkSync } from "fs";
2079
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, unlinkSync, renameSync } from "fs";
2077
2080
  import { join as join2 } from "path";
2078
2081
  import { v4 as uuidv4 } from "uuid";
2079
2082
 
@@ -2298,7 +2301,9 @@ var SessionManager = class {
2298
2301
  if (!this._current) return;
2299
2302
  mkdirSync2(this.historyDir, { recursive: true });
2300
2303
  const filePath = join2(this.historyDir, `${this._current.id}.json`);
2301
- writeFileSync2(filePath, JSON.stringify(this._current.toJSON(), null, 2), "utf-8");
2304
+ const tmpPath = filePath + ".tmp";
2305
+ writeFileSync2(tmpPath, JSON.stringify(this._current.toJSON(), null, 2), "utf-8");
2306
+ renameSync(tmpPath, filePath);
2302
2307
  }
2303
2308
  loadSession(id) {
2304
2309
  const filePath = join2(this.historyDir, `${id}.json`);
@@ -2712,6 +2717,12 @@ var McpClient = class {
2712
2717
  */
2713
2718
  handleStdoutData(chunk) {
2714
2719
  this.stdoutBuffer += chunk;
2720
+ if (this.stdoutBuffer.length > 1048576) {
2721
+ process.stderr.write(`[mcp] stdout buffer exceeded 1MB \u2014 clearing
2722
+ `);
2723
+ this.stdoutBuffer = "";
2724
+ return;
2725
+ }
2715
2726
  const lines = this.stdoutBuffer.split("\n");
2716
2727
  this.stdoutBuffer = lines.pop() ?? "";
2717
2728
  for (const line of lines) {
@@ -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.4.10";
11
+ var VERSION = "0.4.12";
12
12
  var APP_NAME = "ai-cli";
13
13
  var CONFIG_DIR_NAME = ".aicli";
14
14
  var CONFIG_FILE_NAME = "config.json";
@@ -381,7 +381,7 @@ ${content}`);
381
381
  }
382
382
  }
383
383
  async function runTaskMode(config, providers, configManager, topic) {
384
- const { TaskOrchestrator } = await import("./task-orchestrator-W56DGIZ4.js");
384
+ const { TaskOrchestrator } = await import("./task-orchestrator-A5X2GUSH.js");
385
385
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
386
386
  let interrupted = false;
387
387
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  saveDevState,
24
24
  sessionHasMeaningfulContent,
25
25
  setupProxy
26
- } from "./chunk-J3J44O4N.js";
26
+ } from "./chunk-JPCRXQ2E.js";
27
27
  import {
28
28
  ToolRegistry,
29
29
  askUserContext,
@@ -38,7 +38,7 @@ import {
38
38
  theme,
39
39
  truncateOutput,
40
40
  undoStack
41
- } from "./chunk-IIVTIEWB.js";
41
+ } from "./chunk-A3S7PUMM.js";
42
42
  import {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  AUTHOR,
@@ -58,7 +58,7 @@ import {
58
58
  REPO_URL,
59
59
  SKILLS_DIR_NAME,
60
60
  VERSION
61
- } from "./chunk-4EUTAZ6Q.js";
61
+ } from "./chunk-Z5IRVRGL.js";
62
62
 
63
63
  // src/index.ts
64
64
  import { program } from "commander";
@@ -1914,7 +1914,7 @@ ${hint}` : "")
1914
1914
  description: "Run project tests and show structured report",
1915
1915
  usage: "/test [command|filter]",
1916
1916
  async execute(args, _ctx) {
1917
- const { executeTests } = await import("./run-tests-YBNVSXTV.js");
1917
+ const { executeTests } = await import("./run-tests-EUOAU3RZ.js");
1918
1918
  const argStr = args.join(" ").trim();
1919
1919
  let testArgs = {};
1920
1920
  if (argStr) {
@@ -4254,6 +4254,10 @@ Session '${this.resumeSessionId}' not found.
4254
4254
  }, PASTE_DEBOUNCE_MS);
4255
4255
  });
4256
4256
  this.rl.on("close", () => {
4257
+ if (pasteTimer) {
4258
+ clearTimeout(pasteTimer);
4259
+ pasteTimer = null;
4260
+ }
4257
4261
  if (!processing) {
4258
4262
  resolve3();
4259
4263
  }
@@ -5524,7 +5528,7 @@ program.command("web").description("Start Web UI server with browser-based chat
5524
5528
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
5525
5529
  process.exit(1);
5526
5530
  }
5527
- const { startWebServer } = await import("./server-YLN3YUUI.js");
5531
+ const { startWebServer } = await import("./server-PWWT4P52.js");
5528
5532
  await startWebServer({ port, host: options.host });
5529
5533
  });
5530
5534
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
@@ -5757,7 +5761,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
5757
5761
  }),
5758
5762
  config.get("customProviders")
5759
5763
  );
5760
- const { startHub } = await import("./hub-B3YT75IB.js");
5764
+ const { startHub } = await import("./hub-J5ZOVM4Q.js");
5761
5765
  await startHub(
5762
5766
  {
5763
5767
  topic: topic ?? "",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-WC6IEG2I.js";
4
+ } from "./chunk-3HJSWTKO.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-4EUTAZ6Q.js";
5
+ } from "./chunk-Z5IRVRGL.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -18,7 +18,7 @@ import {
18
18
  renderDiff,
19
19
  runHook,
20
20
  setupProxy
21
- } from "./chunk-J3J44O4N.js";
21
+ } from "./chunk-JPCRXQ2E.js";
22
22
  import {
23
23
  AuthManager
24
24
  } from "./chunk-BYNY5JPB.js";
@@ -32,7 +32,7 @@ import {
32
32
  spawnAgentContext,
33
33
  truncateOutput,
34
34
  undoStack
35
- } from "./chunk-IIVTIEWB.js";
35
+ } from "./chunk-A3S7PUMM.js";
36
36
  import {
37
37
  AGENTIC_BEHAVIOR_GUIDELINE,
38
38
  CONTEXT_FILE_CANDIDATES,
@@ -44,7 +44,7 @@ import {
44
44
  PLAN_MODE_SYSTEM_ADDON,
45
45
  SKILLS_DIR_NAME,
46
46
  VERSION
47
- } from "./chunk-4EUTAZ6Q.js";
47
+ } from "./chunk-Z5IRVRGL.js";
48
48
 
49
49
  // src/web/server.ts
50
50
  import express from "express";
@@ -585,10 +585,20 @@ var SessionHandler = class _SessionHandler {
585
585
  try {
586
586
  this.ensureSession();
587
587
  const session = this.sessions.current;
588
+ const ALLOWED_IMAGE_MIMES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"]);
589
+ const MAX_IMAGE_SIZE = 10 * 1024 * 1024;
588
590
  let msgContent;
589
591
  if (images && images.length > 0) {
590
592
  const parts = [];
591
593
  for (const img of images) {
594
+ if (!ALLOWED_IMAGE_MIMES.has(img.mime)) {
595
+ this.send({ type: "error", message: `Rejected image: unsupported MIME type "${img.mime}"` });
596
+ return;
597
+ }
598
+ if (img.data && img.data.length > MAX_IMAGE_SIZE) {
599
+ this.send({ type: "error", message: `Rejected image: too large (${(img.data.length / 1024 / 1024).toFixed(1)} MB, max 10 MB)` });
600
+ return;
601
+ }
592
602
  parts.push({
593
603
  type: "image_url",
594
604
  image_url: { url: `data:${img.mime};base64,${img.data}` }
@@ -1438,7 +1448,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
1438
1448
  case "test": {
1439
1449
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
1440
1450
  try {
1441
- const { executeTests } = await import("./run-tests-YBNVSXTV.js");
1451
+ const { executeTests } = await import("./run-tests-EUOAU3RZ.js");
1442
1452
  const argStr = args.join(" ").trim();
1443
1453
  let testArgs = {};
1444
1454
  if (argStr) {
@@ -2212,6 +2222,10 @@ async function startWebServer(options = {}) {
2212
2222
  if (cached) return cached;
2213
2223
  const userDataDir = authManager.getUserDataDir(username);
2214
2224
  const userConfig = new ConfigManager(userDataDir);
2225
+ if (userConfig.isFirstRun()) {
2226
+ userConfig.setTransient("defaultProvider", config.get("defaultProvider"));
2227
+ userConfig.setTransient("defaultModels", config.get("defaultModels"));
2228
+ }
2215
2229
  const userSessions = new SessionManager(userConfig);
2216
2230
  const userShared = {
2217
2231
  config: userConfig,
@@ -4,10 +4,10 @@ import {
4
4
  getDangerLevel,
5
5
  googleSearchContext,
6
6
  truncateOutput
7
- } from "./chunk-IIVTIEWB.js";
7
+ } from "./chunk-A3S7PUMM.js";
8
8
  import {
9
9
  SUBAGENT_ALLOWED_TOOLS
10
- } from "./chunk-4EUTAZ6Q.js";
10
+ } from "./chunk-Z5IRVRGL.js";
11
11
 
12
12
  // src/hub/task-orchestrator.ts
13
13
  import { createInterface } from "readline";
@@ -16,6 +16,23 @@ import { join } from "path";
16
16
  import chalk from "chalk";
17
17
 
18
18
  // src/hub/task-executor.ts
19
+ var TASK_EXCLUDED_TOOLS = /* @__PURE__ */ new Set(["write_todos", "save_memory", "ask_user", "spawn_agent"]);
20
+ var _cachedRegistry = null;
21
+ var _cachedToolDefs = null;
22
+ function getTaskToolRegistry() {
23
+ if (_cachedRegistry && _cachedToolDefs) {
24
+ return { registry: _cachedRegistry, toolDefs: _cachedToolDefs };
25
+ }
26
+ const registry = new ToolRegistry();
27
+ for (const tool of registry.listAll()) {
28
+ if (!SUBAGENT_ALLOWED_TOOLS.has(tool.definition.name) || TASK_EXCLUDED_TOOLS.has(tool.definition.name)) {
29
+ registry.unregister(tool.definition.name);
30
+ }
31
+ }
32
+ _cachedRegistry = registry;
33
+ _cachedToolDefs = registry.getDefinitions();
34
+ return { registry, toolDefs: _cachedToolDefs };
35
+ }
19
36
  async function executeTask(options) {
20
37
  const {
21
38
  task,
@@ -29,14 +46,7 @@ async function executeTask(options) {
29
46
  onToolResult,
30
47
  onRound
31
48
  } = options;
32
- const TASK_EXCLUDED_TOOLS = /* @__PURE__ */ new Set(["write_todos", "save_memory", "ask_user", "spawn_agent"]);
33
- const registry = new ToolRegistry();
34
- for (const tool of registry.listAll()) {
35
- if (!SUBAGENT_ALLOWED_TOOLS.has(tool.definition.name) || TASK_EXCLUDED_TOOLS.has(tool.definition.name)) {
36
- registry.unregister(tool.definition.name);
37
- }
38
- }
39
- const toolDefs = registry.getDefinitions();
49
+ const { registry, toolDefs } = getTaskToolRegistry();
40
50
  const contextSection = context ? `
41
51
 
42
52
  ## Reference Documents
@@ -280,9 +290,14 @@ var TaskOrchestrator = class {
280
290
  async askResume() {
281
291
  const rl = createInterface({ input: process.stdin, output: process.stdout });
282
292
  try {
283
- const answer = await new Promise((resolve) => {
284
- rl.question(chalk.green(" Resume from saved state? (y/n) > "), resolve);
285
- });
293
+ const answer = await Promise.race([
294
+ new Promise((resolve) => {
295
+ rl.question(chalk.green(" Resume from saved state? (y/n) > "), resolve);
296
+ }),
297
+ new Promise(
298
+ (_, reject) => setTimeout(() => reject(new Error("timeout")), 3e4)
299
+ )
300
+ ]).catch(() => "y");
286
301
  return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
287
302
  } finally {
288
303
  rl.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",