@hifullmoon/aicommit 2.3.0 → 2.4.0

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.
@@ -10,7 +10,10 @@
10
10
  "models": {
11
11
  "default": {
12
12
  "modelId": "MiniMax-M3",
13
- "reasoning": { "mode": "on", "effort": "medium" }
13
+ "reasoning": {
14
+ "mode": "on",
15
+ "effort": "medium"
16
+ }
14
17
  }
15
18
  }
16
19
  },
@@ -22,7 +25,10 @@
22
25
  "models": {
23
26
  "chat": {
24
27
  "modelId": "deepseek-v4-flash",
25
- "reasoning": { "mode": "on", "effort": "high" }
28
+ "reasoning": {
29
+ "mode": "on",
30
+ "effort": "high"
31
+ }
26
32
  }
27
33
  }
28
34
  },
@@ -32,8 +38,12 @@
32
38
  "apiKeyEnv": "OPENROUTER_API_KEY",
33
39
  "defaultModel": "fast",
34
40
  "models": {
35
- "fast": { "modelId": "openai/gpt-4o-mini" },
36
- "quality": { "modelId": "openai/gpt-4o" }
41
+ "fast": {
42
+ "modelId": "openai/gpt-4o-mini"
43
+ },
44
+ "quality": {
45
+ "modelId": "openai/gpt-4o"
46
+ }
37
47
  }
38
48
  },
39
49
  "kimi-code": {
@@ -42,7 +52,9 @@
42
52
  "apiKeyEnv": "KIMI_API_KEY",
43
53
  "defaultModel": "default",
44
54
  "models": {
45
- "default": { "modelId": "kimi-for-coding" }
55
+ "default": {
56
+ "modelId": "kimi-for-coding"
57
+ }
46
58
  }
47
59
  },
48
60
  "ollama": {
@@ -50,8 +62,12 @@
50
62
  "apiUrl": "http://127.0.0.1:11434/api/chat",
51
63
  "defaultModel": "qwen",
52
64
  "models": {
53
- "qwen": { "modelId": "qwen3:8b" },
54
- "deepseek": { "modelId": "deepseek-r1:14b" }
65
+ "qwen": {
66
+ "modelId": "qwen3:8b"
67
+ },
68
+ "deepseek": {
69
+ "modelId": "deepseek-r1:14b"
70
+ }
55
71
  }
56
72
  }
57
73
  },
@@ -122,5 +138,12 @@
122
138
  "maxTokens": 4096,
123
139
  "maxDisplayChars": 12000
124
140
  },
125
- "stripFiles": ["*.min.js", "*.map", "*.snap"]
141
+ "stripFiles": ["*.min.js", "*.map", "*.snap"],
142
+ "largeChange": {
143
+ "strategy": "auto",
144
+ "chunkInputTokens": 12000,
145
+ "maxTotalTokens": 200000,
146
+ "concurrency": 2,
147
+ "timeoutMs": 180000
148
+ }
126
149
  }
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ This file lists notable user-facing changes. Internal refactors, test-only chang
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.4.0] - 2026-09-09
8
+
9
+ ### Changed
10
+
11
+ - Large changes now default to a local inventory, repeated-edit deduplication, and bounded representative excerpts, typically using one model request. Exhaustive model analysis is available through personal `largeChange.strategy: "deep"`.
12
+ - Large split plans must fit a complete local candidate inventory in one request by default; oversized plans stop before spending tokens. Coverage distinguishes sampled content from complete analysis.
13
+ - Temporary diff and untracked-file snapshots open descriptors only while reading or writing, preventing large file sets from exhausting the process descriptor limit.
14
+
15
+ - Moved model requests and streamed response decoding to Pi AI, using its bundled model metadata for reasoning capabilities while retaining existing Provider/Model configuration, custom endpoints, and native Ollama compatibility.
16
+ - Raised the minimum Node.js version to 22.19.0 for Pi AI; startup now reports unsupported runtimes before loading the model SDK.
17
+ - Streamed responses require an explicit provider finish reason. Token-limit aliases remain recoverable, mixed reasoning fields retain their text, and endpoints that only support complete JSON can use `extraBody.stream: false` without streaming-only parameters.
18
+
7
19
  ## [2.3.0] - 2026-09-05
8
20
 
9
21
  ### Added
@@ -188,7 +200,8 @@ This file lists notable user-facing changes. Internal refactors, test-only chang
188
200
  - Added file-level split planning and execution with Git-state concurrency checks.
189
201
  - Added provider presets and user/project configuration boundaries.
190
202
 
191
- [Unreleased]: https://github.com/hi-fullmoon/AICommit/compare/v2.3.0...HEAD
203
+ [Unreleased]: https://github.com/hi-fullmoon/AICommit/compare/v2.4.0...HEAD
204
+ [2.4.0]: https://github.com/hi-fullmoon/AICommit/releases/tag/v2.4.0
192
205
  [2.3.0]: https://github.com/hi-fullmoon/AICommit/releases/tag/v2.3.0
193
206
  [2.2.3]: https://github.com/hi-fullmoon/AICommit/releases/tag/v2.2.3
194
207
  [2.2.2]: https://github.com/hi-fullmoon/AICommit/releases/tag/v2.2.2
package/README.md CHANGED
@@ -30,7 +30,7 @@ These screenshots were captured from real interactive terminal sessions in this
30
30
  npm install --global @hifullmoon/aicommit
31
31
  ```
32
32
 
33
- Requires Node.js >= 18.
33
+ Requires Node.js >= 22.19.0.
34
34
 
35
35
  Update an npm-global installation from the configured registry:
36
36
 
@@ -193,10 +193,10 @@ This is the only supported user-config shape. Earlier flat or provider-level `mo
193
193
  | `timeoutMs` | Per-request timeout in milliseconds (default: `120000`) |
194
194
  | `retry` | Transient retry limits: `maxAttempts`, `baseDelayMs`, and `maxDelayMs` (defaults: `3`, `500`, and `5000`) |
195
195
  | `credentialHelper` | Opt in to `git credential fill` with `enabled` and `username` (defaults: `false` and `aicommit`) |
196
- | `maxDiffChars` | Diff chars sent to the model per call; oversized diffs become a `--stat` summary + truncated hunks (default: `30000`) |
197
- | `maxFileDiffChars` | Cap on a single file's diff section; bigger sections are truncated to their leading hunks so one huge file can't crowd out the rest (default: `3000`) |
198
- | `splitMaxDiffChars` | Diff chars sent to the split-planning call; split mode needs less hunk detail than final message generation (default: `16000`) |
199
- | `splitMaxPlanFiles` | Number of changed files shown to the split planner before extra files are swept into a catch-all commit (default: `100`) |
196
+ | `maxDiffChars` | Per-analysis diff character budget; larger changes use chunked summaries (default: `30000`) |
197
+ | `maxFileDiffChars` | Target per-file fragment size; remaining content is analyzed in subsequent chunks (default: `3000`) |
198
+ | `splitMaxDiffChars` | Context character budget for each split-planning request (default: `16000`) |
199
+ | `splitMaxPlanFiles` | Files or candidate groups per planning request; larger changes use hierarchical planning (default: `100`) |
200
200
  | `diffContextLines` | Context lines around each diff hunk (`git diff --unified=<n>`); lower values mean fewer tokens (default: `1`) |
201
201
  | `stripFiles` | Extra files to stub out of the diff like lock files, matched by basename with `*`/`?` wildcards, e.g. `["*.min.js", "*.map", "*.snap"]` (default: `[]`; project-level entries are merged with user-level ones, not replaced) |
202
202
  | `regenerateWithDiff` | `true` re-sends the full diff on every regenerate for more varied rewrites; `false` (default) only asks the model to reword its previous message, which is far cheaper |
@@ -471,3 +471,29 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for local development and pull-request ch
471
471
  ## License
472
472
 
473
473
  [MIT](LICENSE)
474
+
475
+ ### Automatic large-change analysis
476
+
477
+ The default `largeChange.strategy: "auto"` inventories every file locally, groups identical textual edits within a module, and selects representative excerpts under a fixed input budget. Lockfiles, generated files (such as `dist/`, `build/`, `*.map`, and `*.snap`), and `stripFiles` matches contribute metadata only. Complete content still undergoes local secret scanning; these selection rules do not change which files Git commits.
478
+
479
+ A normal commit typically needs one model request, with no per-file AI calls or recursive model reduction. The inventory contains at most 16 representative groups under a UTF-8 byte budget, prioritizing coverage across code, configuration, tests, and other categories. It explicitly describes sampling limits. Both terminal and JSON output distinguish fully analyzed files, representative excerpts, and metadata-only files. Provider retries, response recovery, policy correction, and user-requested regeneration can still add requests.
480
+
481
+ Split mode builds local candidates and plans them in one model request. The complete candidate inventory must fit `splitMaxPlanFiles` and the input budget; otherwise it stops before calling the provider and suggests staging a smaller logical change or explicitly selecting deep analysis. File membership is still validated completely, with no automatic catch-all commits. Small changes keep the existing request path.
482
+
483
+ For exhaustive chunk-by-chunk model analysis, opt in through personal configuration:
484
+
485
+ ```json
486
+ {
487
+ "largeChange": {
488
+ "strategy": "deep",
489
+ "chunkInputTokens": 12000,
490
+ "maxTotalTokens": 200000,
491
+ "concurrency": 2,
492
+ "timeoutMs": 180000
493
+ }
494
+ }
495
+ ```
496
+
497
+ `deep` spends more requests and tokens, with a maximum of 256 requests. Repository configuration cannot change this personal strategy or raise the spending budget. Both strategies use conservative token estimates; missing usage retains the reservation. Retries, reduction, planning, and final generation share the budget. Budget exhaustion or invalid groups stop execution without automatically committing incomplete results.
498
+
499
+ Complete patches and larger untracked text are captured in local temporary files, with descriptors opened only during reads and writes. Files are cleaned on normal exit or cancellation; crashes may leave them behind. Content reads are bounded. Lines exceeding 1 MiB, independent groups that cannot fit a global planning budget, and experimental hunk planning for large changes fail explicitly.
package/README.zh-CN.md CHANGED
@@ -32,7 +32,7 @@ AI 驱动的 Git 提交信息生成器:读取 diff,请 AI 模型生成符合
32
32
  npm install --global @hifullmoon/aicommit
33
33
  ```
34
34
 
35
- 需要 Node.js >= 18。
35
+ 需要 Node.js >= 22.19.0。
36
36
 
37
37
  从当前配置的 registry 更新 npm 全局安装:
38
38
 
@@ -195,10 +195,10 @@ aicommit -p deepseek -m reasoner
195
195
  | `timeoutMs` | 单次请求超时,单位为毫秒(默认:`120000`) |
196
196
  | `retry` | 瞬时错误重试限制:`maxAttempts`、`baseDelayMs`、`maxDelayMs`(默认:`3`、`500`、`5000`) |
197
197
  | `credentialHelper` | 通过 `enabled` 和 `username` 选择性启用 `git credential fill`(默认:`false`、`aicommit`) |
198
- | `maxDiffChars` | 单次发送给模型的 diff 字符数;超限后改为 `--stat` 摘要和截断的 hunk(默认:`30000`) |
199
- | `maxFileDiffChars` | 单文件 diff 上限;超限文件只保留前部 hunk,避免一个大文件挤占全部上下文(默认:`3000`) |
200
- | `splitMaxDiffChars` | 拆分规划请求的 diff 字符数;规划阶段需要的 hunk 细节少于最终信息生成(默认:`16000`) |
201
- | `splitMaxPlanFiles` | 交给拆分规划器的最大变更文件数;超出部分归入兜底提交(默认:`100`) |
198
+ | `maxDiffChars` | 每次分析的 diff 字符预算;超限自动分块汇总(默认:`30000`) |
199
+ | `maxFileDiffChars` | 单文件正文分块参考大小;剩余内容继续分析(默认:`3000`) |
200
+ | `splitMaxDiffChars` | 每次批次规划的上下文字符预算(默认:`16000`) |
201
+ | `splitMaxPlanFiles` | 每次规划的文件或候选组数量上限;超限分层规划(默认:`100`) |
202
202
  | `diffContextLines` | 每个 diff hunk 周围的上下文行数(`git diff --unified=<n>`);越小越节省 token(默认:`1`) |
203
203
  | `stripFiles` | 额外替换为占位的文件,按 basename 使用 `*` / `?` 通配,如 `["*.min.js", "*.map", "*.snap"]`(默认:`[]`;项目项与用户项合并而非覆盖) |
204
204
  | `regenerateWithDiff` | `true` 表示每次重写都重发完整 diff,以获得更多变化;`false`(默认)只要求模型改写上一条消息,成本更低 |
@@ -473,3 +473,29 @@ exec zsh
473
473
  ## 许可证
474
474
 
475
475
  [MIT](LICENSE)
476
+
477
+ ### 大变更自动分析
478
+
479
+ 默认 `largeChange.strategy: "auto"` 在本地统计所有文件,按模块聚合相同文本修改,并选取固定预算内的代表性片段。lockfile、生成文件(如 `dist/`、`build/`、`*.map`、`*.snap`)和 `stripFiles` 匹配项只提供元数据。所有内容仍在本地接受敏感信息扫描;这些规则不会改变实际提交的文件。
480
+
481
+ 普通提交通常只需要一次模型请求,不会为每个文件调用 AI,也不会递归调用模型汇总。摘要最多包含 16 个代表组,并受 UTF-8 字节预算约束;优先覆盖代码、配置和测试等不同类别。摘要明确说明抽样范围,界面和 JSON 分别报告全文分析、代表片段和仅元数据的文件数,不把抽样视为完整理解。提供方重试、响应恢复、格式修正和用户重新生成仍可能增加请求。
482
+
483
+ 批次提交先在本地建立候选组,再用一次模型请求规划。只有完整候选清单能放入 `splitMaxPlanFiles` 和输入预算时才请求模型;否则在请求前停止,提示暂存更小的逻辑变更或显式选择深度分析。所有文件的归属仍进行完整性校验,不会因数量过多生成兜底提交。小变更保持原有请求路径。
484
+
485
+ 确实需要逐块 AI 分析时,在个人配置中设置:
486
+
487
+ ```json
488
+ {
489
+ "largeChange": {
490
+ "strategy": "deep",
491
+ "chunkInputTokens": 12000,
492
+ "maxTotalTokens": 200000,
493
+ "concurrency": 2,
494
+ "timeoutMs": 180000
495
+ }
496
+ }
497
+ ```
498
+
499
+ `deep` 会增加请求和 token 消耗,最多 256 次请求。仓库配置不能切换这项个人策略或提高费用预算。两种策略均使用保守 token 估算,未知 usage 按预留额度计入;重试、汇总、规划和消息生成共用预算。超限或无效分组会停止,不自动提交不完整结果。
500
+
501
+ 完整补丁及较大未跟踪文本暂存到本地临时文件,只在读写时打开文件句柄,正常结束或取消时清理;异常崩溃可能遗留临时文件。正文读取有界。单行超过 1 MiB、无法在预算内合并的独立分组,以及大变更的实验性 hunk 规划会明确报错。
package/bin/aicommit.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import chalk from 'chalk';
4
4
 
5
- import { main } from '../src/main.js';
5
+ import { nodeSupported, MIN_NODE_VERSION } from '../src/runtime.js';
6
6
  import { sanitizeTerminalText } from '../src/utils.js';
7
7
  import { classifyError } from '../src/errors.js';
8
8
  import { errorOutput, isJsonOutputRequested, successOutput } from '../src/output.js';
@@ -15,6 +15,11 @@ if (jsonOutput) {
15
15
  }
16
16
 
17
17
  try {
18
+ if (!nodeSupported())
19
+ throw new Error(
20
+ `AICommit requires Node.js >=${MIN_NODE_VERSION}; current version is ${process.versions.node}.`,
21
+ );
22
+ const { main } = await import('../src/main.js');
18
23
  const result = await main();
19
24
  if (jsonOutput) process.stdout.write(`${JSON.stringify(successOutput(result))}\n`);
20
25
  } catch (err) {
@@ -33,7 +33,7 @@ The release workflow uses npm Trusted Publishing without a long-lived `NPM_TOKEN
33
33
  ```bash
34
34
  workdir=$(mktemp -d)
35
35
  cd "$workdir"
36
- npm install --package-lock-only @hifullmoon/aicommit@2.3.0
36
+ npm install --package-lock-only @hifullmoon/aicommit@2.4.0
37
37
  npm audit signatures
38
38
  ```
39
39
 
@@ -0,0 +1,193 @@
1
+ # 大变更分析实施计划
2
+
3
+ 状态:核心链路已实施(2026-09-07)。原始清单保留为设计追踪,交付范围、验证结果及设计调整见文末。
4
+
5
+ ## 目标与边界
6
+
7
+ 保留现有“单次提交 / 批次提交”选择,自动根据输入预算决定一次分析或分块分析。单次模式始终生成一个 commit;批次模式按逻辑变更生成多个 commit。分析块不等于提交组。
8
+
9
+ 小变更保持一次生成请求。大变更不再仅依靠截断正文或把超过 100 个文件的部分归入兜底提交。完整文件归属由本地程序维护,模型只接收受预算约束的内容。
10
+
11
+ 第一版不增加第三种用户模式,不引入磁盘摘要缓存、不自动提交不完整批次计划、不更改现有 split 事务恢复协议。现有实验性 hunk 拆分须保持兼容;无法支持的组合应在请求前明确报错,不静默退化。
12
+
13
+ ## 当前接入点
14
+
15
+ | 模块 | 当前行为与待调整点 |
16
+ | --------------- | ------------------------------------------------------------------------------------------------------------ |
17
+ | `src/git.js` | `readGit` 使用 64 MiB 缓冲;staged diff 和二进制指纹补丁完整读入。大内容需改为流式处理。 |
18
+ | `src/main.js` | 多次获取 staged diff,调用 `condenseDiff` 后生成消息;需在所有早期读取位置消除全量正文读取。 |
19
+ | `src/split.js` | `generateSplitPlan` 接收受限上下文,`condenseFileList` 默认仅展示 100 个文件;需接入统一分析及完整归属校验。 |
20
+ | `src/api.js` | 复用消息生成、响应恢复、usage 统计能力,并支持结构化分析输入。 |
21
+ | `src/config.js` | 兼容现有字符限制配置,增加总分析预算。 |
22
+ | `src/output.js` | 已有 `data` 扩展字段,可承载分析覆盖和预算元数据;需同步 schema 与错误输出。 |
23
+
24
+ ## 核心约束
25
+
26
+ 1. 先固定分析范围和快照,再建立全量清单。staged / all 的范围语义保持不变。
27
+ 2. 每个文件都有稳定 ID;重命名保留旧、新路径。ID 仅在同一快照内稳定。
28
+ 3. 文件清单覆盖、正文覆盖、摘要质量是不同指标,不将“模型返回了结果”描述成“完整理解”。
29
+ 4. 默认省略正文的文件仍参与归属、快照校验及现有敏感内容检查。
30
+ 5. 原始 diff、路径、预览和模型中间摘要均作为不可信数据,继续应用现有信任边界。
31
+ 6. 任何请求,包括恢复请求、重试、递归汇总和最终生成,都受共享总预算、截止时间和取消信号约束。
32
+ 7. 分组必须无未知 ID、无遗漏、无重复;文件级和 hunk 级归属不能冲突。
33
+ 8. 提交前重新校验快照。并发修改、未完成分析或非法分组不能导致静默自动提交。
34
+
35
+ ## 阶段 1:数据契约、配置与基线
36
+
37
+ - [ ] 定义 `ChangeManifest`:快照标识、范围、文件 ID、路径映射、状态、增删统计、内容类型和正文策略。
38
+ - [ ] 定义 `AnalysisChunk`:文件 / 片段 ID、顺序、输入估算及来源指纹。
39
+ - [ ] 定义 `AnalysisResult`:有来源引用的事实摘要、关联建议、不确定项、覆盖记录及累计 usage。
40
+ - [ ] 定义覆盖状态:`analyzed`、`metadataOnly`、`partial`、`failed`;记录省略或失败原因。
41
+ - [ ] 明确“完整”要求:所有需正文分析的片段有有效结果,允许策略指定的 `metadataOnly`,不允许把失败标为策略省略。
42
+ - [ ] 增加配置校验、配置展示及示例;制定旧配置迁移说明。
43
+ - [ ] 建立小提交请求次数、延迟和模型输入基线。
44
+
45
+ 建议初始配置,最终默认值由阶段 7 的测量确定:
46
+
47
+ ```json
48
+ {
49
+ "largeChange": {
50
+ "strategy": "auto",
51
+ "chunkInputTokens": 12000,
52
+ "maxTotalTokens": 200000,
53
+ "concurrency": 2,
54
+ "timeoutMs": 180000
55
+ }
56
+ }
57
+ ```
58
+
59
+ `strategy` 首版仅支持 `auto`。每次输入还必须服从模型窗口和现有字符上限中更保守的有效限制,并为指令、包装及响应预留空间。旧 `maxFileDiffChars` 用作分块线索,不再直接丢弃剩余正文;`splitMaxPlanFiles` 用作每次规划的文件数量上限,不再决定全局可处理文件数。文档明确这些语义变化。
60
+
61
+ 验收:非法配置在 Git 写操作和 Provider 请求前失败;旧配置可加载;契约能表示重命名、二进制和单文件多片段。
62
+
63
+ ## 阶段 2:有界 Git 读取与快照
64
+
65
+ 依赖:阶段 1。
66
+
67
+ - [ ] 全量清单优先读取 NUL 分隔的路径、状态和 numstat,正确关联重命名、Unicode、制表符及换行路径。
68
+ - [ ] 新增流式内容读取接口,处理子进程错误、背压、取消和退出状态;禁止巨型字符串持续拼接。
69
+ - [ ] 流式计算 staged 二进制补丁指纹,保持原有指纹语义;如果确需更改算法,必须显式处理版本兼容。
70
+ - [ ] 审计 main、split、快照捕获和验证链路,消除压缩前的全量正文读取,包括未跟踪大文件和二进制变化。
71
+ - [ ] 大量路径使用受限批量参数或 Git 支持的路径输入方式,避免 Windows 命令行长度限制;路径按字面值处理。
72
+ - [ ] 优先复用现有 split 快照与未跟踪文件保护逻辑,检测读取前后的状态变化。
73
+
74
+ 验收:原始补丁超过 64 MiB 仍能完成读取与指纹计算;正文内存不随补丁总字节数线性增长;空变更和 Git 失败可区分;取消后无遗留子进程;并发修改导致中止。
75
+
76
+ ## 阶段 3:分块调度与分层摘要
77
+
78
+ 依赖:阶段 1、2。建议新增 `src/change-analysis.js`,按复杂度再拆分预算与分块模块。
79
+
80
+ - [ ] 先省略按策略无需正文的内容,再判断是否适合一次请求;全量清单在本地保留。
81
+ - [ ] 优先保持完整文件,超大文件按 hunk 分块,超大 hunk 按行切分;超长单行也必须有界,并记录无法完整分析的情况。
82
+ - [ ] 以目录、实现与测试关联改善分块,但不将分块边界固化为提交边界。
83
+ - [ ] 使用有界任务队列、背压和共享预算,限制同时驻留的正文与请求数量。
84
+ - [ ] 验证模型响应结构及引用 ID;要求每个输入片段有结果或明确不确定状态。
85
+ - [ ] 摘要超预算时递归汇总,并设置最大层级 / 请求数量保护,防止不收敛。
86
+ - [ ] 保留本地来源映射,父级用候选组 ID 引用子级;禁止在最后一次请求重新发送全部路径。
87
+ - [ ] 优先使用可用的模型窗口 / token 计数;未知模型采用保守估算,遇上下文超限缩小失败块后重试。
88
+ - [ ] 预留最终生成预算;请求发出前预占预算,并按实际 usage 结算;usage 缺失时保守记账。
89
+ - [ ] 接入现有重试与响应恢复,避免外层和内层重试相乘;将退避计入截止时间。
90
+ - [ ] 仅在本次运行内缓存已完成块;缓存键包含快照、内容、模型、保护策略和 prompt 版本。
91
+
92
+ 验收:每次请求输入受限;失败只重试对应块;所有调用都被计费记录;预算耗尽后不再发请求;摘要树不遗漏来源;小变更不额外增加一次分析调用。
93
+
94
+ ## 阶段 4:接入单次提交
95
+
96
+ 依赖:阶段 3。
97
+
98
+ - [ ] 在 `src/main.js` 接入统一分析入口;小变更走直接生成路径,大变更用事实摘要生成一个提交说明。
99
+ - [ ] 复用现有语言、commit policy、repository context、敏感内容选择及审阅流程。
100
+ - [ ] 重新措辞复用摘要;配置要求重新分析时也服从总预算。
101
+ - [ ] 不完整分析仅产生带覆盖提示的草稿,交互审阅后方可提交;非交互模式返回结构化错误,不自动提交。
102
+ - [ ] 保留提交前指纹校验与 index 事务语义。
103
+
104
+ 验收:大变更最终仍只有一个 commit;生成内容来源可追溯;分析中断不改写真实 index;快照变化阻止提交;普通小提交请求次数不变。
105
+
106
+ ## 阶段 5:接入批次提交
107
+
108
+ 依赖:阶段 3、4。
109
+
110
+ - [ ] 用摘要和短 ID 生成局部候选组,再汇总跨块关联;规划请求同样受预算限制。
111
+ - [ ] 对存在歧义的跨组关联,允许受预算约束地补充相关摘要或片段。
112
+ - [ ] 本地展开组 ID 到文件路径,校验完整覆盖、唯一归属及合法引用,替换超额文件兜底提交。
113
+ - [ ] 为最终分组生成消息,复用已有分析;大量分组的消息生成也纳入总预算。
114
+ - [ ] 未解决归属显示为待处理项,允许在现有审阅中调整;未解决前不执行、不导出可执行计划。
115
+ - [ ] 非交互模式遇不完整分析或非法分组,在自动暂存前失败。
116
+ - [ ] 继续生成现有 split plan 工件,由已有 apply / checkpoint / resume 流程执行;内部分析 ID 不改变外部路径语义。
117
+ - [ ] 验证实验性 hunk 归属和跨块片段映射;无法处理时给出明确错误。
118
+
119
+ 验收:超过 100 个文件不产生由数量上限导致的兜底组;每个路径或 hunk 完整且唯一分配;跨目录的同一逻辑变更可以合并;plan/apply、hook 失败、resume 和 abort 行为保持兼容。
120
+
121
+ ## 阶段 6:进度、机器输出与文档
122
+
123
+ 依赖:阶段 4、5。
124
+
125
+ - [ ] 展示总文件数、正文分析 / 仅统计数量、当前阶段及已完成块数;块动态细分时更新分母。
126
+ - [ ] 并发分析使用聚合进度,避免多个请求的流式内容交错输出。
127
+ - [ ] 在 JSON `data.analysis` 中增加覆盖数、失败数、降级原因和预算元数据,同步 schema;不包含 diff 和中间摘要。
128
+ - [ ] 顶层 usage / latency 汇总完整调用链;stdout 保持单个 JSON,进度进入 stderr。
129
+ - [ ] 更新双语 README、配置示例、privacy、troubleshooting,解释新旧限制语义、成本和失败恢复方式。
130
+
131
+ 验收:终端与 JSON 覆盖数字一致;`metadataOnly` 不被显示为正文已分析;机器输出兼容已有消费方式且通过 schema 校验。
132
+
133
+ ## 阶段 7:回归、规模验证与交付
134
+
135
+ 依赖:阶段 2—6。
136
+
137
+ 使用临时仓库和模拟 Provider 构造测试,不把巨型 fixture 提交到仓库。确定性测试验证边界和完整性,语义评估单独记录,不用字符串快照冒充摘要质量验证。
138
+
139
+ | 场景 | 必须验证 |
140
+ | ------------------------------------- | ------------------------------------------ |
141
+ | 普通小提交 | 一次生成请求,已有消息策略和交互保持兼容 |
142
+ | 10,000 个小文件 | 全量清单完整,请求有界;预算不足时正确停止 |
143
+ | 超过 64 MiB 的源码补丁 | 流式读取、指纹校验与内存规模符合预期 |
144
+ | 巨型 hunk、超长单行 | 不导致超限请求或无界内存,覆盖状态诚实 |
145
+ | 二进制、lock、生成文件、批量重命名 | 正文策略正确,路径仍完整纳入提交 |
146
+ | 跨目录实现与测试 | 可形成同一逻辑组,分块不强制分组 |
147
+ | 敏感文件、未跟踪符号链接 | 保持现有保护行为,不因分块绕过 |
148
+ | 429、响应截断、错误 ID、usage 缺失 | 重试有界、校验拒绝非法响应、预算保守记账 |
149
+ | 超时、Ctrl+C、Git 失败、并发修改 | 清理资源、不误提交、不破坏真实 index |
150
+ | split 导出、apply、hook 失败与 resume | 原有工件和事务恢复兼容 |
151
+
152
+ - [ ] 记录峰值 RSS、总耗时、请求数、输入 / 输出 token 及覆盖情况;至少比较两个补丁体量,确认正文内存有界。
153
+ - [ ] 记录小提交相对基线的额外耗时,测量后确定可接受阈值及最终预算默认值。
154
+ - [ ] 执行相关单元 / 集成测试,再运行 `npm run ci` 和 `npm run test:package`。
155
+ - [ ] 扩充 `eval` 的大变更样例,评估事实准确性、关键变更遗漏及逻辑分组质量。
156
+ - [ ] 真实 Provider 验证可作为单独的受预算冒烟测试,不作为离线回归的必需依赖。
157
+
158
+ 交付标准:两个原有模式都能消费统一分析结果;大变更不存在无提示的正文丢弃或文件兜底归组;输入、内存、请求数及时间均有边界;失败不会绕过现有提交保护。
159
+
160
+ ## 建议实施顺序与提交拆分
161
+
162
+ 1. 契约、配置与基线(阶段 1)。
163
+ 2. Git 流式读取、指纹及路径边界测试(阶段 2)。
164
+ 3. 分块、预算和摘要核心(阶段 3)。
165
+ 4. 单次模式集成与保护回归(阶段 4)。
166
+ 5. 批次分层规划与工件兼容(阶段 5)。
167
+ 6. UI、输出 schema、文档及规模验证(阶段 6、7)。
168
+
169
+ 各阶段完成相关验收后再进入依赖阶段。本文勾选项在对应实现和验证完成后更新;建立计划本身不触发业务代码修改或发布。
170
+
171
+ ## 本次交付与验证记录(2026-09-07)
172
+
173
+ 已交付:私有临时补丁快照及有界读取、流式指纹计算、完整文件 ID 清单、分块事实分析、运行内成功片段缓存、受限并发、共享 token / 请求数 / 时间预算、分层摘要与批次规划、严格 ID 校验、完整未跟踪文本捕获、单次和批次集成、JSON 覆盖信息、Windows 大量路径输入和批量 index 更新。
174
+
175
+ ### 设计调整
176
+
177
+ - Git 内容使用直接写临时文件的方式捕获,Node 按 64 KiB 读取,避免同步 stdout 缓冲上限;没有引入长期运行的异步 Git 子进程。临时文件空间取决于变更大小,Git 捕获有 120 秒命令超时。
178
+ - token 计数采用保守估算并结合 Provider 模型窗口。Provider 上下文超限明确失败,尚未实现 tokenizer 精确计数和 Provider 报错后的自动缩块。
179
+ - 分析不完整时统一停止,不生成可直接接受的部分草稿。完整分析结果的改写继续使用现有审阅流程。
180
+ - 批次分层规划允许合并候选组;无法收敛时要求缩小范围,不把未解决文件自动塞入兜底组。大变更不支持实验性 hunk 规划,单行超过 1 MiB 明确拒绝。
181
+ - 未新增真实 Provider 的语义质量基准;本次验证使用模拟 Provider,不能据此保证任意模型的摘要和分组质量。
182
+
183
+ ### 验证结果
184
+
185
+ - 新增分析测试 12 项通过,涵盖未知 / 重复 / 遗漏 ID、完整未跟踪快照、后段私钥材料、重试计费、超过 64 MiB 的补丁和 10,000 个生成文件。
186
+ - 111 个文件的单次和批次 CLI 实际提交测试通过:覆盖完整、token 汇总一致、暂存区最终干净;单次仍创建一个 commit。
187
+ - 最终缓存调整后,分析、预算和两个 CLI 模式的 4 项针对性回归通过。
188
+ - `npm run lint`、`npm run eval`、`npm run test:package` 通过。
189
+ - 全量 coverage 运行:298 项通过、3 项跳过、3 项因 Windows 创建符号链接返回 EPERM 失败;失败发生在 fixture 创建阶段。后续新增的万文件测试已单独通过。
190
+ - `npm run ci` 在格式检查阶段停止:88 个未修改文件包含当前 Prettier 不接受的格式 / 换行。未为了本功能重排无关文件。
191
+ - 独立进程 Git 读取及指纹基准:32 MiB 输入耗时 2,202 ms、峰值 RSS 56 MiB;96 MiB 输入耗时 5,005 ms、峰值 RSS 58 MiB。这是本机一次测量,未包含 Provider 分析和全流程延迟。可运行 `node scripts/benchmark-large-change.mjs` 复现。
192
+
193
+ 未执行真实 Provider 请求、仓库提交或发布。
package/docs/privacy.md CHANGED
@@ -54,3 +54,9 @@ Provider 自行决定服务端保留与训练策略,AICommit 无法强制控
54
54
  Use `aicommit config show` to inspect effective local state without revealing credentials.
55
55
 
56
56
  使用 `aicommit config show` 可在不显示凭据的情况下检查本地状态。
57
+
58
+ ## Large-change snapshots / 大变更快照
59
+
60
+ Default large-change analysis sends a bounded local inventory and selected protected excerpts to the configured provider, without per-file model requests. Explicit `deep` analysis sends protected fragments and intermediate factual summaries. Both local inventories and model summaries remain untrusted input. Full Git patches and larger untracked text are captured in private local temporary files, with bounded memory reads. Normal completion and Ctrl+C clean them up; an abnormal crash can leave snapshots in the system temporary directory. Summaries are reused only within the current run and are not added to JSON output or split checkpoints.
61
+
62
+ 默认大变更分析向已配置 Provider 发送受限本地清单和选定的保护后片段,不逐文件调用模型。明确选择 `deep` 时才发送分块片段和中间事实摘要。本地清单和模型摘要均视为不可信输入。完整 Git 补丁和较大未跟踪文本保存在本地私有临时文件中,按块读取;正常结束及 Ctrl+C 会清理,异常崩溃可能在系统临时目录留下快照。摘要仅在本次运行中复用,不加入 JSON 输出或 split checkpoint。
@@ -1,25 +1,53 @@
1
1
  # Provider compatibility / Provider 兼容表
2
2
 
3
- Built-in setup defaults choose an adapter and endpoint; adapters own request/response dialects; the core owns Git state, user interaction, HTTPS enforcement, retry, timeout, authorization, and machine output.
3
+ AICommit uses **Pi AI** (`@earendil-works/pi-ai`, pinned to 0.85.0) for model request construction, message conversion, SSE decoding, thinking events, and normalized results. Node.js **>=22.19.0** is required. See the [Pi AI documentation](https://github.com/earendil-works/pi/tree/main/packages/ai).
4
4
 
5
- 内置 setup 默认值负责选择 adapter 和端点;adapter 负责请求/响应方言;核心负责 Git 状态、用户交互、HTTPS、重试、超时、鉴权与机器输出。
5
+ AICommit 使用 **Pi AI**(`@earendil-works/pi-ai`,固定为 0.85.0)构造模型请求、转换消息、解析 SSE,并读取统一的推理事件和结果。要求 Node.js **>=22.19.0**。
6
6
 
7
- | Provider / adapter | Endpoint and auth / 端点与鉴权 | Streaming / 流式 | Reasoning / 推理 | Token and usage mapping / token 与 usage | Notes / 说明 |
8
- | ---------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
9
- | OpenAI / `openai` | Official HTTPS Chat Completions; Bearer key / 官方 HTTPS;Bearer key | SSE | Native for recognized `o*`/`gpt-5*`; model-dependent otherwise / 已识别推理模型原生支持 | `max_completion_tokens` for reasoning models, otherwise `max_tokens`; OpenAI usage | Unsupported effort is rejected locally for known model generations / 已知模型不支持的 effort 会本地拒绝 |
10
- | OpenRouter / `openrouter` | OpenRouter HTTPS; Bearer key; `X-Title: aicommit` | SSE | `reasoning.effort` | `max_tokens`; OpenAI-style usage | Model IDs commonly include vendor prefix / model 通常含厂商前缀 |
11
- | DeepSeek / `deepseek` | DeepSeek HTTPS; Bearer key | SSE | `thinking.type` plus normalized effort / thinking 与归一 effort | `max_tokens`; compatible usage | `medium`/`xhigh` map to supported high behavior where required / 必要时映射为 high |
12
- | MiniMax / `minimax` | MiniMax HTTPS; Bearer key | SSE | `reasoning_split` and thinking switch | `max_tokens`; compatible usage | Adapter removes conflicting switches before send / 发送前移除冲突开关 |
13
- | Kimi Code / `custom` | Kimi Code OpenAI-compatible HTTPS; Bearer key / Kimi Code OpenAI 兼容 HTTPS | SSE | Server default; no vendor fields injected / 使用服务端默认值,不注入厂商字段 | `max_tokens`; OpenAI-style usage | Bundled preset uses `kimi-for-coding`; membership and Platform keys are distinct / 会员与开放平台 key 不通用 |
14
- | Ollama native / `ollama` | Loopback `/api/chat` or `/api/generate`; normally keyless HTTP | Complete JSON in v1; native NDJSON streaming is not consumed / v1 使用完整 JSON | Native `think` boolean | `options.num_predict`; `prompt_eval_count` + `eval_count` | OpenAI-compatible `/v1/chat/completions` uses the compatible shape instead / `/v1` 使用兼容方言 |
15
- | Custom compatible / `custom` | HTTPS remote or loopback HTTP; optional core Bearer key | SSE when endpoint supports Chat Completions events | No vendor fields by default; explicit `enabledBody`/`disabledBody` / 默认不注入厂商字段 | `max_tokens`; common OpenAI/Anthropic/Ollama usage fields normalized | Validate the endpoint before trusting it with code or credentials / 发送代码前验证端点 |
7
+ The runtime keeps the existing Provider/Model config format. `providers.js` selects Pi model metadata and applies configuration overrides; `model-client.js` calls Pi's `openai-completions` implementation. `provider-response.js` normalizes legacy response fields before Pi; its SSE framing uses the lightweight [eventsource-parser](https://github.com/rexxars/eventsource-parser) dependency. `api.js` retains commit prompts, policy validation, and recovery. Presets remain setup data, not executable adapters.
16
8
 
17
- ## Compatibility contract / 兼容契约
9
+ 现有 Provider/Model 配置格式保持不变。`providers.js` 选择 Pi 模型元数据并应用配置覆盖;`model-client.js` 调用 Pi 的 `openai-completions` 实现;`provider-response.js` 在进入 Pi 前统一旧版响应字段,SSE 分帧使用轻量依赖 `eventsource-parser`;`api.js` 保留提交提示词、规则校验与恢复。预设仍是 setup 数据,不是可执行适配器。
18
10
 
19
- All built-in adapters return `content`, optional `reasoning`, normalized usage, finish reason, raw response, capabilities, attempts, and latency. Retries cover 429, selected 5xx, and network/body interruption; authentication, invalid parameters, and safety failures are not retried.
11
+ | Provider / adapter | Pi integration / Pi 接入 | Reasoning / 推理 | Token budget / 输出预算 |
12
+ | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
13
+ | OpenAI / `openai` | Chat Completions; bundled model metadata / Chat Completions 与内置模型元数据 | Pi thinking-level map; unsupported known efforts rejected locally / 使用 Pi 强度映射,已知不支持的强度本地拒绝 | Reasoning: `max_completion_tokens`; otherwise `max_tokens` |
14
+ | OpenRouter / `openrouter` | Chat Completions; `X-Title: aicommit` | Pi `reasoning.effort` and catalog capability checks / Pi 参数映射与模型能力检查 | `max_tokens` |
15
+ | DeepSeek / `deepseek` | Chat Completions; bundled model metadata / 内置模型元数据 | Pi `thinking.type` and effort mapping; enabled thinking omits temperature / Pi 映射推理参数,开启时省略 temperature | `max_tokens` |
16
+ | MiniMax / `minimax` | Chat Completions / 兼容接口 | Small compatibility override for `reasoning_split` and thinking switches / 保留少量开关兼容逻辑 | `max_tokens` |
17
+ | Kimi Code / `custom` | Existing OpenAI-compatible endpoint and `kimi-for-coding` preset / 保留现有兼容端点与预设 | Server defaults; configurable body switches / 服务端默认值或自定义请求体 | `max_tokens` |
18
+ | Ollama / `ollama` | Native JSON bridge for `/api/chat` and `/api/generate`; compatible `/v1/chat/completions` uses Pi directly / 原生端点使用 JSON 桥接,兼容端点直接使用 Pi | Native `think` switch / 原生开关 | Native: `options.num_predict`; compatible: `max_tokens` |
19
+ | Custom / `custom` | Arbitrary OpenAI-compatible model IDs and full endpoint URLs / 任意兼容模型 ID 与完整端点 URL | `enabledBody` / `disabledBody`; no inferred vendor fields / 不自动注入厂商开关 | `max_tokens` |
20
20
 
21
- 所有内置 adapter 返回 `content`、可选 `reasoning`、标准 usage、finish reason、raw response、capability、attempts 与 latency。仅 429、部分 5xx、网络/响应中断会重试;鉴权、参数与安全错误不会重试。
21
+ ## Configuration and model metadata / 配置与模型元数据
22
22
 
23
- Use `aicommit doctor -p provider-name` to verify the selected adapter and live endpoint. Reuse a built-in adapter when only setup defaults change, and use `custom` for an OpenAI-compatible endpoint with optional body switches. A protocol requiring a different transport, streaming parser, or credential scheme needs core support.
23
+ - `apiUrl` is still the **complete endpoint**, not a base URL. Proxy paths and query parameters are preserved. Requests use only the resolved AICommit credential. Pi environment-key discovery and OAuth are not invoked, and redirects are rejected.
24
+ - `modelId` need not exist in Pi's catalog. Known OpenAI, DeepSeek, and OpenRouter models use the bundled metadata; unknown IDs retain a compatible fallback. No online model discovery runs during setup or generation.
25
+ - `reasoning.mode: auto` preserves server defaults and explicit `extraBody`. `on` / `off` applies the selected mode after extras. Setup filters known supported effort levels. DeepSeek's legacy unsupported effort values are normalized by Pi: for the pinned V4 Flash catalog, `medium` becomes `high`, and `xhigh` becomes `max`.
26
+ - Pi requests SSE by default, even when the CLI does not display reasoning. Complete JSON responses are bridged into Pi events. Set `extraBody: { "stream": false }` for endpoints that reject streaming requests; streaming-only options are removed automatically.
27
+ - Native Ollama remains non-streaming. `/api/generate` receives `system` and `prompt`, while `/api/chat` receives `messages`; existing `options` are retained.
24
28
 
25
- 使用 `aicommit doctor -p provider-name` 校验所选 adapter 与在线端点。若只改变 setup 默认值,应复用内置 adapter;OpenAI-compatible endpoint 及少量 body 开关使用 `custom`。需要不同传输、流解析或鉴权方案的协议必须由核心直接支持。
29
+ 对应行为:
30
+
31
+ - `apiUrl` 仍填写**完整接口地址**,代理路径与查询参数会保留。鉴权只使用 AICommit 已解析的凭据,不调用 Pi 的环境变量凭据发现或 OAuth,也不跟随重定向。
32
+ - Pi 目录中没有的 `modelId` 也可以配置;已知 OpenAI、DeepSeek、OpenRouter 模型使用随依赖发布的元数据,未知模型走兼容路径。setup 与生成过程不在线拉取模型目录。
33
+ - `reasoning.mode: auto` 保留服务端默认值及显式 `extraBody`;`on` / `off` 在 extras 之后应用。setup 根据已知能力过滤强度。DeepSeek 的旧配置由 Pi 归一:当前 V4 Flash 目录中 `medium` 映射为 `high`,`xhigh` 映射为 `max`。
34
+ - Pi 默认请求 SSE,包括终端不展示推理的场景;完整 JSON 响应通过桥接交给 Pi。若服务拒绝流式请求,可配置 `extraBody: { "stream": false }`,流式专用参数会自动移除。
35
+ - Ollama 原生端点继续使用非流式响应,保留 `options`;`/api/generate` 使用 `system` / `prompt`,`/api/chat` 使用 `messages`。
36
+
37
+ ## Result and retry contract / 结果与重试契约
38
+
39
+ Callers receive `content`, optional `reasoning`, normalized usage, finish reason, capabilities, attempts, and latency. Cached input tokens are included once in `inputTokens`; reasoning tokens are already part of output usage. `piMessage` exposes Pi's normalized assistant result. `raw` retains the actual complete JSON response, or a reconstructed Chat Completions result for SSE, preserving `callAPI` compatibility.
40
+
41
+ Retries remain owned by AICommit; Pi and the underlying SDK's automatic retries are disabled. Only 429, selected 5xx, and network failures **before an accepted response** can retry. Accepted-body interruptions, malformed responses, authentication, invalid parameters, and safety failures are never automatically replayed. Oversized `Retry-After` fails instead of retrying early.
42
+
43
+ SSE must contain a `finish_reason`. A clean EOF or `[DONE]` alone is rejected, and partial content is not returned as a successful generation. Token-limit aliases (`max_tokens`, `max_output_tokens`, `token_limit`) are normalized to `length` before Pi so recovery can run. Textual `reasoning_details`, including legacy shapes, are combined with ordinary reasoning deltas in arrival order. Duplicate representations within one event are emitted once; repeated text in later events is retained. Encrypted metadata remains opaque.
44
+
45
+ 业务仍获得 `content`、可选 `reasoning`、归一 usage、结束原因、能力、尝试次数与耗时。缓存输入 token 只计入一次,推理 token 已包含在输出中。`piMessage` 提供 Pi 的统一 assistant 结果;完整 JSON 的 `raw` 保留原响应,SSE 的 `raw` 则重建兼容 Chat Completions 结构。
46
+
47
+ 重试由 AICommit 负责,Pi 与底层 SDK 的自动重试均已关闭。只有 429、部分 5xx,以及**收到成功响应前**的网络失败可重试;已接受请求后的响应中断、格式错误、鉴权、参数及安全错误不会自动重放。超过上限的 `Retry-After` 会直接报错,不提前重试。
48
+
49
+ SSE 必须带 `finish_reason`。只有 EOF 或 `[DONE]` 时会拒绝结果,不将半截内容当作成功生成。输出上限别名(`max_tokens`、`max_output_tokens`、`token_limit`)在进入 Pi 前归一为 `length`,保留补全恢复流程。`reasoning_details`(含旧格式)中的文本与普通推理分片按到达顺序合并;同一事件中的重复表示只展示一次,后续事件中重复出现的文本则保留。加密元数据不会作为推理文本输出。
50
+
51
+ Use `aicommit doctor -p provider-name -m model-name` to verify a configured connection. This integration covers the existing six adapter types; installing Pi does **not** automatically expose every Pi provider, OAuth flow, or native Anthropic/Gemini/Responses endpoint. Those protocols require explicit routing and configuration support.
52
+
53
+ 使用 `aicommit doctor -p provider-name -m model-name` 检查配置的连接。本次接入覆盖现有六种适配类型;安装 Pi **不会自动开放**其全部供应商、OAuth 或 Anthropic/Gemini/Responses 原生端点,这些协议需要显式扩展路由与配置。
@@ -33,3 +33,13 @@ JSON 模式保证 stdout 只有一个机器对象,诊断进入 stderr。`error
33
33
  If a failure remains, capture `aicommit doctor --output=json`, Node/Git versions, the error category, and redacted config sources. Never attach a diff, commit message, config file, API key, reasoning trace, or credential-helper output to a public issue.
34
34
 
35
35
  若问题仍未解决,请记录 `aicommit doctor --output=json`、Node/Git 版本、错误分类与脱敏后的配置来源。不要在公开 issue 中附加 diff、commit message、配置文件、API key、reasoning 或 credential-helper 输出。
36
+
37
+ ## Large-change limits / 大变更限制
38
+
39
+ Default `auto` analysis builds a local inventory and selects bounded excerpts without model reduction calls. If a complete split candidate inventory cannot fit one request, stage a smaller logical change or explicitly choose personal `largeChange.strategy: "deep"`. Deep analysis can reach its fixed request (256) or depth (8) limits; increasing token or time budgets does not raise those limits. Token/time limits remain configurable in personal settings. Unknown model token counts use conservative estimates; an oversized request fails before dispatch, and provider-context errors are not blindly replayed.
40
+
41
+ 默认 `auto` 在本地建立清单并选择受限片段,不调用模型递归汇总。完整拆分候选清单放不进一次请求时,请暂存更小的逻辑变更,或明确在个人配置中选择 `largeChange.strategy: "deep"`。深度分析的请求数(256)和汇总层级(8)上限固定,提高 token 或时间预算不会改变它们;token 和时间预算可在个人配置中调整。未知模型采用保守 token 估算,输入估算超限会在发送前失败;Provider 上下文超限不会盲目重试。
42
+
43
+ Text lines over 1 MiB fail explicitly. Large-change hunk plans are unsupported; use file-level split. Metadata-only files remain in the complete plan. Invalid, duplicate, or missing IDs are response-format errors, not automatic catch-all groups.
44
+
45
+ 单行超过 1 MiB 会明确报错。大变更暂不支持 hunk 规划,请使用文件级拆分。仅统计的文件仍纳入完整计划。无效、重复或遗漏 ID 会报响应格式错误,不会自动归入兜底组。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hifullmoon/aicommit",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Safe, local-first AI commit message generator for Git workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -48,6 +48,7 @@
48
48
  "lines": 70
49
49
  },
50
50
  "dependencies": {
51
+ "@earendil-works/pi-ai": "0.85.0",
51
52
  "@inquirer/checkbox": "^4.3.2",
52
53
  "@inquirer/confirm": "^5.1.0",
53
54
  "@inquirer/core": "^10.3.2",
@@ -57,6 +58,7 @@
57
58
  "@inquirer/select": "^4.1.0",
58
59
  "boxen": "^8.0.1",
59
60
  "chalk": "^5.4.0",
61
+ "eventsource-parser": "4.1.0",
60
62
  "ora": "^8.2.0",
61
63
  "wrap-ansi": "^9.0.2"
62
64
  },
@@ -90,7 +92,7 @@
90
92
  }
91
93
  },
92
94
  "engines": {
93
- "node": ">=18"
95
+ "node": ">=22.19.0"
94
96
  },
95
97
  "devDependencies": {
96
98
  "c8": "10.1.3",