@oh-my-pi/pi-coding-agent 13.0.1 → 13.0.2
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/package.json +7 -7
- package/scripts/format-prompts.ts +33 -3
- package/src/commit/prompts/analysis-system.md +3 -3
- package/src/commit/prompts/changelog-system.md +3 -3
- package/src/commit/prompts/summary-system.md +5 -5
- package/src/extensibility/custom-tools/wrapper.ts +1 -0
- package/src/extensibility/extensions/wrapper.ts +2 -0
- package/src/extensibility/hooks/tool-wrapper.ts +1 -0
- package/src/lsp/index.ts +1 -0
- package/src/patch/diff.ts +2 -2
- package/src/patch/hashline.ts +88 -119
- package/src/patch/index.ts +92 -128
- package/src/patch/shared.ts +17 -23
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/find.md +9 -0
- package/src/prompts/tools/hashline.md +130 -155
- package/src/prompts/tools/task.md +3 -3
- package/src/task/index.ts +1 -0
- package/src/tools/ask.ts +1 -0
- package/src/tools/bash.ts +1 -0
- package/src/tools/browser.ts +1 -0
- package/src/tools/calculator.ts +1 -0
- package/src/tools/cancel-job.ts +1 -0
- package/src/tools/exit-plan-mode.ts +1 -0
- package/src/tools/fetch.ts +1 -0
- package/src/tools/find.ts +1 -0
- package/src/tools/grep.ts +1 -0
- package/src/tools/notebook.ts +1 -0
- package/src/tools/plan-mode-guard.ts +2 -2
- package/src/tools/poll-jobs.ts +1 -0
- package/src/tools/python.ts +1 -0
- package/src/tools/read.ts +1 -0
- package/src/tools/ssh.ts +1 -0
- package/src/tools/submit-result.ts +1 -0
- package/src/tools/todo-write.ts +1 -0
- package/src/tools/write.ts +1 -0
- package/src/web/search/index.ts +1 -0
|
@@ -1,97 +1,115 @@
|
|
|
1
1
|
# Edit
|
|
2
2
|
|
|
3
|
-
Apply precise file edits using `LINE#ID` tags
|
|
3
|
+
Apply precise file edits using `LINE#ID` tags from `read` output.
|
|
4
4
|
|
|
5
5
|
<workflow>
|
|
6
|
-
1. You
|
|
7
|
-
2. You MUST pick the smallest operation per change site
|
|
8
|
-
3. You MUST
|
|
9
|
-
4. You MUST submit one `edit` call per file containing all operations.
|
|
10
|
-
5. If another edit is needed in that file, you MUST re-read first (hashes changed).
|
|
11
|
-
6. You MUST output tool calls only; no prose.
|
|
6
|
+
1. You SHOULD issue a `read` call before editing if you have no tagged context for a file.
|
|
7
|
+
2. You MUST pick the smallest operation per change site.
|
|
8
|
+
3. You MUST submit one `edit` call per file with all operations, think your changes through before submitting.
|
|
12
9
|
</workflow>
|
|
13
10
|
|
|
14
11
|
<operations>
|
|
15
|
-
Every edit has `op`, `
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
Every edit has `op`, `pos`, and `lines`. Range replaces also have `end`. Both `pos` and `end` use `"N#ID"` format (e.g. `"23#XY"`).
|
|
13
|
+
**`pos`** — the anchor line. Meaning depends on `op`:
|
|
14
|
+
- `replace`: start of range (or the single line to replace)
|
|
15
|
+
- `prepend`: insert new lines **before** this line; omit for beginning of file
|
|
16
|
+
- `append`: insert new lines **after** this line; omit for end of file
|
|
17
|
+
**`end`** — range replace only. The last line of the range (inclusive). Omit for single-line replace.
|
|
18
|
+
**`lines`** — the replacement content:
|
|
19
|
+
- `["line1", "line2"]` — replace with these lines (array of strings)
|
|
20
|
+
- `"line1"` — shorthand for `["line1"]` (single-line replace)
|
|
21
|
+
- `[""]` — replace content with a blank line (line preserved, content cleared)
|
|
22
|
+
- `null` or `[]` — **delete** the line(s) entirely
|
|
23
|
+
|
|
24
|
+
### Line or range replace/delete
|
|
25
|
+
- `{ file: "…", edits: [{ op: "replace", pos: "N#ID", lines: null }] }` — delete one line
|
|
26
|
+
- `{ file: "…", edits: [{ op: "replace", pos: "N#ID", end: "M#ID", lines: null }] }` — delete a range
|
|
27
|
+
- `{ file: "…", edits: [{ op: "replace", pos: "N#ID", lines: […] }] }` — replace one line
|
|
28
|
+
- `{ file: "…", edits: [{ op: "replace", pos: "N#ID", end: "M#ID", lines: […] }] }` — replace a range
|
|
29
|
+
|
|
30
|
+
### Insert new lines
|
|
31
|
+
- `{ file: "…", edits: [{ op: "prepend", pos: "N#ID", lines: […] }] }` — insert before tagged line
|
|
32
|
+
- `{ file: "…", edits: [{ op: "prepend", lines: […] }] }` — insert at beginning of file (no tag)
|
|
33
|
+
- `{ file: "…", edits: [{ op: "append", pos: "N#ID", lines: […] }] }` — insert after tagged line
|
|
34
|
+
- `{ file: "…", edits: [{ op: "append", lines: […] }] }` — insert at end of file (no tag)
|
|
35
|
+
|
|
36
|
+
### File-level controls
|
|
37
|
+
- `{ file: "…", delete: true, edits: [] }` — delete the file
|
|
38
|
+
- `{ file: "…", move: "new/path.ts", edits: […] }` — move file to new path (edits applied first)
|
|
39
|
+
**Atomicity:** all ops in one call validate against the same pre-edit snapshot; tags reference the last `read`. Edits are applied bottom-up, so earlier tags stay valid even when later ops add or remove lines.
|
|
28
40
|
</operations>
|
|
29
41
|
|
|
30
42
|
<rules>
|
|
31
|
-
1. **Minimize scope:** You MUST use one logical mutation
|
|
32
|
-
2. **
|
|
33
|
-
3. **Prefer insertion over neighbor rewrites:** You SHOULD anchor on structural boundaries (`}`, `]`, `},`) not interior
|
|
34
|
-
4. **
|
|
35
|
-
5. **Touch only requested code:** You MUST NOT make incidental edits.
|
|
36
|
-
6. **Use exact current tokens:** You MUST NOT rewrite approximately; mutate the token that exists now.
|
|
37
|
-
7. **For swaps/moves:** You SHOULD prefer one range operation over multiple single-line operations.
|
|
43
|
+
1. **Minimize scope:** You MUST use one logical mutation per operation.
|
|
44
|
+
2. **No no-ops:** replacement MUST differ from current.
|
|
45
|
+
3. **Prefer insertion over neighbor rewrites:** You SHOULD anchor on structural boundaries (`}`, `]`, `},`), not interior lines.
|
|
46
|
+
4. **For swaps/moves:** You SHOULD prefer one range op over multiple single-line ops.
|
|
38
47
|
</rules>
|
|
39
48
|
|
|
40
|
-
<op-choice>
|
|
41
|
-
- One wrong line → MUST use `set`
|
|
42
|
-
- Adjacent block changed → MUST use `insert`
|
|
43
|
-
- Missing line/block → MUST use `append`/`prepend`
|
|
44
|
-
</op-choice>
|
|
45
|
-
|
|
46
|
-
<tag-choice>
|
|
47
|
-
- You MUST copy tags exactly from the prefix of the `read` or error output.
|
|
48
|
-
- You MUST NOT guess tags.
|
|
49
|
-
- For inserts, you SHOULD prefer `insert` > `append`/`prepend` when both boundaries are known.
|
|
50
|
-
- You MUST re-read after each successful edit call before issuing another on same file.
|
|
51
|
-
</tag-choice>
|
|
52
|
-
|
|
53
49
|
<recovery>
|
|
54
|
-
**Tag mismatch (`>>>`)
|
|
55
|
-
- You MUST
|
|
56
|
-
- You MUST re-read only if required tags are missing from error snippet.
|
|
57
|
-
- If mismatch repeats, you MUST stop and re-read the exact block.
|
|
50
|
+
**Tag mismatch (`>>>`):** You MUST retry using fresh tags from the error snippet. Re-read only if snippet lacks context.
|
|
51
|
+
**No-op (`identical`):** You MUST NOT resubmit. Re-read target lines and adjust the edit.
|
|
58
52
|
</recovery>
|
|
59
53
|
|
|
60
|
-
<example name="
|
|
54
|
+
<example name="single-line replace">
|
|
61
55
|
```ts
|
|
62
56
|
{{hlinefull 23 " const timeout: number = 5000;"}}
|
|
63
57
|
```
|
|
64
58
|
```
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
{
|
|
60
|
+
file: "…",
|
|
61
|
+
edits: [{
|
|
62
|
+
op: "replace",
|
|
63
|
+
pos: "{{hlineref 23 " const timeout: number = 5000;"}}",
|
|
64
|
+
lines: [" const timeout: number = 30_000;"]
|
|
65
|
+
}]
|
|
66
|
+
}
|
|
68
67
|
```
|
|
69
68
|
</example>
|
|
70
69
|
|
|
71
|
-
<example name="
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
op: "replace"
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
<example name="delete lines">
|
|
71
|
+
Single line — `lines: null` deletes entirely:
|
|
72
|
+
```
|
|
73
|
+
{
|
|
74
|
+
file: "…",
|
|
75
|
+
edits: [{
|
|
76
|
+
op: "replace",
|
|
77
|
+
pos: "{{hlineref 7 "// @ts-ignore"}}",
|
|
78
|
+
lines: null
|
|
79
|
+
}]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
Range — add `end`:
|
|
83
|
+
```
|
|
84
|
+
{
|
|
85
|
+
file: "…",
|
|
86
|
+
edits: [{
|
|
87
|
+
op: "replace",
|
|
88
|
+
pos: "{{hlineref 80 " // TODO: remove after migration"}}",
|
|
89
|
+
end: "{{hlineref 83 " }"}}",
|
|
90
|
+
lines: null
|
|
91
|
+
}]
|
|
92
|
+
}
|
|
80
93
|
```
|
|
81
94
|
</example>
|
|
82
95
|
|
|
83
|
-
<example name="clear
|
|
96
|
+
<example name="clear text but keep the line break">
|
|
84
97
|
```ts
|
|
85
98
|
{{hlinefull 14 " placeholder: \"DO NOT SHIP\","}}
|
|
86
99
|
```
|
|
87
100
|
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
{
|
|
102
|
+
file: "…",
|
|
103
|
+
edits: [{
|
|
104
|
+
op: "replace",
|
|
105
|
+
pos: "{{hlineref 14 " placeholder: \"DO NOT SHIP\","}}",
|
|
106
|
+
lines: [""]
|
|
107
|
+
}]
|
|
108
|
+
}
|
|
91
109
|
```
|
|
92
110
|
</example>
|
|
93
111
|
|
|
94
|
-
<example name="rewrite a block
|
|
112
|
+
<example name="rewrite a block">
|
|
95
113
|
```ts
|
|
96
114
|
{{hlinefull 60 " } catch (err) {"}}
|
|
97
115
|
{{hlinefull 61 " console.error(err);"}}
|
|
@@ -99,117 +117,74 @@ content: [""]
|
|
|
99
117
|
{{hlinefull 63 " }"}}
|
|
100
118
|
```
|
|
101
119
|
```
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
op: "replace"
|
|
118
|
-
first: "{{hlineref 80 " // TODO: remove after migration"}}"
|
|
119
|
-
last: "{{hlineref 83 " }"}}"
|
|
120
|
-
content: null
|
|
120
|
+
{
|
|
121
|
+
file: "…",
|
|
122
|
+
edits: [{
|
|
123
|
+
op: "replace",
|
|
124
|
+
pos: "{{hlineref 60 " } catch (err) {"}}",
|
|
125
|
+
end: "{{hlineref 63 " }"}}",
|
|
126
|
+
lines: [
|
|
127
|
+
" } catch (err) {",
|
|
128
|
+
" if (isEnoent(err)) return null;",
|
|
129
|
+
" throw err;",
|
|
130
|
+
" }"
|
|
131
|
+
]
|
|
132
|
+
}]
|
|
133
|
+
}
|
|
121
134
|
```
|
|
122
135
|
</example>
|
|
123
136
|
|
|
124
|
-
<example name="
|
|
137
|
+
<example name="insert between siblings">
|
|
125
138
|
```ts
|
|
126
|
-
{{hlinefull
|
|
127
|
-
{{hlinefull
|
|
128
|
-
```
|
|
129
|
-
```
|
|
130
|
-
op: "prepend"
|
|
131
|
-
last: "{{hlineref 1 "import * as fs from \"node:fs/promises\";"}}"
|
|
132
|
-
content: ["import * as os from \"node:os\";"]
|
|
133
|
-
```
|
|
134
|
-
Use `last` for anchored insertion before a specific line. Omit anchor to prepend at BOF.
|
|
135
|
-
</example>
|
|
136
|
-
|
|
137
|
-
<example name="append at end of file">
|
|
138
|
-
```ts
|
|
139
|
-
{{hlinefull 260 "export { serialize, deserialize };"}}
|
|
139
|
+
{{hlinefull 44 " \"build\": \"bun run compile\","}}
|
|
140
|
+
{{hlinefull 45 " \"test\": \"bun test\""}}
|
|
140
141
|
```
|
|
141
142
|
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
{
|
|
144
|
+
file: "…",
|
|
145
|
+
edits: [{
|
|
146
|
+
op: "prepend",
|
|
147
|
+
pos: "{{hlineref 45 " \"test\": \"bun test\""}}",
|
|
148
|
+
lines: [" \"lint\": \"biome check\","]
|
|
149
|
+
}]
|
|
150
|
+
}
|
|
145
151
|
```
|
|
146
|
-
|
|
147
|
-
</example>
|
|
148
|
-
|
|
149
|
-
<example name="add an entry between known siblings">
|
|
152
|
+
Result:
|
|
150
153
|
```ts
|
|
151
154
|
{{hlinefull 44 " \"build\": \"bun run compile\","}}
|
|
152
|
-
{{hlinefull 45 " \"
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
op: "insert"
|
|
156
|
-
first: "{{hlineref 44 " \"build\": \"bun run compile\","}}"
|
|
157
|
-
last: "{{hlineref 45 " \"test\": \"bun test\""}}"
|
|
158
|
-
content: [" \"lint\": \"biome check\","]
|
|
155
|
+
{{hlinefull 45 " \"lint\": \"biome check\","}}
|
|
156
|
+
{{hlinefull 46 " \"test\": \"bun test\""}}
|
|
159
157
|
```
|
|
160
|
-
Dual anchors pin the insert to exactly one gap, preventing drift from edits elsewhere in the file. **Always prefer dual anchors when both boundaries are content lines.**
|
|
161
158
|
</example>
|
|
162
159
|
|
|
163
|
-
<example name="
|
|
160
|
+
<example name="anchor to structure, not whitespace">
|
|
161
|
+
Trailing `""` in `lines` preserves blank-line separators. Anchor to the structural line, not the blank line above — blank lines are ambiguous and shift.
|
|
164
162
|
```ts
|
|
165
|
-
{{hlinefull 100 " return buf.toString(\"hex\");"}}
|
|
166
163
|
{{hlinefull 101 "}"}}
|
|
167
164
|
{{hlinefull 102 ""}}
|
|
168
165
|
{{hlinefull 103 "export function serialize(data: unknown): string {"}}
|
|
169
166
|
```
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
path: "src/utils.ts"
|
|
188
|
-
rename: "src/helpers/utils.ts"
|
|
189
|
-
edits: […]
|
|
190
|
-
```
|
|
191
|
-
</example>
|
|
192
|
-
|
|
193
|
-
<example name="anti-pattern: anchoring to whitespace">
|
|
194
|
-
Bad — tags to a blank line; fragile if blank lines shift:
|
|
195
|
-
```
|
|
196
|
-
first: "{{hlineref 102 ""}}"
|
|
197
|
-
content: ["function validate() {", …, "}"]
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Good — anchors to the structural target:
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
last: "{{hlineref 103 "export function serialize(data: unknown): string {"}}"
|
|
204
|
-
content: ["function validate() {", …, "}"]
|
|
167
|
+
Bad — append after "}"
|
|
168
|
+
Good — anchors to structural line:
|
|
169
|
+
```
|
|
170
|
+
{
|
|
171
|
+
file: "…",
|
|
172
|
+
edits: [{
|
|
173
|
+
op: "prepend",
|
|
174
|
+
pos: "{{hlineref 103 "export function serialize(data: unknown): string {"}}",
|
|
175
|
+
lines: [
|
|
176
|
+
"function validate(data: unknown): boolean {",
|
|
177
|
+
" return data != null && typeof data === \"object\";",
|
|
178
|
+
"}",
|
|
179
|
+
""
|
|
180
|
+
]
|
|
181
|
+
}]
|
|
182
|
+
}
|
|
205
183
|
```
|
|
206
184
|
</example>
|
|
207
185
|
|
|
208
186
|
<critical>
|
|
209
|
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
|
|
213
|
-
- Scope MUST be minimal and formatting MUST be preserved except targeted token changes
|
|
214
|
-
</critical>
|
|
215
|
-
**Final reminder:** tags are immutable references to the last read snapshot. You MUST re-read when state changes, then edit.
|
|
187
|
+
- Edit payload: `{ file, edits[] }`. Each entry: `op`, `lines`, optional `pos`/`end`. No extra keys.
|
|
188
|
+
- Every tag MUST be copied exactly from fresh tool result as `N#ID`.
|
|
189
|
+
- You MUST re-read after each edit call before issuing another on same file.
|
|
190
|
+
</critical>
|
|
@@ -172,7 +172,7 @@ Micromanaging (you think, agent types):
|
|
|
172
172
|
```
|
|
173
173
|
assignment: "In src/api/handler.ts, line 47, change `throw err` to `throw new ApiError(err.message, 500)`.
|
|
174
174
|
On line 63, wrap fetch call try/catch return 502 on failure.
|
|
175
|
-
On line 89, add null check before accessing resp.body
|
|
175
|
+
On line 89, add null check before accessing resp.body…"
|
|
176
176
|
```
|
|
177
177
|
|
|
178
178
|
Delegating (agent thinks within constraints):
|
|
@@ -226,8 +226,8 @@ Do not touch TS bindings or downstream consumers — separate phase.
|
|
|
226
226
|
|
|
227
227
|
## Change
|
|
228
228
|
- Implement three N-API exports in grep.rs:
|
|
229
|
-
- `search(pattern: JsString, path: JsString, env: Env)
|
|
230
|
-
|
|
229
|
+
- `search(pattern: JsString, path: JsString, env: Env) → napi::Result<Vec<Match>>`
|
|
230
|
+
…
|
|
231
231
|
|
|
232
232
|
## Acceptance (task-local)
|
|
233
233
|
- Three functions exported with correct signatures (caller verifies build after all tasks)
|
package/src/task/index.ts
CHANGED
|
@@ -134,6 +134,7 @@ function renderDescription(
|
|
|
134
134
|
export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
135
135
|
readonly name = "task";
|
|
136
136
|
readonly label = "Task";
|
|
137
|
+
readonly strict = true;
|
|
137
138
|
readonly parameters: TaskSchema;
|
|
138
139
|
readonly renderCall = renderCall;
|
|
139
140
|
readonly renderResult = renderResult;
|
package/src/tools/ask.ts
CHANGED
|
@@ -246,6 +246,7 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
246
246
|
readonly label = "Ask";
|
|
247
247
|
readonly description: string;
|
|
248
248
|
readonly parameters = askSchema;
|
|
249
|
+
readonly strict = true;
|
|
249
250
|
|
|
250
251
|
constructor(private readonly session: ToolSession) {
|
|
251
252
|
this.description = renderPromptTemplate(askDescription);
|
package/src/tools/bash.ts
CHANGED
|
@@ -91,6 +91,7 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
91
91
|
readonly description: string;
|
|
92
92
|
readonly parameters: BashToolSchema;
|
|
93
93
|
readonly concurrency = "exclusive";
|
|
94
|
+
readonly strict = true;
|
|
94
95
|
readonly #asyncEnabled: boolean;
|
|
95
96
|
|
|
96
97
|
constructor(private readonly session: ToolSession) {
|
package/src/tools/browser.ts
CHANGED
|
@@ -484,6 +484,7 @@ export class BrowserTool implements AgentTool<typeof browserSchema, BrowserToolD
|
|
|
484
484
|
readonly label = "Puppeteer";
|
|
485
485
|
readonly description: string;
|
|
486
486
|
readonly parameters = browserSchema;
|
|
487
|
+
readonly strict = true;
|
|
487
488
|
#browser: Browser | null = null;
|
|
488
489
|
#page: Page | null = null;
|
|
489
490
|
#currentHeadless: boolean | null = null;
|
package/src/tools/calculator.ts
CHANGED
|
@@ -399,6 +399,7 @@ export class CalculatorTool implements AgentTool<typeof calculatorSchema, Calcul
|
|
|
399
399
|
readonly label = "Calc";
|
|
400
400
|
readonly description: string;
|
|
401
401
|
readonly parameters = calculatorSchema;
|
|
402
|
+
readonly strict = true;
|
|
402
403
|
|
|
403
404
|
constructor(_session: ToolSession) {
|
|
404
405
|
this.description = renderPromptTemplate(calculatorDescription);
|
package/src/tools/cancel-job.ts
CHANGED
|
@@ -20,6 +20,7 @@ export class CancelJobTool implements AgentTool<typeof cancelJobSchema, CancelJo
|
|
|
20
20
|
readonly label = "CancelJob";
|
|
21
21
|
readonly description: string;
|
|
22
22
|
readonly parameters = cancelJobSchema;
|
|
23
|
+
readonly strict = true;
|
|
23
24
|
|
|
24
25
|
constructor(private readonly session: ToolSession) {
|
|
25
26
|
this.description = renderPromptTemplate(cancelJobDescription);
|
|
@@ -45,6 +45,7 @@ export class ExitPlanModeTool implements AgentTool<typeof exitPlanModeSchema, Ex
|
|
|
45
45
|
readonly label = "ExitPlanMode";
|
|
46
46
|
readonly description: string;
|
|
47
47
|
readonly parameters = exitPlanModeSchema;
|
|
48
|
+
readonly strict = true;
|
|
48
49
|
|
|
49
50
|
constructor(private readonly session: ToolSession) {
|
|
50
51
|
this.description = renderPromptTemplate(exitPlanModeDescription);
|
package/src/tools/fetch.ts
CHANGED
|
@@ -856,6 +856,7 @@ export class FetchTool implements AgentTool<typeof fetchSchema, FetchToolDetails
|
|
|
856
856
|
readonly label = "Fetch";
|
|
857
857
|
readonly description: string;
|
|
858
858
|
readonly parameters = fetchSchema;
|
|
859
|
+
readonly strict = true;
|
|
859
860
|
|
|
860
861
|
constructor(private readonly session: ToolSession) {
|
|
861
862
|
this.description = renderPromptTemplate(fetchDescription);
|
package/src/tools/find.ts
CHANGED
|
@@ -127,6 +127,7 @@ export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
|
|
|
127
127
|
readonly label = "Find";
|
|
128
128
|
readonly description: string;
|
|
129
129
|
readonly parameters = findSchema;
|
|
130
|
+
readonly strict = true;
|
|
130
131
|
|
|
131
132
|
readonly #customOps?: FindOperations;
|
|
132
133
|
|
package/src/tools/grep.ts
CHANGED
|
@@ -60,6 +60,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
|
|
|
60
60
|
readonly label = "Grep";
|
|
61
61
|
readonly description: string;
|
|
62
62
|
readonly parameters = grepSchema;
|
|
63
|
+
readonly strict = true;
|
|
63
64
|
|
|
64
65
|
constructor(private readonly session: ToolSession) {
|
|
65
66
|
const displayMode = resolveFileDisplayMode(session);
|
package/src/tools/notebook.ts
CHANGED
|
@@ -65,6 +65,7 @@ export class NotebookTool implements AgentTool<typeof notebookSchema, NotebookTo
|
|
|
65
65
|
readonly description =
|
|
66
66
|
"Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number.";
|
|
67
67
|
readonly parameters = notebookSchema;
|
|
68
|
+
readonly strict = true;
|
|
68
69
|
readonly concurrency = "exclusive";
|
|
69
70
|
|
|
70
71
|
constructor(private readonly session: ToolSession) {}
|
|
@@ -19,7 +19,7 @@ export function resolvePlanPath(session: ToolSession, targetPath: string): strin
|
|
|
19
19
|
export function enforcePlanModeWrite(
|
|
20
20
|
session: ToolSession,
|
|
21
21
|
targetPath: string,
|
|
22
|
-
options?: {
|
|
22
|
+
options?: { move?: string; op?: "create" | "update" | "delete" },
|
|
23
23
|
): void {
|
|
24
24
|
const state = session.getPlanModeState?.();
|
|
25
25
|
if (!state?.enabled) return;
|
|
@@ -27,7 +27,7 @@ export function enforcePlanModeWrite(
|
|
|
27
27
|
const resolvedTarget = resolvePlanPath(session, targetPath);
|
|
28
28
|
const resolvedPlan = resolvePlanPath(session, state.planFilePath);
|
|
29
29
|
|
|
30
|
-
if (options?.
|
|
30
|
+
if (options?.move) {
|
|
31
31
|
throw new ToolError("Plan mode: renaming files is not allowed.");
|
|
32
32
|
}
|
|
33
33
|
|
package/src/tools/poll-jobs.ts
CHANGED
|
@@ -39,6 +39,7 @@ export class PollJobsTool implements AgentTool<typeof pollJobsSchema, PollJobsTo
|
|
|
39
39
|
readonly label = "PollJobs";
|
|
40
40
|
readonly description: string;
|
|
41
41
|
readonly parameters = pollJobsSchema;
|
|
42
|
+
readonly strict = true;
|
|
42
43
|
|
|
43
44
|
constructor(private readonly session: ToolSession) {
|
|
44
45
|
this.description = renderPromptTemplate(pollJobsDescription);
|
package/src/tools/python.ts
CHANGED
|
@@ -148,6 +148,7 @@ export class PythonTool implements AgentTool<typeof pythonSchema> {
|
|
|
148
148
|
readonly description: string;
|
|
149
149
|
readonly parameters = pythonSchema;
|
|
150
150
|
readonly concurrency = "exclusive";
|
|
151
|
+
readonly strict = true;
|
|
151
152
|
|
|
152
153
|
readonly #proxyExecutor?: PythonProxyExecutor;
|
|
153
154
|
|
package/src/tools/read.ts
CHANGED
|
@@ -558,6 +558,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
558
558
|
readonly description: string;
|
|
559
559
|
readonly parameters = readSchema;
|
|
560
560
|
readonly nonAbortable = true;
|
|
561
|
+
readonly strict = true;
|
|
561
562
|
|
|
562
563
|
readonly #autoResizeImages: boolean;
|
|
563
564
|
|
package/src/tools/ssh.ts
CHANGED
|
@@ -122,6 +122,7 @@ export class SshTool implements AgentTool<typeof sshSchema, SSHToolDetails> {
|
|
|
122
122
|
readonly label = "SSH";
|
|
123
123
|
readonly parameters = sshSchema;
|
|
124
124
|
readonly concurrency = "exclusive";
|
|
125
|
+
readonly strict = true;
|
|
125
126
|
|
|
126
127
|
readonly #allowedHosts: Set<string>;
|
|
127
128
|
|
|
@@ -59,6 +59,7 @@ export class SubmitResultTool implements AgentTool<TObject, SubmitResultDetails>
|
|
|
59
59
|
"Finish the task with structured JSON output. Call exactly once at the end of the task.\n\n" +
|
|
60
60
|
"If you cannot complete the task, call with status='aborted' and an error message.";
|
|
61
61
|
readonly parameters: TObject;
|
|
62
|
+
readonly strict = true;
|
|
62
63
|
|
|
63
64
|
readonly #validate?: ValidateFunction;
|
|
64
65
|
readonly #schemaError?: string;
|
package/src/tools/todo-write.ts
CHANGED
|
@@ -289,6 +289,7 @@ export class TodoWriteTool implements AgentTool<typeof todoWriteSchema, TodoWrit
|
|
|
289
289
|
readonly description: string;
|
|
290
290
|
readonly parameters = todoWriteSchema;
|
|
291
291
|
readonly concurrency = "exclusive";
|
|
292
|
+
readonly strict = true;
|
|
292
293
|
|
|
293
294
|
constructor(private readonly session: ToolSession) {
|
|
294
295
|
this.description = renderPromptTemplate(todoWriteDescription);
|
package/src/tools/write.ts
CHANGED
|
@@ -75,6 +75,7 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
|
|
|
75
75
|
readonly description: string;
|
|
76
76
|
readonly parameters = writeSchema;
|
|
77
77
|
readonly nonAbortable = true;
|
|
78
|
+
readonly strict = true;
|
|
78
79
|
readonly concurrency = "exclusive";
|
|
79
80
|
|
|
80
81
|
readonly #writethrough: WritethroughCallback;
|
package/src/web/search/index.ts
CHANGED
|
@@ -258,6 +258,7 @@ export class SearchTool implements AgentTool<typeof webSearchSchema, SearchRende
|
|
|
258
258
|
readonly label = "Web Search";
|
|
259
259
|
readonly description: string;
|
|
260
260
|
readonly parameters = webSearchSchema;
|
|
261
|
+
readonly strict = true;
|
|
261
262
|
|
|
262
263
|
constructor(_session: ToolSession) {
|
|
263
264
|
this.description = renderPromptTemplate(webSearchDescription);
|