Skip to content

Commit 7c7c2d2

Browse files
committed
merge: resolve conflicts with main (drop heap-pressure, adapt to getHistoryShallow)
Main landed #4286 (replace structuredClone with shallow copy) which: - Reverted #4186's heap-pressure auto-compaction safety net (#4286 removed HEAP_PRESSURE_COMPRESSION_RATIO because the underlying OOM cause was fixed by the shallow-copy refactor) - Reverted #4168's consecutiveFailures ladder back to single-shot hasFailedCompressionAttempt - Introduced getHistoryShallow() / peekLastHistoryEntry() to replace structuredClone-based history access - Added a Chinese-language design doc draft for this exact redesign Resolution strategy: - Take OUR redesign everywhere it conflicts: three-tier threshold ladder, consecutiveFailures circuit breaker, hard-rescue, token estimator, hard-rescue debug log, CompressOptions plumbing for pendingUserMessage / precomputedEffectiveTokens / trigger. - DROP all bypassTokenThreshold / heapPressureCompressionCooldownUntil / HEAP_PRESSURE_* / mockGetHeapStatistics / mockHeapPressure code (heap-pressure mechanism is gone on main; we're not reviving it). - Use main's new getHistoryShallow(true) in chatCompressionService and in the hard-tier rescue estimator path (was getHistory(true) before main's refactor; the shallow path is what other compaction call sites now use). - For chatCompressionService.test.ts inline mockChat objects, alias getHistoryShallow to the same vi.fn() as getHistory so existing .mockReturnValue() calls drive both methods. - For the design doc, keep our resolved Open Question 2 closure rationale and prepend the round-2 blockquote clarifying the Background section describes pre-redesign behavior; take main's slightly more thorough SUMMARY_RESERVE paragraph where it explains both with/without-thinking cases. - Replace the round-2 test that asserted "hard-rescue forwards consecutiveFailures=3" with a test compatible with the post-merge history-access shape (now using getHistoryShallow). 346 core tests passing; CLI typecheck clean for affected files. Pre-existing provider-config typecheck errors from main's #4287 refactor are unrelated to this PR and not touched here.
2 parents 1f856ba + 60d8ffa commit 7c7c2d2

215 files changed

Lines changed: 13878 additions & 6067 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/release.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Configuration for GitHub's automatic release notes generation
2+
# PRs with 'skip-changelog' label will be excluded from release notes
3+
changelog:
4+
exclude:
5+
labels:
6+
- 'skip-changelog'

docs/design/auto-compaction-threshold-redesign.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const MAX_CONSECUTIVE_FAILURES = 3; // 失败熔断阈值
7777

7878
数值来源:全部沿用 claude-code 的实测值([autoCompact.ts:30,62-65](src/services/compact/autoCompact.ts:30))。
7979

80-
`SUMMARY_RESERVE = COMPACT_MAX_OUTPUT_TOKENS` 是关键关系:模型受 `maxOutputTokens` 硬限制约束,输出不可能超出 20K,因此 reserve 不需要额外 safety margin。`thinking + summary` 是合并预算(Gemini SDK / 多数 provider 的 `maxOutputTokens` 语义),模型自行在两者间分配。
80+
`SUMMARY_RESERVE = COMPACT_MAX_OUTPUT_TOKENS` 是关键关系:模型受 `maxOutputTokens` 硬限制约束,输出不可能超出 20K,因此 reserve 不需要额外 safety margin。注意:本设计关闭 thinking 后该等式成立(output budget 全部给 summary);若保留 thinking,`thinking + summary` 共享预算(Gemini SDK / 多数 provider 的 `maxOutputTokens` 语义),模型自行在两者间分配,此时 summary 的实际可用空间小于 20K(见「风险与注意事项」第 1、2 条)
8181

8282
## 计算函数
8383

docs/developers/sdk-java.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ The SDK supports different permission modes for controlling tool execution:
144144

145145
- **`default`**: Write tools are denied unless approved via `canUseTool` callback or in `allowedTools`. Read-only tools execute without confirmation.
146146
- **`plan`**: Blocks all write tools, instructing AI to present a plan first.
147-
- **`auto-edit`**: Auto-approve edit tools (edit, write_file) while other tools require confirmation.
147+
- **`auto-edit`**: Auto-approve edit tools (`edit`, `write_file`, `notebook_edit`) while other tools require confirmation.
148148
- **`yolo`**: All tools execute automatically without confirmation.
149149

150150
### Session Event Consumers and Assistant Content Consumers

docs/developers/sdk-typescript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ The SDK supports different permission modes for controlling tool execution:
158158

159159
- **`default`**: Write tools are denied unless approved via `canUseTool` callback or in `allowedTools`. Read-only tools execute without confirmation.
160160
- **`plan`**: Blocks all write tools, instructing AI to present a plan first.
161-
- **`auto-edit`**: Auto-approve edit tools (edit, write_file) while other tools require confirmation.
161+
- **`auto-edit`**: Auto-approve edit tools (`edit`, `write_file`, `notebook_edit`) while other tools require confirmation.
162162
- **`yolo`**: All tools execute automatically without confirmation.
163163

164164
### Permission Priority Chain

docs/developers/tools/file-system.md

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,72 @@ Qwen Code provides a comprehensive suite of tools for interacting with the local
4444
- For other binary files: A message like `Cannot display content of binary file: /path/to/data.bin`.
4545
- **Confirmation:** No.
4646

47-
## 3. `write_file` (WriteFile)
47+
### Jupyter notebook reads
48+
49+
For Jupyter notebooks (`.ipynb`), `read_file` parses the notebook JSON and returns a structured, model-readable notebook view instead of raw JSON. The rendered output includes the notebook language, ordered cells, cell IDs, source, and summarized outputs.
50+
51+
Notebook cells can then be edited with `notebook_edit`. The model should use the cell IDs shown by `read_file` when targeting a cell.
52+
53+
`offset` and `limit` are not supported for `.ipynb` files. Notebook reads are treated as structured full-file reads; if the rendered notebook output is internally truncated because it is too large, `notebook_edit` will reject cell-level edits and ask you to reduce outputs or split the notebook before editing.
54+
55+
## 3. `notebook_edit` (NotebookEdit)
56+
57+
`notebook_edit` edits Jupyter notebook (`.ipynb`) files safely at the cell level. Use it instead of `edit` or `write_file` when changing notebook cells.
58+
59+
- **Tool name:** `notebook_edit`
60+
- **Display name:** NotebookEdit
61+
- **File:** `notebook-edit.ts`
62+
- **Parameters:**
63+
- `notebook_path` (string, required): The absolute path to the `.ipynb` file.
64+
- `cell_id` (string, optional): The target cell ID shown by `read_file`. Required for `replace` and `delete`. For `insert`, the new cell is inserted after this cell; if omitted, the new cell is inserted at the beginning.
65+
- `new_source` (string, optional): The new cell source for `replace` and `insert`. Not required for `delete`.
66+
- `cell_type` (`code` or `markdown`, optional): The cell type for inserted cells, or the target type when replacing a cell.
67+
- `edit_mode` (`replace`, `insert`, or `delete`, optional): The edit operation. Defaults to `replace`.
68+
- **Behavior:**
69+
- Requires the notebook to have been read first with `read_file` in the current session.
70+
- Targets cells using the IDs rendered by `read_file`, including real notebook cell IDs and displayed `cell-N` fallback IDs.
71+
- Rejects ambiguous rendered cell IDs instead of guessing.
72+
- For code cells, clears stale outputs and resets `execution_count` when source changes.
73+
- Preserves notebook JSON formatting, line endings, encoding, and BOM where possible.
74+
- Invalidates the prior-read state after structural edits when displayed fallback IDs can shift, so the next notebook edit requires a fresh `read_file`.
75+
- **Output (`llmContent`):** A success message describing the edited notebook cell and, for non-delete operations, the updated source.
76+
- **Confirmation:** Yes. Shows a notebook JSON diff and asks for user approval before writing, unless the current permission mode or rules auto-approve edit tools.
77+
78+
### `notebook_edit` examples
79+
80+
Replace a code cell:
81+
82+
```
83+
notebook_edit(
84+
notebook_path="/path/to/analysis.ipynb",
85+
cell_id="load-data",
86+
new_source="result = 41 + 1\nprint(result)"
87+
)
88+
```
89+
90+
Insert a markdown cell after an existing cell:
91+
92+
```
93+
notebook_edit(
94+
notebook_path="/path/to/analysis.ipynb",
95+
edit_mode="insert",
96+
cell_id="summary",
97+
cell_type="markdown",
98+
new_source="## Findings\n\nThe cleaned data is ready for modeling."
99+
)
100+
```
101+
102+
Delete a cell:
103+
104+
```
105+
notebook_edit(
106+
notebook_path="/path/to/analysis.ipynb",
107+
edit_mode="delete",
108+
cell_id="old-experiment"
109+
)
110+
```
111+
112+
## 4. `write_file` (WriteFile)
48113

49114
`write_file` writes content to a specified file. If the file exists, it will be overwritten. If the file doesn't exist, it (and any necessary parent directories) will be created.
50115

@@ -56,11 +121,12 @@ Qwen Code provides a comprehensive suite of tools for interacting with the local
56121
- `content` (string, required): The content to write into the file.
57122
- **Behavior:**
58123
- Writes the provided `content` to the `file_path`.
124+
- Does not write raw Jupyter notebook JSON. Use `notebook_edit` for `.ipynb` cell edits.
59125
- Creates parent directories if they don't exist.
60126
- **Output (`llmContent`):** A success message, e.g., `Successfully overwrote file: /path/to/your/file.txt` or `Successfully created and wrote to new file: /path/to/new/file.txt`.
61127
- **Confirmation:** Yes. Shows a diff of changes and asks for user approval before writing.
62128

63-
## 4. `glob` (Glob)
129+
## 5. `glob` (Glob)
64130

65131
`glob` finds files matching specific glob patterns (e.g., `src/**/*.ts`, `*.md`), returning absolute paths sorted by modification time (newest first).
66132

@@ -78,7 +144,7 @@ Qwen Code provides a comprehensive suite of tools for interacting with the local
78144
- **Output (`llmContent`):** A message like: `Found 5 file(s) matching "*.ts" within /path/to/search/dir, sorted by modification time (newest first):\n---\n/path/to/file1.ts\n/path/to/subdir/file2.ts\n---\n[95 files truncated] ...`
79145
- **Confirmation:** No.
80146

81-
## 5. `grep_search` (Grep)
147+
## 6. `grep_search` (Grep)
82148

83149
`grep_search` searches for a regular expression pattern within the content of files in a specified directory. Can filter files by a glob pattern. Returns the lines containing matches, along with their file paths and line numbers.
84150

@@ -131,7 +197,7 @@ Search for a pattern with file filtering and custom result limiting:
131197
grep_search(pattern="function", glob="*.js", limit=10)
132198
```
133199

134-
## 6. `edit` (Edit)
200+
## 7. `edit` (Edit)
135201

136202
`edit` replaces text within a file. By default it requires `old_string` to match a single unique location; set `replace_all` to `true` when you intentionally want to change every occurrence. This tool is designed for precise, targeted changes and requires significant context around the `old_string` to ensure it modifies the correct location.
137203

@@ -148,6 +214,7 @@ grep_search(pattern="function", glob="*.js", limit=10)
148214
- `replace_all` (boolean, optional): Replace all occurrences of `old_string`. Defaults to `false`.
149215

150216
- **Behavior:**
217+
- Does not edit raw Jupyter notebook JSON. Use `notebook_edit` for `.ipynb` cell edits.
151218
- If `old_string` is empty and `file_path` does not exist, creates a new file with `new_string` as content.
152219
- If `old_string` is provided, it reads the `file_path` and attempts to find exactly one occurrence unless `replace_all` is true.
153220
- If the match is unique (or `replace_all` is true), it replaces the text with `new_string`.

0 commit comments

Comments
 (0)