jinzd-ai-cli 0.4.261 → 0.4.262

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.
Files changed (38) hide show
  1. package/README.md +10 -8
  2. package/README.zh-CN.md +11 -9
  3. package/dist/{batch-YUPAC4CK.js → batch-2B7UUX27.js} +2 -2
  4. package/dist/{chunk-OIOTHBDB.js → chunk-25HFWCM3.js} +18 -6
  5. package/dist/{chunk-Z5TCAE4L.js → chunk-2XPJRRBB.js} +4 -4
  6. package/dist/{chunk-YXMBP567.js → chunk-A6JLBNAI.js} +2 -2
  7. package/dist/{chunk-KFNQESEG.js → chunk-BS44XEZ4.js} +1 -1
  8. package/dist/{chunk-HU3IYBU5.js → chunk-D6DHS5GL.js} +4 -4
  9. package/dist/{chunk-NOB2OPQI.js → chunk-FWBSGBB7.js} +4 -4
  10. package/dist/{chunk-KQQHMGK7.js → chunk-HPDI4F5F.js} +1 -1
  11. package/dist/{chunk-W5XUZYQE.js → chunk-JEJHNVA2.js} +1 -1
  12. package/dist/{chunk-T7R7ILYT.js → chunk-JFXKQPKY.js} +1 -1
  13. package/dist/{chunk-HGTDI5ME.js → chunk-KMS3LBO3.js} +1 -1
  14. package/dist/{chunk-323S2X5I.js → chunk-KWYJFLXY.js} +1 -1
  15. package/dist/{chunk-H6FND2UG.js → chunk-MTIS7H6V.js} +1 -1
  16. package/dist/{chunk-GC4KA5LF.js → chunk-WAAFA32V.js} +1 -1
  17. package/dist/{chunk-R6DXWVVN.js → chunk-ZQZEBPAQ.js} +1 -1
  18. package/dist/{ci-FX26BNT2.js → ci-G6OZDH4H.js} +5 -5
  19. package/dist/{ci-format-GEWIAIZD.js → ci-format-BRS7G5X5.js} +2 -2
  20. package/dist/{constants-YN4B6C7B.js → constants-24AD5JQV.js} +1 -1
  21. package/dist/{doctor-cli-PXGXZYQB.js → doctor-cli-WWZRFGQJ.js} +5 -5
  22. package/dist/electron-server.js +24 -13
  23. package/dist/{hub-RCANK6SK.js → hub-2DYZQVEN.js} +1 -1
  24. package/dist/index.js +24 -22
  25. package/dist/{persistent-memory-P3COUZZM.js → persistent-memory-DFSZZSYP.js} +2 -2
  26. package/dist/{persistent-memory-UARSSYAA.js → persistent-memory-LJT37XVO.js} +2 -2
  27. package/dist/{pr-7LQTAUFK.js → pr-OOIQPCBX.js} +5 -5
  28. package/dist/{run-tests-YNHESHYY.js → run-tests-ICTVJSJN.js} +2 -2
  29. package/dist/{run-tests-7RYU4BK5.js → run-tests-W4TG4OQV.js} +2 -2
  30. package/dist/{server-YZ37TL46.js → server-GTVYIHBG.js} +5 -5
  31. package/dist/{server-SSAWGNT7.js → server-IXUVVPTV.js} +13 -13
  32. package/dist/{task-orchestrator-ZFL4E6NZ.js → task-orchestrator-6MHSDOFR.js} +5 -5
  33. package/dist/{usage-PDKM7J75.js → usage-23I3ZJZO.js} +2 -2
  34. package/dist/web/client/actions.js +12 -7
  35. package/dist/web/client/app.js +4 -36
  36. package/dist/web/client/sidebar-tabs.js +48 -0
  37. package/dist/web/client/sw.js +1 -1
  38. package/package.json +1 -1
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  <!-- AICLI:DOCS_DEFAULT_WEB_PORT=3000 -->
6
6
  <!-- AICLI:DOCS_BUILTIN_TOOL_COUNT=30 -->
7
7
  <!-- AICLI:DOCS_REPL_COMMAND_COUNT=48 -->
8
+ <!-- AICLI:DOCS_BUILTIN_PROVIDER_COUNT=10 -->
8
9
  <!-- AICLI:DOCS_MEMORY_SOURCE=memory.jsonl -->
9
10
 
10
11
  > A cross-platform AI coding assistant — CLI, Web UI, and Desktop App — with multi-provider support and agentic tool calling
@@ -12,7 +13,6 @@
12
13
  [![npm version](https://img.shields.io/npm/v/jinzd-ai-cli)](https://www.npmjs.com/package/jinzd-ai-cli)
13
14
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
15
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20.18.1-brightgreen)](https://nodejs.org)
15
- [![Tests](https://img.shields.io/badge/tests-1639%20passing-brightgreen)]()
16
16
  [![GitHub Release](https://img.shields.io/github/v/release/jinzhengdong/ai-cli)](https://github.com/jinzhengdong/ai-cli/releases)
17
17
  [![CI](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml)
18
18
 
@@ -131,13 +131,14 @@ aicli user delete x # Delete user
131
131
  |----------|--------|-------------|
132
132
  | **Claude** | Opus 4, Sonnet 4, Haiku 4 | [console.anthropic.com](https://console.anthropic.com) |
133
133
  | **Gemini** | 2.5 Pro, 2.5 Flash | [aistudio.google.com](https://aistudio.google.com) |
134
- | **DeepSeek** | DeepSeek-Chat (V3), Reasoner (R1) | [platform.deepseek.com](https://platform.deepseek.com) |
134
+ | **DeepSeek** | deepseek-v4-flash (default), deepseek-v4-pro | [platform.deepseek.com](https://platform.deepseek.com) |
135
135
  | **OpenAI** | GPT-5.4, GPT-5, GPT-4.1, o3, o4-mini | [platform.openai.com](https://platform.openai.com) |
136
136
  | **OpenRouter** | 300+ models (Claude, GPT, Gemini, Llama, Qwen, Mistral...) | [openrouter.ai](https://openrouter.ai) |
137
137
  | **Zhipu** | GLM-4, GLM-5 | [open.bigmodel.cn](https://open.bigmodel.cn) |
138
138
  | **Kimi** | Kimi K2.6, K2.5, K2 Thinking | [platform.moonshot.cn](https://platform.moonshot.cn) |
139
- | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
140
- | **Ollama** | Any locally installed model (Llama, Qwen, Gemma, Mistral...) | No API key — [ollama.com](https://ollama.com) |
139
+ | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
140
+ | **MiniMax** | MiniMax-M3 (default), M2.7, M2.5, M2.1, M2 | [platform.minimaxi.com](https://platform.minimaxi.com) |
141
+ | **Ollama** | Any locally installed model (Llama, Qwen, Gemma, Mistral...) | No API key — [ollama.com](https://ollama.com) |
141
142
 
142
143
  Any OpenAI-compatible API can also be used via `customBaseUrls` in config.
143
144
 
@@ -462,8 +463,9 @@ Environment variables take precedence over config file values:
462
463
  | `AICLI_API_KEY_OPENROUTER` | OpenRouter API Key |
463
464
  | `AICLI_API_KEY_ZHIPU` | Zhipu API Key |
464
465
  | `AICLI_API_KEY_KIMI` | Kimi API Key |
465
- | `AICLI_API_KEY_QWEN` | Qwen / Alibaba Cloud API Key |
466
- | `AICLI_PROVIDER` | Default provider ID |
466
+ | `AICLI_API_KEY_QWEN` | Qwen / Alibaba Cloud API Key |
467
+ | `AICLI_API_KEY_MINIMAX` | MiniMax API Key |
468
+ | `AICLI_PROVIDER` | Default provider ID |
467
469
  | `AICLI_NO_STREAM` | Set to `1` to disable streaming |
468
470
  | `HTTPS_PROXY` / `HTTP_PROXY` | Proxy URL |
469
471
 
@@ -517,13 +519,13 @@ The Web UI (`aicli web`) provides a full-featured browser interface:
517
519
  ## Testing
518
520
 
519
521
  ```bash
520
- npm test # Offline regression suite: 91 files, 1639 passed, 2 skipped
522
+ npm test # Offline regression suite
521
523
  npm run test:providers # Real-provider smoke tests (network/API-key dependent)
522
524
  npm run test:e2e-web # Playwright browser smoke; may need browser-process permission in sandboxes
523
525
  npm run test:watch # Watch mode
524
526
  ```
525
527
 
526
- 79 offline test files covering: authentication, sessions, tool types & danger levels, permissions, output truncation, diff rendering, edit-file similarity, error hierarchy, config management, env loading, provider registry, web-fetch, grep-files, hub renderer, hub discussion, hub presets, dev-state, token estimator, tool registry budget, parallel tool execution, cost tracker, session tool history.
528
+ Offline tests cover authentication, sessions, tool types and danger levels, permissions, output truncation, diff rendering, edit-file similarity, error hierarchy, config management, env loading, provider registry, web-fetch, grep-files, Hub, dev-state, token estimation, tool registry budgets, parallel tool execution, cost tracking, and session tool history.
527
529
 
528
530
  ## Releasing (Version Bump → npm Publish → GitHub Push)
529
531
 
package/README.zh-CN.md CHANGED
@@ -5,6 +5,7 @@
5
5
  <!-- AICLI:DOCS_DEFAULT_WEB_PORT=3000 -->
6
6
  <!-- AICLI:DOCS_BUILTIN_TOOL_COUNT=30 -->
7
7
  <!-- AICLI:DOCS_REPL_COMMAND_COUNT=48 -->
8
+ <!-- AICLI:DOCS_BUILTIN_PROVIDER_COUNT=10 -->
8
9
  <!-- AICLI:DOCS_MEMORY_SOURCE=memory.jsonl -->
9
10
 
10
11
  > 跨平台 AI 编程助手 — CLI 终端、Web 界面、桌面应用三合一,支持 10 大 Provider(含本地 Ollama)与 Agentic 工具调用
@@ -12,7 +13,6 @@
12
13
  [![npm version](https://img.shields.io/npm/v/jinzd-ai-cli)](https://www.npmjs.com/package/jinzd-ai-cli)
13
14
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
15
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20.18.1-brightgreen)](https://nodejs.org)
15
- [![Tests](https://img.shields.io/badge/tests-1097%20passing-brightgreen)]()
16
16
  [![GitHub Release](https://img.shields.io/github/v/release/jinzhengdong/ai-cli)](https://github.com/jinzhengdong/ai-cli/releases)
17
17
  [![CI](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml)
18
18
 
@@ -119,13 +119,14 @@ aicli user delete x # 删除用户
119
119
  |----------|------|-------------|
120
120
  | **Claude** | Opus 4, Sonnet 4, Haiku 4 | [console.anthropic.com](https://console.anthropic.com) |
121
121
  | **Gemini** | 2.5 Pro, 2.5 Flash | [aistudio.google.com](https://aistudio.google.com) |
122
- | **DeepSeek** | DeepSeek-Chat (V3), Reasoner (R1) | [platform.deepseek.com](https://platform.deepseek.com) |
122
+ | **DeepSeek** | deepseek-v4-flash(默认), deepseek-v4-pro | [platform.deepseek.com](https://platform.deepseek.com) |
123
123
  | **OpenAI** | GPT-5.4, GPT-5, GPT-4.1, o3, o4-mini | [platform.openai.com](https://platform.openai.com) |
124
124
  | **OpenRouter** | 300+ 模型(Claude/GPT/Gemini/Llama/Qwen/Mistral...) | [openrouter.ai](https://openrouter.ai) |
125
- | **智谱清言** | GLM-4, GLM-5 | [open.bigmodel.cn](https://open.bigmodel.cn) |
125
+ | **Zhipu(智谱)** | GLM-4, GLM-5 | [open.bigmodel.cn](https://open.bigmodel.cn) |
126
126
  | **Kimi** | Kimi K2.6, K2.5, K2 Thinking | [platform.moonshot.cn](https://platform.moonshot.cn) |
127
- | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
128
- | **Ollama** | 任意本地模型(LlamaQwenGemmaMistral...) | 无需 API Key — [ollama.com](https://ollama.com) |
127
+ | **Qwen** | qwen-plus, qwen-max, qwen-turbo, qwen-coder-plus | [bailian.console.aliyun.com](https://bailian.console.aliyun.com) |
128
+ | **MiniMax** | MiniMax-M3(默认)、M2.7M2.5M2.1M2 | [platform.minimaxi.com](https://platform.minimaxi.com) |
129
+ | **Ollama** | 任意本地模型(Llama、Qwen、Gemma、Mistral...) | 无需 API Key — [ollama.com](https://ollama.com) |
129
130
 
130
131
  也可通过 `customBaseUrls` 配置接入任意 OpenAI 兼容 API。
131
132
 
@@ -420,8 +421,9 @@ Auto Mode 不会被项目配置静默开启。用 `/permissions recently-denied`
420
421
  | `AICLI_API_KEY_OPENROUTER` | OpenRouter API Key |
421
422
  | `AICLI_API_KEY_ZHIPU` | 智谱 API Key |
422
423
  | `AICLI_API_KEY_KIMI` | Kimi API Key |
423
- | `AICLI_API_KEY_QWEN` | Qwen / Alibaba Cloud API Key |
424
- | `AICLI_PROVIDER` | 默认 Provider |
424
+ | `AICLI_API_KEY_QWEN` | Qwen / Alibaba Cloud API Key |
425
+ | `AICLI_API_KEY_MINIMAX` | MiniMax API Key |
426
+ | `AICLI_PROVIDER` | 默认 Provider |
425
427
  | `AICLI_NO_STREAM` | 设为 `1` 禁用流式输出 |
426
428
  | `HTTPS_PROXY` / `HTTP_PROXY` | 代理地址 |
427
429
 
@@ -475,11 +477,11 @@ Web UI(`aicli web`)提供功能完备的浏览器界面:
475
477
  ## 测试
476
478
 
477
479
  ```bash
478
- npm test # 运行全部 515 个测试(30 suites)
480
+ npm test # 运行离线回归测试
479
481
  npm run test:watch # 监听模式
480
482
  ```
481
483
 
482
- 26 个测试套件覆盖:认证、会话、工具类型与危险级别、权限、输出截断、diff 渲染、edit-file 相似度、错误层级、配置管理、环境变量、Provider 注册、web-fetch、grep-files、Hub 渲染、Hub 讨论、Hub 预设、开发状态、Token 估算、工具注册表预算、并行工具执行、费用追踪、会话工具历史。
484
+ 离线测试覆盖:认证、会话、工具类型与危险级别、权限、输出截断、diff 渲染、edit-file 相似度、错误层级、配置管理、环境变量、Provider 注册、web-fetch、grep-files、Hub、开发状态、Token 估算、工具注册表预算、并行工具执行、费用追踪和会话工具历史。
483
485
 
484
486
  ## 发布(版本提升 → npm 发布 → 推送 GitHub)
485
487
 
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-H6FND2UG.js";
4
+ } from "./chunk-MTIS7H6V.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
- import "./chunk-323S2X5I.js";
6
+ import "./chunk-KWYJFLXY.js";
7
7
  import {
8
8
  atomicWriteFileSync
9
9
  } from "./chunk-IW3Q7AE5.js";
@@ -2116,6 +2116,18 @@ var BUILT_IN_PROVIDERS = [
2116
2116
  OpenRouterProvider,
2117
2117
  OllamaProvider
2118
2118
  ];
2119
+ function listBuiltInProviderMetadata() {
2120
+ return BUILT_IN_PROVIDERS.map((ProviderClass) => {
2121
+ const { info } = new ProviderClass();
2122
+ return {
2123
+ id: info.id,
2124
+ displayName: info.displayName,
2125
+ defaultModel: info.defaultModel,
2126
+ apiKeyEnvVar: info.apiKeyEnvVar,
2127
+ requiresApiKey: info.requiresApiKey
2128
+ };
2129
+ });
2130
+ }
2119
2131
  var ProviderRegistry = class {
2120
2132
  providers = /* @__PURE__ */ new Map();
2121
2133
  customConfigs = [];
@@ -2210,13 +2222,12 @@ var ProviderRegistry = class {
2210
2222
  return [...this.providers.values()];
2211
2223
  }
2212
2224
  listAll() {
2213
- const builtIn = BUILT_IN_PROVIDERS.map((P) => {
2214
- const p = new P();
2225
+ const builtIn = listBuiltInProviderMetadata().map((info) => {
2215
2226
  return {
2216
- id: p.info.id,
2217
- displayName: p.info.displayName,
2218
- configured: this.providers.has(p.info.id),
2219
- defaultModel: p.info.defaultModel,
2227
+ id: info.id,
2228
+ displayName: info.displayName,
2229
+ configured: this.providers.has(info.id),
2230
+ defaultModel: info.defaultModel,
2220
2231
  isCustom: false
2221
2232
  };
2222
2233
  });
@@ -2235,5 +2246,6 @@ var ProviderRegistry = class {
2235
2246
  };
2236
2247
 
2237
2248
  export {
2249
+ listBuiltInProviderMetadata,
2238
2250
  ProviderRegistry
2239
2251
  };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-GC4KA5LF.js";
5
+ } from "./chunk-WAAFA32V.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -10,13 +10,13 @@ import {
10
10
  } from "./chunk-HLWUDRBO.js";
11
11
  import {
12
12
  ProviderRegistry
13
- } from "./chunk-OIOTHBDB.js";
13
+ } from "./chunk-25HFWCM3.js";
14
14
  import {
15
15
  ConfigManager
16
- } from "./chunk-H6FND2UG.js";
16
+ } from "./chunk-MTIS7H6V.js";
17
17
  import {
18
18
  VERSION
19
- } from "./chunk-323S2X5I.js";
19
+ } from "./chunk-KWYJFLXY.js";
20
20
 
21
21
  // src/cli/ci.ts
22
22
  import { execFileSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-HU3IYBU5.js";
4
+ } from "./chunk-D6DHS5GL.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
@@ -11,7 +11,7 @@ import {
11
11
  MCP_PROTOCOL_VERSION,
12
12
  MCP_TOOL_PREFIX,
13
13
  VERSION
14
- } from "./chunk-323S2X5I.js";
14
+ } from "./chunk-KWYJFLXY.js";
15
15
  import {
16
16
  atomicWriteFileSync
17
17
  } from "./chunk-IW3Q7AE5.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-R6DXWVVN.js";
3
+ } from "./chunk-ZQZEBPAQ.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -7,7 +7,7 @@ import {
7
7
  searchPersistentMemories,
8
8
  touchMemoryReferences,
9
9
  updateMemoryEntry
10
- } from "./chunk-HGTDI5ME.js";
10
+ } from "./chunk-KMS3LBO3.js";
11
11
  import {
12
12
  indexProject
13
13
  } from "./chunk-GLSR2NR3.js";
@@ -23,7 +23,7 @@ import {
23
23
  runHook,
24
24
  runLifecycleHooks,
25
25
  runTool
26
- } from "./chunk-W5XUZYQE.js";
26
+ } from "./chunk-JEJHNVA2.js";
27
27
  import {
28
28
  buildTruncatedArgumentsError,
29
29
  getDangerLevel,
@@ -40,14 +40,14 @@ import {
40
40
  } from "./chunk-4BKXL7SM.js";
41
41
  import {
42
42
  runTestsTool
43
- } from "./chunk-KQQHMGK7.js";
43
+ } from "./chunk-HPDI4F5F.js";
44
44
  import {
45
45
  CONFIG_DIR_NAME,
46
46
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
47
47
  SUBAGENT_ALLOWED_TOOLS,
48
48
  SUBAGENT_DEFAULT_MAX_ROUNDS,
49
49
  SUBAGENT_MAX_ROUNDS_LIMIT
50
- } from "./chunk-323S2X5I.js";
50
+ } from "./chunk-KWYJFLXY.js";
51
51
  import {
52
52
  loadChatIndex,
53
53
  searchChatMemory
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProviderRegistry
4
- } from "./chunk-OIOTHBDB.js";
4
+ } from "./chunk-25HFWCM3.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-H6FND2UG.js";
7
+ } from "./chunk-MTIS7H6V.js";
8
8
  import {
9
9
  getActivePluginAssets,
10
10
  getPendingHookTrust,
@@ -14,7 +14,7 @@ import {
14
14
  listHooks,
15
15
  listInstalledPlugins,
16
16
  resetStats
17
- } from "./chunk-W5XUZYQE.js";
17
+ } from "./chunk-JEJHNVA2.js";
18
18
  import {
19
19
  getGitRoot
20
20
  } from "./chunk-HOSJZMQS.js";
@@ -26,7 +26,7 @@ import {
26
26
  MCP_PROJECT_CONFIG_NAME,
27
27
  MEMORY_FILE_NAME,
28
28
  VERSION
29
- } from "./chunk-323S2X5I.js";
29
+ } from "./chunk-KWYJFLXY.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-323S2X5I.js";
4
+ } from "./chunk-KWYJFLXY.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  PLUGINS_DIR_NAME
5
- } from "./chunk-323S2X5I.js";
5
+ } from "./chunk-KWYJFLXY.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
8
  } from "./chunk-IW3Q7AE5.js";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-R6DXWVVN.js";
9
+ } from "./chunk-ZQZEBPAQ.js";
10
10
  import {
11
11
  atomicWriteFileSync
12
12
  } from "./chunk-6BUTA5VW.js";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-323S2X5I.js";
9
+ } from "./chunk-KWYJFLXY.js";
10
10
  import {
11
11
  DEFAULT_PATTERNS,
12
12
  redactString
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.261";
4
+ var VERSION = "0.4.262";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-323S2X5I.js";
11
+ } from "./chunk-KWYJFLXY.js";
12
12
  import {
13
13
  atomicWriteFileSync
14
14
  } from "./chunk-IW3Q7AE5.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-323S2X5I.js";
4
+ } from "./chunk-KWYJFLXY.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.261";
2
+ var VERSION = "0.4.262";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -3,14 +3,14 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-Z5TCAE4L.js";
7
- import "./chunk-GC4KA5LF.js";
6
+ } from "./chunk-2XPJRRBB.js";
7
+ import "./chunk-WAAFA32V.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
- import "./chunk-OIOTHBDB.js";
10
- import "./chunk-H6FND2UG.js";
9
+ import "./chunk-25HFWCM3.js";
10
+ import "./chunk-MTIS7H6V.js";
11
11
  import "./chunk-XZNRZGG2.js";
12
12
  import "./chunk-TU3L3PW7.js";
13
- import "./chunk-323S2X5I.js";
13
+ import "./chunk-KWYJFLXY.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
  export {
16
16
  CI_COMMENT_MARKER,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-GC4KA5LF.js";
10
- import "./chunk-323S2X5I.js";
9
+ } from "./chunk-WAAFA32V.js";
10
+ import "./chunk-KWYJFLXY.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-323S2X5I.js";
41
+ } from "./chunk-KWYJFLXY.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-NOB2OPQI.js";
6
- import "./chunk-OIOTHBDB.js";
7
- import "./chunk-H6FND2UG.js";
8
- import "./chunk-W5XUZYQE.js";
5
+ } from "./chunk-FWBSGBB7.js";
6
+ import "./chunk-25HFWCM3.js";
7
+ import "./chunk-MTIS7H6V.js";
8
+ import "./chunk-JEJHNVA2.js";
9
9
  import "./chunk-XZNRZGG2.js";
10
10
  import "./chunk-TU3L3PW7.js";
11
11
  import "./chunk-HOSJZMQS.js";
12
- import "./chunk-323S2X5I.js";
12
+ import "./chunk-KWYJFLXY.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
14
  export {
15
15
  formatDoctorReport,
@@ -34,14 +34,14 @@ import {
34
34
  touchMemoryReferences,
35
35
  updateMemoryApproval,
36
36
  updateMemoryEntry
37
- } from "./chunk-T7R7ILYT.js";
37
+ } from "./chunk-JFXKQPKY.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-KFNQESEG.js";
44
+ } from "./chunk-BS44XEZ4.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-R6DXWVVN.js";
76
+ } from "./chunk-ZQZEBPAQ.js";
77
77
  import {
78
78
  hasSemanticIndex,
79
79
  semanticSearch
@@ -3991,6 +3991,18 @@ var BUILT_IN_PROVIDERS = [
3991
3991
  OpenRouterProvider,
3992
3992
  OllamaProvider
3993
3993
  ];
3994
+ function listBuiltInProviderMetadata() {
3995
+ return BUILT_IN_PROVIDERS.map((ProviderClass) => {
3996
+ const { info } = new ProviderClass();
3997
+ return {
3998
+ id: info.id,
3999
+ displayName: info.displayName,
4000
+ defaultModel: info.defaultModel,
4001
+ apiKeyEnvVar: info.apiKeyEnvVar,
4002
+ requiresApiKey: info.requiresApiKey
4003
+ };
4004
+ });
4005
+ }
3994
4006
  var ProviderRegistry = class {
3995
4007
  providers = /* @__PURE__ */ new Map();
3996
4008
  customConfigs = [];
@@ -4085,13 +4097,12 @@ var ProviderRegistry = class {
4085
4097
  return [...this.providers.values()];
4086
4098
  }
4087
4099
  listAll() {
4088
- const builtIn = BUILT_IN_PROVIDERS.map((P) => {
4089
- const p = new P();
4100
+ const builtIn = listBuiltInProviderMetadata().map((info) => {
4090
4101
  return {
4091
- id: p.info.id,
4092
- displayName: p.info.displayName,
4093
- configured: this.providers.has(p.info.id),
4094
- defaultModel: p.info.defaultModel,
4102
+ id: info.id,
4103
+ displayName: info.displayName,
4104
+ configured: this.providers.has(info.id),
4105
+ defaultModel: info.defaultModel,
4095
4106
  isCustom: false
4096
4107
  };
4097
4108
  });
@@ -15369,7 +15380,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15369
15380
  Cost: ${formatCost(cost)}` : "";
15370
15381
  let memoryLine = "";
15371
15382
  try {
15372
- const { countPendingMemories } = await import("./persistent-memory-P3COUZZM.js");
15383
+ const { countPendingMemories } = await import("./persistent-memory-DFSZZSYP.js");
15373
15384
  const pending = countPendingMemories(ctx.config.getConfigDir());
15374
15385
  if (pending > 0) memoryLine = `
15375
15386
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -16178,14 +16189,14 @@ async function handleSecurityReview(args, ctx) {
16178
16189
  async function handleTest(args, ctx) {
16179
16190
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
16180
16191
  try {
16181
- const { executeTests } = await import("./run-tests-7RYU4BK5.js");
16182
16192
  const argStr = args.join(" ").trim();
16183
16193
  let testArgs = {};
16184
16194
  if (argStr) {
16185
16195
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
16186
16196
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
16187
16197
  }
16188
- const report = await executeTests(testArgs);
16198
+ const runTests = ctx.runTests ?? (await import("./run-tests-W4TG4OQV.js")).executeTests;
16199
+ const report = await runTests(testArgs);
16189
16200
  ctx.send({ type: "info", message: report });
16190
16201
  } catch (err) {
16191
16202
  ctx.send({ type: "error", message: `Test failed: ${err.message}` });
@@ -16442,7 +16453,7 @@ async function handleMemory(args, ctx) {
16442
16453
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16443
16454
  } else if (sub === "export") {
16444
16455
  if (args[1] === "md") {
16445
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-P3COUZZM.js");
16456
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-DFSZZSYP.js");
16446
16457
  ctx.send({
16447
16458
  type: "export_data",
16448
16459
  format: "md",
@@ -154,7 +154,7 @@ ${content}`);
154
154
  }
155
155
  }
156
156
  async function runTaskMode(config, providers, configManager, topic) {
157
- const { TaskOrchestrator } = await import("./task-orchestrator-ZFL4E6NZ.js");
157
+ const { TaskOrchestrator } = await import("./task-orchestrator-6MHSDOFR.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  scanProject,
18
18
  sessionHasMeaningfulContent,
19
19
  setupProxy
20
- } from "./chunk-YXMBP567.js";
20
+ } from "./chunk-A6JLBNAI.js";
21
21
  import {
22
22
  computeCost,
23
23
  formatCost,
@@ -50,7 +50,7 @@ import {
50
50
  spawnAgentContext,
51
51
  theme,
52
52
  undoStack
53
- } from "./chunk-HU3IYBU5.js";
53
+ } from "./chunk-D6DHS5GL.js";
54
54
  import {
55
55
  addMemoryEntry,
56
56
  backupMemoryStore,
@@ -76,7 +76,7 @@ import {
76
76
  touchMemoryReferences,
77
77
  updateMemoryApproval,
78
78
  updateMemoryEntry
79
- } from "./chunk-HGTDI5ME.js";
79
+ } from "./chunk-KMS3LBO3.js";
80
80
  import "./chunk-GLSR2NR3.js";
81
81
  import "./chunk-UUSRWSSX.js";
82
82
  import "./chunk-CKH4KQ4E.js";
@@ -90,13 +90,14 @@ import {
90
90
  formatDoctorReport,
91
91
  loadContextFiles,
92
92
  writeCrashLog
93
- } from "./chunk-NOB2OPQI.js";
93
+ } from "./chunk-FWBSGBB7.js";
94
94
  import {
95
- ProviderRegistry
96
- } from "./chunk-OIOTHBDB.js";
95
+ ProviderRegistry,
96
+ listBuiltInProviderMetadata
97
+ } from "./chunk-25HFWCM3.js";
97
98
  import {
98
99
  ConfigManager
99
- } from "./chunk-H6FND2UG.js";
100
+ } from "./chunk-MTIS7H6V.js";
100
101
  import {
101
102
  describePlugin,
102
103
  getActivePluginAssets,
@@ -113,7 +114,7 @@ import {
113
114
  trustHook,
114
115
  trustPlugin,
115
116
  untrustHook
116
- } from "./chunk-W5XUZYQE.js";
117
+ } from "./chunk-JEJHNVA2.js";
117
118
  import {
118
119
  CONTENT_ONLY_STREAM_REMINDER,
119
120
  TEE_FINAL_USER_NUDGE,
@@ -147,7 +148,7 @@ import {
147
148
  import {
148
149
  fileCheckpoints
149
150
  } from "./chunk-4BKXL7SM.js";
150
- import "./chunk-KQQHMGK7.js";
151
+ import "./chunk-HPDI4F5F.js";
151
152
  import {
152
153
  AGENTIC_BEHAVIOR_GUIDELINE,
153
154
  AUTHOR,
@@ -166,7 +167,7 @@ import {
166
167
  SKILLS_DIR_NAME,
167
168
  VERSION,
168
169
  buildUserIdentityPrompt
169
- } from "./chunk-323S2X5I.js";
170
+ } from "./chunk-KWYJFLXY.js";
170
171
  import {
171
172
  buildChatIndex,
172
173
  clearChatIndex,
@@ -1398,7 +1399,7 @@ No tools match "${filter}".
1398
1399
  const { join: join6 } = await import("path");
1399
1400
  const { existsSync: existsSync6 } = await import("fs");
1400
1401
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1401
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-YN4B6C7B.js");
1402
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-24AD5JQV.js");
1402
1403
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1403
1404
  const cwd = process.cwd();
1404
1405
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2386,7 +2387,7 @@ function createReviewCommands() {
2386
2387
  usage: "/test [command|filter]",
2387
2388
  async execute(args, ctx) {
2388
2389
  try {
2389
- const { executeTests } = await import("./run-tests-YNHESHYY.js");
2390
+ const { executeTests } = await import("./run-tests-ICTVJSJN.js");
2390
2391
  const argStr = args.join(" ").trim();
2391
2392
  let testArgs = {};
2392
2393
  if (argStr) {
@@ -8065,8 +8066,9 @@ process.on("unhandledRejection", (reason) => {
8065
8066
  `);
8066
8067
  process.exit(1);
8067
8068
  });
8069
+ var builtInProviderIds = listBuiltInProviderMetadata().map(({ id }) => id).join("/");
8068
8070
  program.name("aicli").description("Cross-platform REPL-style AI CLI with multi-provider support").version(VERSION);
8069
- program.option("--provider <name>", "AI provider to use (claude/gemini/deepseek/zhipu/kimi 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) => {
8071
+ 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) => {
8070
8072
  if (options.prompt !== void 0) {
8071
8073
  await runHeadless(options);
8072
8074
  } else {
@@ -8113,7 +8115,7 @@ program.command("web").description("Start Web UI server with browser-based chat
8113
8115
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
8114
8116
  process.exit(1);
8115
8117
  }
8116
- const { startWebServer } = await import("./server-SSAWGNT7.js");
8118
+ const { startWebServer } = await import("./server-IXUVVPTV.js");
8117
8119
  await startWebServer({ port, host: options.host });
8118
8120
  });
8119
8121
  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) => {
@@ -8280,11 +8282,11 @@ program.command("sessions").description("List recent conversation sessions").opt
8280
8282
  console.log(footer + "\n");
8281
8283
  });
8282
8284
  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) => {
8283
- const { runUsageCli } = await import("./usage-PDKM7J75.js");
8285
+ const { runUsageCli } = await import("./usage-23I3ZJZO.js");
8284
8286
  await runUsageCli(options);
8285
8287
  });
8286
8288
  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) => {
8287
- const { runDoctorCli } = await import("./doctor-cli-PXGXZYQB.js");
8289
+ const { runDoctorCli } = await import("./doctor-cli-WWZRFGQJ.js");
8288
8290
  const argv = process.argv.slice(2);
8289
8291
  await runDoctorCli({
8290
8292
  json: !!options.json || argv.includes("--json"),
@@ -8293,7 +8295,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
8293
8295
  });
8294
8296
  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) => {
8295
8297
  try {
8296
- const batch = await import("./batch-YUPAC4CK.js");
8298
+ const batch = await import("./batch-2B7UUX27.js");
8297
8299
  switch (action) {
8298
8300
  case "submit":
8299
8301
  if (!arg) {
@@ -8336,7 +8338,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
8336
8338
  }
8337
8339
  });
8338
8340
  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) => {
8339
- const { startMcpServer } = await import("./server-YZ37TL46.js");
8341
+ const { startMcpServer } = await import("./server-GTVYIHBG.js");
8340
8342
  await startMcpServer({
8341
8343
  allowDestructive: !!options.allowDestructive,
8342
8344
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -8349,7 +8351,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
8349
8351
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
8350
8352
  process.exit(1);
8351
8353
  }
8352
- const { runPrCli } = await import("./pr-7LQTAUFK.js");
8354
+ const { runPrCli } = await import("./pr-OOIQPCBX.js");
8353
8355
  const result = await runPrCli({
8354
8356
  action,
8355
8357
  target,
@@ -8369,8 +8371,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
8369
8371
  process.exit(result.exitCode);
8370
8372
  });
8371
8373
  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) => {
8372
- const { runCi } = await import("./ci-FX26BNT2.js");
8373
- const { formatCiResult } = await import("./ci-format-GEWIAIZD.js");
8374
+ const { runCi } = await import("./ci-G6OZDH4H.js");
8375
+ const { formatCiResult } = await import("./ci-format-BRS7G5X5.js");
8374
8376
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
8375
8377
  if (formats > 1) {
8376
8378
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -8528,7 +8530,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
8528
8530
  config.get("customProviders"),
8529
8531
  config.getConfigDir()
8530
8532
  );
8531
- const { startHub } = await import("./hub-RCANK6SK.js");
8533
+ const { startHub } = await import("./hub-2DYZQVEN.js");
8532
8534
  await startHub(
8533
8535
  {
8534
8536
  topic: topic ?? "",
@@ -27,9 +27,9 @@ import {
27
27
  touchMemoryReferences,
28
28
  updateMemoryApproval,
29
29
  updateMemoryEntry
30
- } from "./chunk-T7R7ILYT.js";
30
+ } from "./chunk-JFXKQPKY.js";
31
31
  import "./chunk-YVTASHS5.js";
32
- import "./chunk-R6DXWVVN.js";
32
+ import "./chunk-ZQZEBPAQ.js";
33
33
  import "./chunk-6BUTA5VW.js";
34
34
  export {
35
35
  addMemoryEntry,
@@ -28,9 +28,9 @@ import {
28
28
  touchMemoryReferences,
29
29
  updateMemoryApproval,
30
30
  updateMemoryEntry
31
- } from "./chunk-HGTDI5ME.js";
31
+ } from "./chunk-KMS3LBO3.js";
32
32
  import "./chunk-HOSJZMQS.js";
33
- import "./chunk-323S2X5I.js";
33
+ import "./chunk-KWYJFLXY.js";
34
34
  import "./chunk-B5TYJO7V.js";
35
35
  import "./chunk-IW3Q7AE5.js";
36
36
  export {
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  countSeverity,
4
4
  runCi
5
- } from "./chunk-Z5TCAE4L.js";
6
- import "./chunk-GC4KA5LF.js";
5
+ } from "./chunk-2XPJRRBB.js";
6
+ import "./chunk-WAAFA32V.js";
7
7
  import {
8
8
  buildReviewPrompt,
9
9
  buildSecurityReviewPrompt,
@@ -11,15 +11,15 @@ import {
11
11
  } from "./chunk-HLWUDRBO.js";
12
12
  import {
13
13
  ProviderRegistry
14
- } from "./chunk-OIOTHBDB.js";
14
+ } from "./chunk-25HFWCM3.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-H6FND2UG.js";
17
+ } from "./chunk-MTIS7H6V.js";
18
18
  import "./chunk-XZNRZGG2.js";
19
19
  import "./chunk-TU3L3PW7.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-323S2X5I.js";
22
+ } from "./chunk-KWYJFLXY.js";
23
23
  import "./chunk-IW3Q7AE5.js";
24
24
 
25
25
  // src/cli/pr.ts
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-KQQHMGK7.js";
6
- import "./chunk-323S2X5I.js";
5
+ } from "./chunk-HPDI4F5F.js";
6
+ import "./chunk-KWYJFLXY.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-KFNQESEG.js";
5
- import "./chunk-R6DXWVVN.js";
4
+ } from "./chunk-BS44XEZ4.js";
5
+ import "./chunk-ZQZEBPAQ.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-HU3IYBU5.js";
5
- import "./chunk-HGTDI5ME.js";
4
+ } from "./chunk-D6DHS5GL.js";
5
+ import "./chunk-KMS3LBO3.js";
6
6
  import "./chunk-GLSR2NR3.js";
7
7
  import "./chunk-UUSRWSSX.js";
8
8
  import "./chunk-CKH4KQ4E.js";
9
9
  import "./chunk-BXP6YZ2P.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-W5XUZYQE.js";
12
+ } from "./chunk-JEJHNVA2.js";
13
13
  import {
14
14
  getDangerLevel,
15
15
  schemaToJsonSchema
@@ -17,10 +17,10 @@ import {
17
17
  import "./chunk-TU3L3PW7.js";
18
18
  import "./chunk-HOSJZMQS.js";
19
19
  import "./chunk-4BKXL7SM.js";
20
- import "./chunk-KQQHMGK7.js";
20
+ import "./chunk-HPDI4F5F.js";
21
21
  import {
22
22
  VERSION
23
- } from "./chunk-323S2X5I.js";
23
+ } from "./chunk-KWYJFLXY.js";
24
24
  import "./chunk-6RPGQ5CG.js";
25
25
  import "./chunk-KHYD3WXE.js";
26
26
  import "./chunk-NYNSYLFY.js";
@@ -23,7 +23,7 @@ import {
23
23
  scanDirTree,
24
24
  scanProject,
25
25
  setupProxy
26
- } from "./chunk-YXMBP567.js";
26
+ } from "./chunk-A6JLBNAI.js";
27
27
  import {
28
28
  computeCost,
29
29
  formatCost,
@@ -64,7 +64,7 @@ import {
64
64
  spawnAgentContext,
65
65
  truncateOutput,
66
66
  undoStack
67
- } from "./chunk-HU3IYBU5.js";
67
+ } from "./chunk-D6DHS5GL.js";
68
68
  import {
69
69
  addMemoryEntry,
70
70
  clearMemoryEntries,
@@ -78,7 +78,7 @@ import {
78
78
  parseWritableScope,
79
79
  updateMemoryApproval,
80
80
  updateMemoryEntry
81
- } from "./chunk-HGTDI5ME.js";
81
+ } from "./chunk-KMS3LBO3.js";
82
82
  import "./chunk-GLSR2NR3.js";
83
83
  import "./chunk-UUSRWSSX.js";
84
84
  import "./chunk-CKH4KQ4E.js";
@@ -91,13 +91,13 @@ import {
91
91
  buildDoctorReport,
92
92
  formatDoctorReport,
93
93
  loadContextFiles
94
- } from "./chunk-NOB2OPQI.js";
94
+ } from "./chunk-FWBSGBB7.js";
95
95
  import {
96
96
  ProviderRegistry
97
- } from "./chunk-OIOTHBDB.js";
97
+ } from "./chunk-25HFWCM3.js";
98
98
  import {
99
99
  ConfigManager
100
- } from "./chunk-H6FND2UG.js";
100
+ } from "./chunk-MTIS7H6V.js";
101
101
  import {
102
102
  describePlugin,
103
103
  getActivePluginAssets,
@@ -112,7 +112,7 @@ import {
112
112
  runTool,
113
113
  setPluginEnabled,
114
114
  trustPlugin
115
- } from "./chunk-W5XUZYQE.js";
115
+ } from "./chunk-JEJHNVA2.js";
116
116
  import {
117
117
  CONTENT_ONLY_STREAM_REMINDER,
118
118
  TEE_FINAL_USER_NUDGE,
@@ -137,7 +137,7 @@ import {
137
137
  getGitRoot
138
138
  } from "./chunk-HOSJZMQS.js";
139
139
  import "./chunk-4BKXL7SM.js";
140
- import "./chunk-KQQHMGK7.js";
140
+ import "./chunk-HPDI4F5F.js";
141
141
  import {
142
142
  AGENTIC_BEHAVIOR_GUIDELINE,
143
143
  AUTHOR,
@@ -153,7 +153,7 @@ import {
153
153
  SKILLS_DIR_NAME,
154
154
  VERSION,
155
155
  buildUserIdentityPrompt
156
- } from "./chunk-323S2X5I.js";
156
+ } from "./chunk-KWYJFLXY.js";
157
157
  import "./chunk-6RPGQ5CG.js";
158
158
  import "./chunk-KHYD3WXE.js";
159
159
  import "./chunk-NYNSYLFY.js";
@@ -815,7 +815,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
815
815
  Cost: ${formatCost(cost)}` : "";
816
816
  let memoryLine = "";
817
817
  try {
818
- const { countPendingMemories } = await import("./persistent-memory-UARSSYAA.js");
818
+ const { countPendingMemories } = await import("./persistent-memory-LJT37XVO.js");
819
819
  const pending = countPendingMemories(ctx.config.getConfigDir());
820
820
  if (pending > 0) memoryLine = `
821
821
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -1624,14 +1624,14 @@ async function handleSecurityReview(args, ctx) {
1624
1624
  async function handleTest(args, ctx) {
1625
1625
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
1626
1626
  try {
1627
- const { executeTests } = await import("./run-tests-YNHESHYY.js");
1628
1627
  const argStr = args.join(" ").trim();
1629
1628
  let testArgs = {};
1630
1629
  if (argStr) {
1631
1630
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
1632
1631
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
1633
1632
  }
1634
- const report = await executeTests(testArgs);
1633
+ const runTests = ctx.runTests ?? (await import("./run-tests-ICTVJSJN.js")).executeTests;
1634
+ const report = await runTests(testArgs);
1635
1635
  ctx.send({ type: "info", message: report });
1636
1636
  } catch (err) {
1637
1637
  ctx.send({ type: "error", message: `Test failed: ${err.message}` });
@@ -1888,7 +1888,7 @@ async function handleMemory(args, ctx) {
1888
1888
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
1889
1889
  } else if (sub === "export") {
1890
1890
  if (args[1] === "md") {
1891
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-UARSSYAA.js");
1891
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-LJT37XVO.js");
1892
1892
  ctx.send({
1893
1893
  type: "export_data",
1894
1894
  format: "md",
@@ -3,15 +3,15 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-HU3IYBU5.js";
7
- import "./chunk-HGTDI5ME.js";
6
+ } from "./chunk-D6DHS5GL.js";
7
+ import "./chunk-KMS3LBO3.js";
8
8
  import "./chunk-GLSR2NR3.js";
9
9
  import "./chunk-UUSRWSSX.js";
10
10
  import "./chunk-CKH4KQ4E.js";
11
11
  import "./chunk-BXP6YZ2P.js";
12
12
  import {
13
13
  runTool
14
- } from "./chunk-W5XUZYQE.js";
14
+ } from "./chunk-JEJHNVA2.js";
15
15
  import {
16
16
  getDangerLevel,
17
17
  runLeanAgentLoop
@@ -19,10 +19,10 @@ import {
19
19
  import "./chunk-TU3L3PW7.js";
20
20
  import "./chunk-HOSJZMQS.js";
21
21
  import "./chunk-4BKXL7SM.js";
22
- import "./chunk-KQQHMGK7.js";
22
+ import "./chunk-HPDI4F5F.js";
23
23
  import {
24
24
  SUBAGENT_ALLOWED_TOOLS
25
- } from "./chunk-323S2X5I.js";
25
+ } from "./chunk-KWYJFLXY.js";
26
26
  import "./chunk-6RPGQ5CG.js";
27
27
  import "./chunk-KHYD3WXE.js";
28
28
  import "./chunk-NYNSYLFY.js";
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-EZ6QLHOS.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-H6FND2UG.js";
11
+ } from "./chunk-MTIS7H6V.js";
12
12
  import "./chunk-TU3L3PW7.js";
13
- import "./chunk-323S2X5I.js";
13
+ import "./chunk-KWYJFLXY.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
@@ -87,16 +87,21 @@ document.addEventListener('keydown', (event) => {
87
87
 
88
88
  document.getElementById('auth-form')?.addEventListener('submit', handleAuth);
89
89
 
90
- function registerServiceWorker() {
90
+ function registerServiceWorker() {
91
91
  // Self-updating service worker (v0.4.159). A new SW postMessages
92
92
  // 'sw-updated' (and triggers controllerchange) when it takes over; reload
93
93
  // once so users do not stay on stale index.html/app.js after an upgrade.
94
- if (!('serviceWorker' in navigator)) return;
95
- let swReloaded = false;
96
- const reloadOnce = () => {
97
- if (!swReloaded) {
98
- swReloaded = true;
99
- location.reload();
94
+ if (!('serviceWorker' in navigator)) return;
95
+ // A first-time install also emits `controllerchange` after clients.claim().
96
+ // Reloading in that case resets focus and any in-progress input for no gain:
97
+ // this page already came from the current server. Only an already-controlled
98
+ // page needs a reload when a replacement worker takes over.
99
+ const hadController = Boolean(navigator.serviceWorker.controller);
100
+ let swReloaded = false;
101
+ const reloadOnce = () => {
102
+ if (hadController && !swReloaded) {
103
+ swReloaded = true;
104
+ location.reload();
100
105
  }
101
106
  };
102
107
  navigator.serviceWorker.addEventListener('message', (e) => {
@@ -24,6 +24,7 @@ import {
24
24
  sessionSearchInput, toolsSearchInput, sessionTabsListEl, btnAddTab,
25
25
  dashboardPanel, btnDashboardRefresh,
26
26
  } from './dom.js';
27
+ import { setupSidebarTabs } from './sidebar-tabs.js';
27
28
 
28
29
  // ── Configure marked.js ────────────────────────────────────────────
29
30
 
@@ -1654,42 +1655,9 @@ if (sessionSearchInput) {
1654
1655
 
1655
1656
  // ── Sidebar tabs ──────────────────────────────────────────────────────
1656
1657
 
1657
- let fileTreeLoaded = false;
1658
-
1659
- function switchSidebarTab(tabName) {
1660
- document.querySelectorAll('.sidebar-tab').forEach(btn => {
1661
- const active = btn.dataset.tab === tabName;
1662
- btn.classList.toggle('active', active);
1663
- btn.setAttribute('aria-selected', String(active));
1664
- btn.tabIndex = active ? 0 : -1;
1665
- });
1666
- document.querySelectorAll('.sidebar-tab-content').forEach(el => {
1667
- const active = el.id === `tab-${tabName}`;
1668
- el.classList.toggle('hidden', !active);
1669
- el.setAttribute('aria-hidden', String(!active));
1670
- });
1671
- // Lazy-init file tree on first visit
1672
- if (tabName === 'files' && !fileTreeLoaded) {
1673
- fileTreeLoaded = true;
1674
- initFileTree();
1675
- }
1676
- if (tabName === 'dashboard') renderDashboard();
1677
- }
1678
-
1679
- const sidebarTabs = [...document.querySelectorAll('.sidebar-tab')];
1680
- sidebarTabs.forEach((btn, index) => {
1681
- btn.addEventListener('click', () => switchSidebarTab(btn.dataset.tab));
1682
- btn.addEventListener('keydown', (event) => {
1683
- let target = index;
1684
- if (event.key === 'ArrowRight') target = (index + 1) % sidebarTabs.length;
1685
- else if (event.key === 'ArrowLeft') target = (index - 1 + sidebarTabs.length) % sidebarTabs.length;
1686
- else if (event.key === 'Home') target = 0;
1687
- else if (event.key === 'End') target = sidebarTabs.length - 1;
1688
- else return;
1689
- event.preventDefault();
1690
- sidebarTabs[target].focus();
1691
- switchSidebarTab(sidebarTabs[target].dataset.tab);
1692
- });
1658
+ const switchSidebarTab = setupSidebarTabs({
1659
+ onFilesFirstVisit: initFileTree,
1660
+ onDashboard: renderDashboard,
1693
1661
  });
1694
1662
  btnDashboardRefresh?.addEventListener('click', () => {
1695
1663
  send({ type: 'command', name: 'status', args: [] });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Accessible sidebar tab state machine.
3
+ *
4
+ * Kept independent from app.js so click/keyboard/ARIA state transitions have
5
+ * one owner and can be tested without the rest of the chat application.
6
+ */
7
+ export function setupSidebarTabs({ onFilesFirstVisit, onDashboard }) {
8
+ const tabs = [...document.querySelectorAll('.sidebar-tab')];
9
+ let fileTreeLoaded = false;
10
+
11
+ function switchTo(tabName) {
12
+ tabs.forEach((button) => {
13
+ const active = button.dataset.tab === tabName;
14
+ button.classList.toggle('active', active);
15
+ button.setAttribute('aria-selected', String(active));
16
+ button.tabIndex = active ? 0 : -1;
17
+ });
18
+ document.querySelectorAll('.sidebar-tab-content').forEach((panel) => {
19
+ const active = panel.id === `tab-${tabName}`;
20
+ panel.classList.toggle('hidden', !active);
21
+ panel.setAttribute('aria-hidden', String(!active));
22
+ });
23
+
24
+ if (tabName === 'files' && !fileTreeLoaded) {
25
+ fileTreeLoaded = true;
26
+ onFilesFirstVisit();
27
+ }
28
+ if (tabName === 'dashboard') onDashboard();
29
+ }
30
+
31
+ tabs.forEach((button, index) => {
32
+ button.addEventListener('click', () => switchTo(button.dataset.tab));
33
+ button.addEventListener('keydown', (event) => {
34
+ let target = index;
35
+ if (event.key === 'ArrowRight') target = (index + 1) % tabs.length;
36
+ else if (event.key === 'ArrowLeft') target = (index - 1 + tabs.length) % tabs.length;
37
+ else if (event.key === 'Home') target = 0;
38
+ else if (event.key === 'End') target = tabs.length - 1;
39
+ else return;
40
+
41
+ event.preventDefault();
42
+ tabs[target].focus();
43
+ switchTo(tabs[target].dataset.tab);
44
+ });
45
+ });
46
+
47
+ return switchTo;
48
+ }
@@ -16,7 +16,7 @@ const CACHE_NAME = 'aicli-v3';
16
16
  // HTML/JS that must always be fresh — never served from the SW cache, so an
17
17
  // upgraded server is reflected on the very next load. Other assets (vendored
18
18
  // CSS/JS, icons) are large + content-stable and fine to cache.
19
- const NEVER_CACHE = new Set(['/', '/index.html', '/state.js', '/util.js', '/dom.js', '/app.js', '/templates.js', '/actions.js']);
19
+ const NEVER_CACHE = new Set(['/', '/index.html', '/state.js', '/util.js', '/dom.js', '/app.js', '/sidebar-tabs.js', '/templates.js', '/actions.js']);
20
20
 
21
21
  // App shell to precache (offline-capable startup). Deliberately EXCLUDES the
22
22
  // always-fresh HTML/JS in NEVER_CACHE — only large content-stable assets.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.261",
3
+ "version": "0.4.262",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",