@qwen-code/qwen-code 0.15.12-preview.3 → 0.16.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.
- package/bundled/qc-helper/docs/configuration/settings.md +59 -61
- package/bundled/qc-helper/docs/features/_meta.ts +2 -0
- package/bundled/qc-helper/docs/features/approval-mode.md +119 -2
- package/bundled/qc-helper/docs/features/auto-mode.md +263 -0
- package/bundled/qc-helper/docs/features/commands.md +11 -10
- package/bundled/qc-helper/docs/features/skills.md +3 -0
- package/bundled/qc-helper/docs/features/structured-output.md +309 -0
- package/bundled/qc-helper/docs/features/sub-agents.md +47 -5
- package/bundled/qc-helper/docs/qwen-serve.md +134 -10
- package/bundled/review/SKILL.md +12 -3
- package/chunks/{agent-LIAWUWAO.js → agent-K6OWOMBN.js} +15 -17
- package/chunks/{anthropicContentGenerator-4QE6LTVV.js → anthropicContentGenerator-RQJNXJIY.js} +7 -4
- package/chunks/{askUserQuestion-QFSCBTUO.js → askUserQuestion-PQPMPNM3.js} +2 -2
- package/chunks/{ca-S3XJMT6P.js → ca-UZ7BANMN.js} +3 -3
- package/chunks/{chunk-AJSOD5IR.js → chunk-3T4ZT63H.js} +8833 -3600
- package/chunks/{chunk-B7ZL7HUA.js → chunk-4AOCVI6J.js} +2 -1
- package/chunks/{chunk-AOJ3BBY7.js → chunk-4J63U5QO.js} +17 -349
- package/chunks/{chunk-AEJ2DKLP.js → chunk-C6WMLUNB.js} +1 -1
- package/chunks/{chunk-JMZQICAL.js → chunk-CAVZVZX6.js} +2 -2
- package/chunks/{chunk-CAWKL3UC.js → chunk-CSWBPY3P.js} +2 -2
- package/chunks/{chunk-G27O2LD2.js → chunk-D5NTAHYL.js} +1 -1
- package/chunks/{chunk-BXNCPI75.js → chunk-DMIMF3CG.js} +2 -2
- package/chunks/{chunk-OCC4MZRS.js → chunk-F23NCRJ2.js} +1 -1
- package/chunks/{chunk-5QQ5FGTU.js → chunk-G7YTSRES.js} +1 -1
- package/chunks/{chunk-SQNQIOD5.js → chunk-GGNTZ2NH.js} +92 -21
- package/chunks/{chunk-FKVKVE6N.js → chunk-KXZ4TJB4.js} +1 -1
- package/chunks/chunk-L34E6AGL.js +19126 -0
- package/chunks/{chunk-CBVB66WY.js → chunk-L5E26RN6.js} +2 -2
- package/chunks/{chunk-UXW7MYAW.js → chunk-MAY32HXD.js} +376 -1
- package/chunks/{chunk-GC5RXNL2.js → chunk-NOAHME6A.js} +115 -23
- package/chunks/{chunk-CM2IESUE.js → chunk-PR4T27R7.js} +1 -1
- package/chunks/{chunk-FYMSCRHM.js → chunk-PVVL5Q3W.js} +32 -1
- package/chunks/{chunk-YHEAJFCI.js → chunk-USE2VQ5P.js} +3 -0
- package/chunks/chunk-VMOAQVBP.js +379 -0
- package/chunks/{chunk-XLQ4E5PS.js → chunk-WCZWAKFG.js} +795 -142
- package/chunks/{chunk-GJXIKCKL.js → chunk-XP27SJMH.js} +76 -5
- package/chunks/{chunk-TPGOGCWM.js → chunk-YJLGXDQJ.js} +1 -1
- package/chunks/{contextCommand-SVLAZMQL.js → contextCommand-7CPNXBLO.js} +17 -19
- package/chunks/{cron-create-WUTD5ZTH.js → cron-create-IGYXQVG4.js} +28 -2
- package/chunks/{cron-delete-N3UQYCRA.js → cron-delete-ETKIZCWT.js} +2 -2
- package/chunks/{cron-list-Z6RJJ4YH.js → cron-list-BVCUSWRU.js} +2 -2
- package/chunks/{de-MNR4SMAI.js → de-V4IE2OOZ.js} +3 -3
- package/chunks/{dist-RRYNPBOE.js → dist-4L54HRX2.js} +2 -2
- package/chunks/{dist-WP4AH3VK.js → dist-BXDUQ2QY.js} +1 -1
- package/chunks/{dist-M6GFCZ7S.js → dist-MN2PDDPR.js} +1 -1
- package/chunks/{edit-VNAZBIZR.js → edit-CBM5NDVK.js} +28 -18
- package/chunks/{en-NRN4QBAT.js → en-HGJ2SPLM.js} +5 -3
- package/chunks/{enter-worktree-FOF5YZIV.js → enter-worktree-XABKPLO6.js} +41 -17
- package/chunks/{exit-worktree-Y6QVAO3C.js → exit-worktree-56MN2PCL.js} +41 -17
- package/chunks/{exitPlanMode-QZKO7GH7.js → exitPlanMode-YDNPCSCJ.js} +15 -17
- package/chunks/{fr-OFJFHLCR.js → fr-CJULI7ZX.js} +3 -3
- package/chunks/{geminiContentGenerator-DYHZPKJX.js → geminiContentGenerator-ZGPNBFDS.js} +3 -3
- package/chunks/{glob-G7XATELV.js → glob-ZHA35VO5.js} +15 -17
- package/chunks/{grep-4SETMY47.js → grep-RV6V6T52.js} +15 -17
- package/chunks/{ja-V6OQ6VL7.js → ja-L7CHRQEW.js} +3 -3
- package/chunks/{keychain-token-storage-DMFP5IJM.js → keychain-token-storage-335UOLJ6.js} +2 -2
- package/chunks/{ls-SUILOZZB.js → ls-7HD6XG3V.js} +3 -3
- package/chunks/{lsp-6TQBWVMZ.js → lsp-ZZSFCIWD.js} +2 -2
- package/chunks/{monitor-JTLJBJ7H.js → monitor-5G2OBGE5.js} +27 -17
- package/chunks/notebook-edit-XUBTCT6L.js +756 -0
- package/chunks/{openaiContentGenerator-3H7XOZBW.js → openaiContentGenerator-POYAZQ6I.js} +12 -11
- package/chunks/{pt-ZLE6SA4A.js → pt-M6JULLEQ.js} +3 -3
- package/chunks/{qwenContentGenerator-FAU3QPYO.js → qwenContentGenerator-2E4H56DK.js} +17 -19
- package/chunks/{qwenOAuth2-JSQ7EPR3.js → qwenOAuth2-EEJGROP7.js} +9 -3
- package/chunks/{read-file-WWUQVNCZ.js → read-file-3JIOOXFT.js} +7 -8
- package/chunks/{ripGrep-WCOAIWL6.js → ripGrep-LEI3L6PM.js} +15 -17
- package/chunks/{ru-A4OHIUNN.js → ru-QILM4HBC.js} +3 -3
- package/chunks/{send-message-Q2JRAC3J.js → send-message-ULK4MQXJ.js} +23 -2
- package/chunks/{serve-VJEEEXA6.js → serve-CFVRMD4W.js} +8500 -1663
- package/chunks/{shell-IAOKGIJ6.js → shell-3B5DZ437.js} +15 -17
- package/chunks/{skill-NHW6222K.js → skill-STSZUBXR.js} +23 -10
- package/chunks/{src-OWV5HVQQ.js → src-ROFXAPEP.js} +211 -19
- package/chunks/{syntheticOutput-S4DRGMQM.js → syntheticOutput-IS2X5OZ2.js} +3 -3
- package/chunks/{task-stop-7THHVAQS.js → task-stop-7QSJGSSP.js} +2 -2
- package/chunks/{todoWrite-WKUGUTPX.js → todoWrite-7CVACFUX.js} +3 -3
- package/chunks/{tool-search-MSJ6SXLI.js → tool-search-ARWOD3GD.js} +7 -8
- package/chunks/{web-fetch-OZE6ZQUF.js → web-fetch-ENQ2I5JA.js} +7 -4
- package/chunks/{write-file-RKCENFZ5.js → write-file-6MRT7TEW.js} +25 -18
- package/chunks/{zh-RN3JULHO.js → zh-PWL2NKY3.js} +5 -3
- package/chunks/{zh-TW-XZEHEV5S.js → zh-TW-S3YGWICZ.js} +5 -3
- package/cli.js +58070 -75930
- package/locales/ca.js +4 -5
- package/locales/de.js +4 -5
- package/locales/en.js +8 -5
- package/locales/fr.js +4 -5
- package/locales/ja.js +4 -5
- package/locales/pt.js +4 -5
- package/locales/ru.js +4 -5
- package/locales/zh-TW.js +6 -4
- package/locales/zh.js +6 -4
- package/package.json +2 -2
- package/chunks/chunk-5P5XGNYH.js +0 -93
- package/chunks/chunk-SYCJMSIJ.js +0 -82
- package/chunks/chunk-Y6Z2O3WR.js +0 -33
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
StructuredToolError
|
|
5
|
+
} from "./chunk-L5E26RN6.js";
|
|
6
|
+
import {
|
|
7
|
+
CommitAttributionService,
|
|
8
|
+
DEFAULT_DIFF_OPTIONS,
|
|
9
|
+
createPatch,
|
|
10
|
+
detectLineEnding,
|
|
11
|
+
getDiffStat
|
|
12
|
+
} from "./chunk-3T4ZT63H.js";
|
|
13
|
+
import "./chunk-K5PGHDBN.js";
|
|
14
|
+
import "./chunk-O4PICXES.js";
|
|
15
|
+
import "./chunk-TW522KN6.js";
|
|
16
|
+
import "./chunk-MLZQVCF3.js";
|
|
17
|
+
import "./chunk-CAVZVZX6.js";
|
|
18
|
+
import "./chunk-G7YTSRES.js";
|
|
19
|
+
import "./chunk-4AOCVI6J.js";
|
|
20
|
+
import "./chunk-77WXWU44.js";
|
|
21
|
+
import "./chunk-F23NCRJ2.js";
|
|
22
|
+
import "./chunk-CSWBPY3P.js";
|
|
23
|
+
import {
|
|
24
|
+
FileOperationEvent,
|
|
25
|
+
findCellIndex,
|
|
26
|
+
getCellDisplayId,
|
|
27
|
+
getNotebookLanguage,
|
|
28
|
+
getSpecificMimeType,
|
|
29
|
+
hasStableCellIds,
|
|
30
|
+
inferInsertedCellSourceArrayStyle,
|
|
31
|
+
inferNotebookJsonFormat,
|
|
32
|
+
isAmbiguousCellId,
|
|
33
|
+
logFileOperation,
|
|
34
|
+
makeCellId,
|
|
35
|
+
normalizeEditedCell,
|
|
36
|
+
normalizeSource,
|
|
37
|
+
parseNotebook,
|
|
38
|
+
serializeNotebook,
|
|
39
|
+
toNotebookSource
|
|
40
|
+
} from "./chunk-WCZWAKFG.js";
|
|
41
|
+
import "./chunk-UWCTAVOD.js";
|
|
42
|
+
import "./chunk-OFEVLU4C.js";
|
|
43
|
+
import "./chunk-PR4T27R7.js";
|
|
44
|
+
import "./chunk-MAY32HXD.js";
|
|
45
|
+
import "./chunk-D5NTAHYL.js";
|
|
46
|
+
import "./chunk-T4VD6OJ4.js";
|
|
47
|
+
import "./chunk-RDYWTWEM.js";
|
|
48
|
+
import "./chunk-YJLGXDQJ.js";
|
|
49
|
+
import {
|
|
50
|
+
BaseDeclarativeTool,
|
|
51
|
+
BaseToolInvocation,
|
|
52
|
+
ToolDisplayNames,
|
|
53
|
+
ToolNames
|
|
54
|
+
} from "./chunk-PVVL5Q3W.js";
|
|
55
|
+
import "./chunk-GGNTZ2NH.js";
|
|
56
|
+
import "./chunk-KXZ4TJB4.js";
|
|
57
|
+
import {
|
|
58
|
+
createDebugLogger,
|
|
59
|
+
makeRelative,
|
|
60
|
+
shortenPath,
|
|
61
|
+
unescapePath
|
|
62
|
+
} from "./chunk-XP27SJMH.js";
|
|
63
|
+
import "./chunk-E7E2MFYM.js";
|
|
64
|
+
import "./chunk-ZERZSAZL.js";
|
|
65
|
+
import "./chunk-QN5NZ3UQ.js";
|
|
66
|
+
import "./chunk-BR4QREVK.js";
|
|
67
|
+
import "./chunk-QWSRH265.js";
|
|
68
|
+
import {
|
|
69
|
+
init_esbuild_shims
|
|
70
|
+
} from "./chunk-A4BMJM77.js";
|
|
71
|
+
import {
|
|
72
|
+
__name
|
|
73
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
74
|
+
|
|
75
|
+
// packages/core/src/tools/notebook-edit.ts
|
|
76
|
+
init_esbuild_shims();
|
|
77
|
+
import * as fs from "node:fs";
|
|
78
|
+
import * as path from "node:path";
|
|
79
|
+
var debugLogger = createDebugLogger("NOTEBOOK_EDIT");
|
|
80
|
+
function rejectNotebookPriorRead(notebookPath, reason, decision) {
|
|
81
|
+
debugLogger.debug("prior-read-rejected", {
|
|
82
|
+
path: notebookPath,
|
|
83
|
+
reason,
|
|
84
|
+
type: decision.type,
|
|
85
|
+
displayMessage: decision.displayMessage
|
|
86
|
+
});
|
|
87
|
+
return decision;
|
|
88
|
+
}
|
|
89
|
+
__name(rejectNotebookPriorRead, "rejectNotebookPriorRead");
|
|
90
|
+
var NotebookEditError = class extends Error {
|
|
91
|
+
constructor(message, type) {
|
|
92
|
+
super(message);
|
|
93
|
+
this.type = type;
|
|
94
|
+
this.name = "NotebookEditError";
|
|
95
|
+
}
|
|
96
|
+
static {
|
|
97
|
+
__name(this, "NotebookEditError");
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
function requireNotebookSource(source, mode) {
|
|
101
|
+
if (mode === "delete") {
|
|
102
|
+
return "";
|
|
103
|
+
}
|
|
104
|
+
if (typeof source !== "string") {
|
|
105
|
+
throw new NotebookEditError(
|
|
106
|
+
`new_source is required when edit_mode is "${mode}".`,
|
|
107
|
+
"invalid_tool_params" /* INVALID_TOOL_PARAMS */
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
return source;
|
|
111
|
+
}
|
|
112
|
+
__name(requireNotebookSource, "requireNotebookSource");
|
|
113
|
+
function displayCellId(cell, index) {
|
|
114
|
+
return cell ? getCellDisplayId(cell, index) : `cell-${index}`;
|
|
115
|
+
}
|
|
116
|
+
__name(displayCellId, "displayCellId");
|
|
117
|
+
function resolveTargetIndex(notebook, cellId, mode) {
|
|
118
|
+
if (!cellId) {
|
|
119
|
+
if (mode === "insert") {
|
|
120
|
+
return -1;
|
|
121
|
+
}
|
|
122
|
+
throw new NotebookEditError(
|
|
123
|
+
"cell_id is required for replace and delete operations.",
|
|
124
|
+
"invalid_tool_params" /* INVALID_TOOL_PARAMS */
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if (isAmbiguousCellId(notebook, cellId)) {
|
|
128
|
+
throw new NotebookEditError(
|
|
129
|
+
`Cell ID "${cellId}" is ambiguous in the rendered notebook. Re-read the notebook and target a stable real cell ID before editing.`,
|
|
130
|
+
"invalid_tool_params" /* INVALID_TOOL_PARAMS */
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
const index = findCellIndex(notebook, cellId);
|
|
134
|
+
if (index === -1) {
|
|
135
|
+
throw new NotebookEditError(
|
|
136
|
+
`Cell with ID "${cellId}" not found in notebook.`,
|
|
137
|
+
"notebook_cell_not_found" /* NOTEBOOK_CELL_NOT_FOUND */
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return index;
|
|
141
|
+
}
|
|
142
|
+
__name(resolveTargetIndex, "resolveTargetIndex");
|
|
143
|
+
function createNotebookCell(notebook, cellType, source, preferSourceArray) {
|
|
144
|
+
const cell = {
|
|
145
|
+
cell_type: cellType,
|
|
146
|
+
metadata: {},
|
|
147
|
+
source: toNotebookSource(source, preferSourceArray)
|
|
148
|
+
};
|
|
149
|
+
const id = makeCellId(notebook);
|
|
150
|
+
if (id) {
|
|
151
|
+
cell.id = id;
|
|
152
|
+
}
|
|
153
|
+
normalizeEditedCell(cell, cellType);
|
|
154
|
+
return cell;
|
|
155
|
+
}
|
|
156
|
+
__name(createNotebookCell, "createNotebookCell");
|
|
157
|
+
function applyNotebookEdit(rawContent, params) {
|
|
158
|
+
let notebook;
|
|
159
|
+
try {
|
|
160
|
+
notebook = parseNotebook(rawContent);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
throw new NotebookEditError(
|
|
163
|
+
error instanceof Error ? error.message : String(error),
|
|
164
|
+
"notebook_invalid_json" /* NOTEBOOK_INVALID_JSON */
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
const mode = params.edit_mode ?? "replace";
|
|
168
|
+
const source = requireNotebookSource(params.new_source, mode);
|
|
169
|
+
const originalHasStableCellIds = hasStableCellIds(notebook);
|
|
170
|
+
const targetIndex = resolveTargetIndex(notebook, params.cell_id, mode);
|
|
171
|
+
const language = getNotebookLanguage(notebook);
|
|
172
|
+
const jsonFormat = inferNotebookJsonFormat(rawContent);
|
|
173
|
+
const buildResult = /* @__PURE__ */ __name((updatedNotebook, result) => {
|
|
174
|
+
const structuralEdit = mode === "insert" || mode === "delete";
|
|
175
|
+
return {
|
|
176
|
+
...result,
|
|
177
|
+
updatedContent: serializeNotebook(updatedNotebook, jsonFormat),
|
|
178
|
+
requiresReadAfterWrite: structuralEdit && !(originalHasStableCellIds && hasStableCellIds(updatedNotebook))
|
|
179
|
+
};
|
|
180
|
+
}, "buildResult");
|
|
181
|
+
switch (mode) {
|
|
182
|
+
case "insert": {
|
|
183
|
+
const cellType = params.cell_type ?? "code";
|
|
184
|
+
const insertAt = targetIndex === -1 ? 0 : targetIndex + 1;
|
|
185
|
+
const newCell = createNotebookCell(
|
|
186
|
+
notebook,
|
|
187
|
+
cellType,
|
|
188
|
+
source,
|
|
189
|
+
inferInsertedCellSourceArrayStyle(notebook, insertAt)
|
|
190
|
+
);
|
|
191
|
+
notebook.cells.splice(insertAt, 0, newCell);
|
|
192
|
+
return buildResult(notebook, {
|
|
193
|
+
editedCellId: displayCellId(newCell, insertAt),
|
|
194
|
+
editedCellType: cellType,
|
|
195
|
+
language,
|
|
196
|
+
mode
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
case "delete": {
|
|
200
|
+
const [removed] = notebook.cells.splice(targetIndex, 1);
|
|
201
|
+
return buildResult(notebook, {
|
|
202
|
+
editedCellId: displayCellId(removed, targetIndex),
|
|
203
|
+
editedCellType: removed?.cell_type,
|
|
204
|
+
language,
|
|
205
|
+
mode
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
case "replace": {
|
|
209
|
+
const target = notebook.cells[targetIndex];
|
|
210
|
+
if (!target) {
|
|
211
|
+
throw new NotebookEditError(
|
|
212
|
+
`Cell index ${targetIndex} is out of range.`,
|
|
213
|
+
"notebook_cell_not_found" /* NOTEBOOK_CELL_NOT_FOUND */
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
const finalType = params.cell_type ?? target.cell_type;
|
|
217
|
+
target.source = toNotebookSource(source, Array.isArray(target.source));
|
|
218
|
+
normalizeEditedCell(target, finalType);
|
|
219
|
+
return buildResult(notebook, {
|
|
220
|
+
editedCellId: displayCellId(target, targetIndex),
|
|
221
|
+
editedCellType: finalType,
|
|
222
|
+
language,
|
|
223
|
+
mode
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
default:
|
|
227
|
+
throw new NotebookEditError(
|
|
228
|
+
`Unsupported notebook edit mode: ${mode}`,
|
|
229
|
+
"invalid_tool_params" /* INVALID_TOOL_PARAMS */
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
__name(applyNotebookEdit, "applyNotebookEdit");
|
|
234
|
+
function prepareModifiedNotebookContent(originalContent, modifiedContent, params) {
|
|
235
|
+
let notebook;
|
|
236
|
+
let originalNotebook;
|
|
237
|
+
try {
|
|
238
|
+
notebook = parseNotebook(modifiedContent);
|
|
239
|
+
originalNotebook = parseNotebook(originalContent);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
throw new NotebookEditError(
|
|
242
|
+
error instanceof Error ? error.message : String(error),
|
|
243
|
+
"notebook_invalid_json" /* NOTEBOOK_INVALID_JSON */
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
updatedContent: modifiedContent,
|
|
248
|
+
editedCellId: params.cell_id ?? "user-modified-notebook",
|
|
249
|
+
editedCellType: void 0,
|
|
250
|
+
language: getNotebookLanguage(notebook),
|
|
251
|
+
mode: params.edit_mode ?? "replace",
|
|
252
|
+
requiresReadAfterWrite: !hasStableCellIds(originalNotebook) || !hasStableCellIds(notebook)
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
__name(prepareModifiedNotebookContent, "prepareModifiedNotebookContent");
|
|
256
|
+
async function checkPriorNotebookRead(config, notebookPath, options = {}) {
|
|
257
|
+
if (config.getFileReadCacheDisabled()) {
|
|
258
|
+
return { ok: true };
|
|
259
|
+
}
|
|
260
|
+
let stats;
|
|
261
|
+
try {
|
|
262
|
+
stats = await fs.promises.stat(notebookPath);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
const code = error?.code;
|
|
265
|
+
if (code === "ENOENT") {
|
|
266
|
+
if (options.expectExisting) {
|
|
267
|
+
return rejectNotebookPriorRead(notebookPath, "missing-after-read", {
|
|
268
|
+
ok: false,
|
|
269
|
+
type: "file_changed_since_read" /* FILE_CHANGED_SINCE_READ */,
|
|
270
|
+
rawMessage: `Notebook ${notebookPath} disappeared after it was read. Re-read it with the ${ToolNames.READ_FILE} tool before editing it.`,
|
|
271
|
+
displayMessage: `notebook disappeared after last read; re-run ${ToolNames.READ_FILE} first.`
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return { ok: true };
|
|
275
|
+
}
|
|
276
|
+
return rejectNotebookPriorRead(notebookPath, "stat-failed", {
|
|
277
|
+
ok: false,
|
|
278
|
+
type: "prior_read_verification_failed" /* PRIOR_READ_VERIFICATION_FAILED */,
|
|
279
|
+
rawMessage: `Could not stat ${notebookPath} to verify prior notebook read (${code ?? "unknown error"}). Re-read it with the ${ToolNames.READ_FILE} tool before editing it.`,
|
|
280
|
+
displayMessage: `cannot verify prior read of ${notebookPath}; re-run ${ToolNames.READ_FILE} before editing this notebook.`
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (stats.isDirectory()) {
|
|
284
|
+
return rejectNotebookPriorRead(notebookPath, "target-is-directory", {
|
|
285
|
+
ok: false,
|
|
286
|
+
type: "target_is_directory" /* TARGET_IS_DIRECTORY */,
|
|
287
|
+
rawMessage: `${notebookPath} is a directory. The NotebookEdit tool only operates on .ipynb files.`,
|
|
288
|
+
displayMessage: "path is a directory; cannot edit as a notebook."
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
if (!stats.isFile()) {
|
|
292
|
+
return rejectNotebookPriorRead(notebookPath, "target-not-regular-file", {
|
|
293
|
+
ok: false,
|
|
294
|
+
type: "target_not_regular_file" /* TARGET_NOT_REGULAR_FILE */,
|
|
295
|
+
rawMessage: `${notebookPath} is not a regular file. The NotebookEdit tool only operates on .ipynb files.`,
|
|
296
|
+
displayMessage: "special file; cannot edit as a notebook."
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
const status = config.getFileReadCache().check(stats);
|
|
300
|
+
if (status.state === "fresh" && status.entry.lastReadAt !== void 0 && status.entry.lastReadWasFull) {
|
|
301
|
+
return { ok: true };
|
|
302
|
+
}
|
|
303
|
+
if (status.state === "fresh" && status.entry.lastReadAt !== void 0 && !status.entry.lastReadWasFull) {
|
|
304
|
+
return rejectNotebookPriorRead(notebookPath, "truncated-cache-entry", {
|
|
305
|
+
ok: false,
|
|
306
|
+
type: "edit_requires_prior_read" /* EDIT_REQUIRES_PRIOR_READ */,
|
|
307
|
+
rawMessage: `Notebook ${notebookPath} is too large for cell-level editing because its rendered output was truncated when read. Reduce the notebook output size or split the notebook before editing cells.`,
|
|
308
|
+
displayMessage: "notebook too large for cell-level editing."
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
if (status.state === "stale") {
|
|
312
|
+
return rejectNotebookPriorRead(notebookPath, "stale-cache-entry", {
|
|
313
|
+
ok: false,
|
|
314
|
+
type: "file_changed_since_read" /* FILE_CHANGED_SINCE_READ */,
|
|
315
|
+
rawMessage: `Notebook ${notebookPath} has been modified since you last read it. Re-read it with the ${ToolNames.READ_FILE} tool before editing it.`,
|
|
316
|
+
displayMessage: `notebook changed since last read; re-run ${ToolNames.READ_FILE} first.`
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return rejectNotebookPriorRead(notebookPath, `cache-${status.state}`, {
|
|
320
|
+
ok: false,
|
|
321
|
+
type: "edit_requires_prior_read" /* EDIT_REQUIRES_PRIOR_READ */,
|
|
322
|
+
rawMessage: `Notebook ${notebookPath} has not been fully read in this session. Use the ${ToolNames.READ_FILE} tool first, without offset or limit, before editing cells.`,
|
|
323
|
+
displayMessage: `${ToolNames.READ_FILE} required before editing this notebook.`
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
__name(checkPriorNotebookRead, "checkPriorNotebookRead");
|
|
327
|
+
var NotebookEditInvocation = class extends BaseToolInvocation {
|
|
328
|
+
constructor(config, params, modifyMetadata) {
|
|
329
|
+
super(params);
|
|
330
|
+
this.config = config;
|
|
331
|
+
this.modifyMetadata = modifyMetadata;
|
|
332
|
+
}
|
|
333
|
+
static {
|
|
334
|
+
__name(this, "NotebookEditInvocation");
|
|
335
|
+
}
|
|
336
|
+
toolLocations() {
|
|
337
|
+
return [{ path: this.params.notebook_path }];
|
|
338
|
+
}
|
|
339
|
+
getDescription() {
|
|
340
|
+
const relativePath = makeRelative(
|
|
341
|
+
this.params.notebook_path,
|
|
342
|
+
this.config.getTargetDir()
|
|
343
|
+
);
|
|
344
|
+
const mode = this.params.edit_mode ?? "replace";
|
|
345
|
+
const cell = this.params.cell_id ?? "beginning";
|
|
346
|
+
return `${mode} notebook cell ${cell} in ${shortenPath(relativePath)}`;
|
|
347
|
+
}
|
|
348
|
+
async getDefaultPermission() {
|
|
349
|
+
return "ask";
|
|
350
|
+
}
|
|
351
|
+
async getConfirmationDetails(abortSignal) {
|
|
352
|
+
const prepared = await this.prepareEdit(abortSignal);
|
|
353
|
+
const fileName = path.basename(this.params.notebook_path);
|
|
354
|
+
const fileDiff = createPatch(
|
|
355
|
+
fileName,
|
|
356
|
+
prepared.originalContent,
|
|
357
|
+
prepared.updatedContent,
|
|
358
|
+
"Current",
|
|
359
|
+
"Proposed",
|
|
360
|
+
DEFAULT_DIFF_OPTIONS
|
|
361
|
+
);
|
|
362
|
+
const confirmationDetails = {
|
|
363
|
+
type: "edit",
|
|
364
|
+
title: `Confirm Notebook Edit: ${shortenPath(makeRelative(this.params.notebook_path, this.config.getTargetDir()))}`,
|
|
365
|
+
fileName,
|
|
366
|
+
filePath: this.params.notebook_path,
|
|
367
|
+
fileDiff,
|
|
368
|
+
originalContent: prepared.originalContent,
|
|
369
|
+
newContent: prepared.updatedContent,
|
|
370
|
+
onConfirm: /* @__PURE__ */ __name(async (outcome) => {
|
|
371
|
+
if (outcome === "proceed_always" /* ProceedAlways */) {
|
|
372
|
+
this.config.setApprovalMode("auto-edit" /* AUTO_EDIT */);
|
|
373
|
+
}
|
|
374
|
+
}, "onConfirm")
|
|
375
|
+
};
|
|
376
|
+
return confirmationDetails;
|
|
377
|
+
}
|
|
378
|
+
async prepareEdit(abortSignal) {
|
|
379
|
+
const preDecision = await checkPriorNotebookRead(
|
|
380
|
+
this.config,
|
|
381
|
+
this.params.notebook_path
|
|
382
|
+
);
|
|
383
|
+
if (!preDecision.ok) {
|
|
384
|
+
throw new StructuredToolError(preDecision.rawMessage, preDecision.type);
|
|
385
|
+
}
|
|
386
|
+
let originalContent;
|
|
387
|
+
let bom = false;
|
|
388
|
+
let encoding;
|
|
389
|
+
let lineEnding = "lf";
|
|
390
|
+
try {
|
|
391
|
+
const fileInfo = await this.config.getFileSystemService().readTextFile({
|
|
392
|
+
path: this.params.notebook_path
|
|
393
|
+
});
|
|
394
|
+
originalContent = fileInfo.content;
|
|
395
|
+
bom = fileInfo._meta?.bom ?? false;
|
|
396
|
+
encoding = fileInfo._meta?.encoding;
|
|
397
|
+
lineEnding = fileInfo._meta?.lineEnding ?? detectLineEnding(fileInfo.content);
|
|
398
|
+
} catch (error) {
|
|
399
|
+
if (abortSignal.aborted) {
|
|
400
|
+
throw error;
|
|
401
|
+
}
|
|
402
|
+
const code = error?.code;
|
|
403
|
+
if (code === "ENOENT") {
|
|
404
|
+
throw new StructuredToolError(
|
|
405
|
+
`Notebook file not found: ${this.params.notebook_path}`,
|
|
406
|
+
"file_not_found" /* FILE_NOT_FOUND */
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
throw new StructuredToolError(
|
|
410
|
+
`Error reading notebook: ${error instanceof Error ? error.message : String(error)}`,
|
|
411
|
+
"read_content_failure" /* READ_CONTENT_FAILURE */
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
const postDecision = await checkPriorNotebookRead(
|
|
415
|
+
this.config,
|
|
416
|
+
this.params.notebook_path,
|
|
417
|
+
{ expectExisting: true }
|
|
418
|
+
);
|
|
419
|
+
if (!postDecision.ok) {
|
|
420
|
+
throw new StructuredToolError(postDecision.rawMessage, postDecision.type);
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
if (this.modifyMetadata?.modifiedNotebookContent !== void 0) {
|
|
424
|
+
return {
|
|
425
|
+
...prepareModifiedNotebookContent(
|
|
426
|
+
originalContent,
|
|
427
|
+
this.modifyMetadata.modifiedNotebookContent,
|
|
428
|
+
this.params
|
|
429
|
+
),
|
|
430
|
+
originalContent,
|
|
431
|
+
bom,
|
|
432
|
+
encoding,
|
|
433
|
+
lineEnding
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
...applyNotebookEdit(originalContent, this.params),
|
|
438
|
+
originalContent,
|
|
439
|
+
bom,
|
|
440
|
+
encoding,
|
|
441
|
+
lineEnding
|
|
442
|
+
};
|
|
443
|
+
} catch (error) {
|
|
444
|
+
if (error instanceof NotebookEditError) {
|
|
445
|
+
throw new StructuredToolError(error.message, error.type);
|
|
446
|
+
}
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async execute(signal) {
|
|
451
|
+
let prepared;
|
|
452
|
+
try {
|
|
453
|
+
prepared = await this.prepareEdit(signal);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
if (signal.aborted) {
|
|
456
|
+
throw error;
|
|
457
|
+
}
|
|
458
|
+
const errorType = error instanceof StructuredToolError ? error.errorType : "notebook_edit_failure" /* NOTEBOOK_EDIT_FAILURE */;
|
|
459
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
460
|
+
return {
|
|
461
|
+
llmContent: message,
|
|
462
|
+
returnDisplay: `Error: ${message}`,
|
|
463
|
+
error: {
|
|
464
|
+
message,
|
|
465
|
+
type: errorType
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
try {
|
|
471
|
+
await this.config.getFileHistoryService().trackEdit(this.params.notebook_path);
|
|
472
|
+
} catch {
|
|
473
|
+
}
|
|
474
|
+
const writeDecision = await checkPriorNotebookRead(
|
|
475
|
+
this.config,
|
|
476
|
+
this.params.notebook_path,
|
|
477
|
+
{ expectExisting: true }
|
|
478
|
+
);
|
|
479
|
+
if (!writeDecision.ok) {
|
|
480
|
+
return {
|
|
481
|
+
llmContent: writeDecision.rawMessage,
|
|
482
|
+
returnDisplay: `Error: ${writeDecision.displayMessage}`,
|
|
483
|
+
error: {
|
|
484
|
+
message: writeDecision.rawMessage,
|
|
485
|
+
type: writeDecision.type
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
await this.config.getFileSystemService().writeTextFile({
|
|
490
|
+
path: this.params.notebook_path,
|
|
491
|
+
content: prepared.updatedContent,
|
|
492
|
+
_meta: {
|
|
493
|
+
bom: prepared.bom,
|
|
494
|
+
encoding: prepared.encoding,
|
|
495
|
+
lineEnding: prepared.lineEnding
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
if (!this.modifyMetadata?.modifiedByUser) {
|
|
499
|
+
CommitAttributionService.getInstance().recordEdit(
|
|
500
|
+
this.params.notebook_path,
|
|
501
|
+
prepared.originalContent,
|
|
502
|
+
prepared.updatedContent
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
const postWriteStats = fs.statSync(this.params.notebook_path);
|
|
507
|
+
const cache = this.config.getFileReadCache();
|
|
508
|
+
if (prepared.requiresReadAfterWrite) {
|
|
509
|
+
cache.invalidate(postWriteStats);
|
|
510
|
+
} else {
|
|
511
|
+
cache.recordWrite(this.params.notebook_path, postWriteStats, {
|
|
512
|
+
cacheable: false
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
} catch (error) {
|
|
516
|
+
debugLogger.warn(
|
|
517
|
+
`[NotebookEdit] post-write cache update failed for ${this.params.notebook_path}: ${error instanceof Error ? error.message : String(error)}`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
const fileName = path.basename(this.params.notebook_path);
|
|
521
|
+
const fileDiff = createPatch(
|
|
522
|
+
fileName,
|
|
523
|
+
prepared.originalContent,
|
|
524
|
+
prepared.updatedContent,
|
|
525
|
+
"Current",
|
|
526
|
+
"Proposed",
|
|
527
|
+
DEFAULT_DIFF_OPTIONS
|
|
528
|
+
);
|
|
529
|
+
const diffStat = getDiffStat(
|
|
530
|
+
fileName,
|
|
531
|
+
prepared.originalContent,
|
|
532
|
+
this.modifyMetadata?.aiProposedContent ?? prepared.updatedContent,
|
|
533
|
+
prepared.updatedContent
|
|
534
|
+
);
|
|
535
|
+
logFileOperation(
|
|
536
|
+
this.config,
|
|
537
|
+
new FileOperationEvent(
|
|
538
|
+
NotebookEditTool.Name,
|
|
539
|
+
"update" /* UPDATE */,
|
|
540
|
+
prepared.updatedContent.split("\n").length,
|
|
541
|
+
getSpecificMimeType(this.params.notebook_path),
|
|
542
|
+
".ipynb",
|
|
543
|
+
prepared.language
|
|
544
|
+
)
|
|
545
|
+
);
|
|
546
|
+
const displayResult = {
|
|
547
|
+
fileDiff,
|
|
548
|
+
fileName,
|
|
549
|
+
originalContent: prepared.originalContent,
|
|
550
|
+
newContent: prepared.updatedContent,
|
|
551
|
+
diffStat
|
|
552
|
+
};
|
|
553
|
+
const llmContent = this.modifyMetadata?.modifiedNotebookContent !== void 0 ? `Notebook ${this.params.notebook_path} has been updated. Notebook content was modified by the user before approval; the final saved notebook may differ from the original ${prepared.mode} cell ${prepared.editedCellId} proposal.` : `Notebook ${this.params.notebook_path} has been updated. ${prepared.mode} cell ${prepared.editedCellId}.${prepared.mode === "delete" ? "" : `
|
|
554
|
+
|
|
555
|
+
Updated source:
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
${normalizeSource(this.params.new_source ?? "")}`}`;
|
|
560
|
+
return {
|
|
561
|
+
llmContent,
|
|
562
|
+
returnDisplay: displayResult,
|
|
563
|
+
resultFilePaths: [this.params.notebook_path]
|
|
564
|
+
};
|
|
565
|
+
} catch (error) {
|
|
566
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
567
|
+
return {
|
|
568
|
+
llmContent: `Error writing notebook: ${message}`,
|
|
569
|
+
returnDisplay: `Error writing notebook: ${message}`,
|
|
570
|
+
error: {
|
|
571
|
+
message,
|
|
572
|
+
type: "file_write_failure" /* FILE_WRITE_FAILURE */
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
var NotebookEditTool = class _NotebookEditTool extends BaseDeclarativeTool {
|
|
579
|
+
constructor(config) {
|
|
580
|
+
super(
|
|
581
|
+
_NotebookEditTool.Name,
|
|
582
|
+
ToolDisplayNames.NOTEBOOK_EDIT,
|
|
583
|
+
`Edits a Jupyter notebook (.ipynb) safely at the cell level. Use this instead of ${ToolNames.EDIT} or ${ToolNames.WRITE_FILE} for notebook cells. Supports replacing, inserting, and deleting cells. Always read the notebook first with ${ToolNames.READ_FILE}; then use the cell IDs shown in that output.`,
|
|
584
|
+
"edit" /* Edit */,
|
|
585
|
+
{
|
|
586
|
+
properties: {
|
|
587
|
+
notebook_path: {
|
|
588
|
+
description: "Absolute path to the Jupyter notebook file to edit. Must end with .ipynb.",
|
|
589
|
+
type: "string"
|
|
590
|
+
},
|
|
591
|
+
cell_id: {
|
|
592
|
+
description: "Target cell ID from read_file output, or cell-N 0-based fallback. Required for replace and delete. For insert, the new cell is inserted after this cell; if omitted, inserted at the beginning.",
|
|
593
|
+
type: "string"
|
|
594
|
+
},
|
|
595
|
+
new_source: {
|
|
596
|
+
description: "New source content for replace and insert operations. Not required for delete.",
|
|
597
|
+
type: "string"
|
|
598
|
+
},
|
|
599
|
+
cell_type: {
|
|
600
|
+
description: "Cell type for inserted cells or type conversion on replace.",
|
|
601
|
+
type: "string",
|
|
602
|
+
enum: ["code", "markdown"]
|
|
603
|
+
},
|
|
604
|
+
edit_mode: {
|
|
605
|
+
description: "Notebook edit operation. Defaults to replace.",
|
|
606
|
+
type: "string",
|
|
607
|
+
enum: ["replace", "insert", "delete"]
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
required: ["notebook_path"],
|
|
611
|
+
additionalProperties: false,
|
|
612
|
+
type: "object"
|
|
613
|
+
}
|
|
614
|
+
);
|
|
615
|
+
this.config = config;
|
|
616
|
+
}
|
|
617
|
+
static {
|
|
618
|
+
__name(this, "NotebookEditTool");
|
|
619
|
+
}
|
|
620
|
+
static Name = ToolNames.NOTEBOOK_EDIT;
|
|
621
|
+
modifyMetadataByParams = /* @__PURE__ */ new WeakMap();
|
|
622
|
+
modifyMetadataByKey = /* @__PURE__ */ new Map();
|
|
623
|
+
validateToolParamValues(params) {
|
|
624
|
+
params.notebook_path = unescapePath(params.notebook_path.trim());
|
|
625
|
+
if (!params.notebook_path) {
|
|
626
|
+
return "The 'notebook_path' parameter must be non-empty.";
|
|
627
|
+
}
|
|
628
|
+
if (!path.isAbsolute(params.notebook_path)) {
|
|
629
|
+
return `Notebook path must be absolute: ${params.notebook_path}`;
|
|
630
|
+
}
|
|
631
|
+
if (path.extname(params.notebook_path).toLowerCase() !== ".ipynb") {
|
|
632
|
+
return "File must be a Jupyter notebook (.ipynb). Use the edit tool for other file types.";
|
|
633
|
+
}
|
|
634
|
+
const mode = params.edit_mode ?? "replace";
|
|
635
|
+
if (!["replace", "insert", "delete"].includes(mode)) {
|
|
636
|
+
return "edit_mode must be 'replace', 'insert', or 'delete'.";
|
|
637
|
+
}
|
|
638
|
+
if (params.cell_type && !["code", "markdown"].includes(params.cell_type)) {
|
|
639
|
+
return "cell_type must be 'code' or 'markdown'.";
|
|
640
|
+
}
|
|
641
|
+
if (mode !== "insert" && !params.cell_id) {
|
|
642
|
+
return "cell_id is required for replace and delete operations.";
|
|
643
|
+
}
|
|
644
|
+
if (mode !== "delete" && typeof params.new_source !== "string") {
|
|
645
|
+
return `new_source is required when edit_mode is "${mode}".`;
|
|
646
|
+
}
|
|
647
|
+
const fileService = this.config.getFileService();
|
|
648
|
+
if (fileService.shouldQwenIgnoreFile(params.notebook_path)) {
|
|
649
|
+
return `File path '${params.notebook_path}' is ignored by .qwenignore pattern(s).`;
|
|
650
|
+
}
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
createInvocation(params) {
|
|
654
|
+
return new NotebookEditInvocation(
|
|
655
|
+
this.config,
|
|
656
|
+
params,
|
|
657
|
+
this.consumeModifyMetadata(params)
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
getModifyMetadataKey(params) {
|
|
661
|
+
return JSON.stringify({
|
|
662
|
+
notebook_path: unescapePath(params.notebook_path.trim()),
|
|
663
|
+
cell_id: params.cell_id,
|
|
664
|
+
new_source: params.new_source,
|
|
665
|
+
cell_type: params.cell_type,
|
|
666
|
+
edit_mode: params.edit_mode
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
rememberModifyMetadata(params, metadata) {
|
|
670
|
+
this.modifyMetadataByParams.set(params, metadata);
|
|
671
|
+
const key = this.getModifyMetadataKey(params);
|
|
672
|
+
const queue = this.modifyMetadataByKey.get(key) ?? [];
|
|
673
|
+
queue.push(metadata);
|
|
674
|
+
this.modifyMetadataByKey.set(key, queue);
|
|
675
|
+
}
|
|
676
|
+
consumeModifyMetadata(params) {
|
|
677
|
+
const metadata = this.modifyMetadataByParams.get(params);
|
|
678
|
+
if (metadata) {
|
|
679
|
+
this.modifyMetadataByParams.delete(params);
|
|
680
|
+
this.removeQueuedModifyMetadata(params, metadata);
|
|
681
|
+
return metadata;
|
|
682
|
+
}
|
|
683
|
+
const key = this.getModifyMetadataKey(params);
|
|
684
|
+
const queue = this.modifyMetadataByKey.get(key);
|
|
685
|
+
const queuedMetadata = queue?.shift();
|
|
686
|
+
if (queue && queue.length === 0) {
|
|
687
|
+
this.modifyMetadataByKey.delete(key);
|
|
688
|
+
}
|
|
689
|
+
return queuedMetadata;
|
|
690
|
+
}
|
|
691
|
+
removeQueuedModifyMetadata(params, metadata) {
|
|
692
|
+
const key = this.getModifyMetadataKey(params);
|
|
693
|
+
const queue = this.modifyMetadataByKey.get(key);
|
|
694
|
+
if (!queue) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const index = queue.indexOf(metadata);
|
|
698
|
+
if (index !== -1) {
|
|
699
|
+
queue.splice(index, 1);
|
|
700
|
+
}
|
|
701
|
+
if (queue.length === 0) {
|
|
702
|
+
this.modifyMetadataByKey.delete(key);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
getModifyContext(_abortSignal) {
|
|
706
|
+
const currentContentSnapshots = /* @__PURE__ */ new Map();
|
|
707
|
+
const readCurrentContentSnapshot = /* @__PURE__ */ __name(async (params) => {
|
|
708
|
+
const cached = currentContentSnapshots.get(params.notebook_path);
|
|
709
|
+
if (cached !== void 0) {
|
|
710
|
+
return cached;
|
|
711
|
+
}
|
|
712
|
+
const { content } = await this.config.getFileSystemService().readTextFile({ path: params.notebook_path });
|
|
713
|
+
currentContentSnapshots.set(params.notebook_path, content);
|
|
714
|
+
return content;
|
|
715
|
+
}, "readCurrentContentSnapshot");
|
|
716
|
+
return {
|
|
717
|
+
getFilePath: /* @__PURE__ */ __name((params) => params.notebook_path, "getFilePath"),
|
|
718
|
+
getCurrentContent: /* @__PURE__ */ __name(async (params) => readCurrentContentSnapshot(params), "getCurrentContent"),
|
|
719
|
+
getProposedContent: /* @__PURE__ */ __name(async (params) => {
|
|
720
|
+
const content = await readCurrentContentSnapshot(params);
|
|
721
|
+
return applyNotebookEdit(content, params).updatedContent;
|
|
722
|
+
}, "getProposedContent"),
|
|
723
|
+
createUpdatedParams: /* @__PURE__ */ __name((oldContent, modifiedProposedContent, originalParams) => {
|
|
724
|
+
let aiProposedContent = this.modifyMetadataByParams.get(originalParams)?.aiProposedContent;
|
|
725
|
+
if (aiProposedContent === void 0) {
|
|
726
|
+
try {
|
|
727
|
+
aiProposedContent = applyNotebookEdit(
|
|
728
|
+
oldContent,
|
|
729
|
+
originalParams
|
|
730
|
+
).updatedContent;
|
|
731
|
+
} catch {
|
|
732
|
+
aiProposedContent = modifiedProposedContent;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
const updatedParams = {
|
|
736
|
+
...originalParams
|
|
737
|
+
};
|
|
738
|
+
this.rememberModifyMetadata(updatedParams, {
|
|
739
|
+
aiProposedContent,
|
|
740
|
+
modifiedByUser: true,
|
|
741
|
+
modifiedNotebookContent: modifiedProposedContent
|
|
742
|
+
});
|
|
743
|
+
return updatedParams;
|
|
744
|
+
}, "createUpdatedParams")
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
export {
|
|
749
|
+
NotebookEditTool,
|
|
750
|
+
applyNotebookEdit
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* @license
|
|
754
|
+
* Copyright 2026 Qwen Team
|
|
755
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
756
|
+
*/
|