@oh-my-pi/pi-coding-agent 14.3.0 → 14.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.
- package/CHANGELOG.md +84 -1
- package/package.json +7 -7
- package/src/autoresearch/prompt.md +1 -1
- package/src/commit/agentic/prompts/analyze-file.md +1 -1
- package/src/config/model-registry.ts +67 -15
- package/src/config/prompt-templates.ts +5 -5
- package/src/config/settings-schema.ts +4 -4
- package/src/cursor.ts +3 -8
- package/src/discovery/helpers.ts +3 -3
- package/src/edit/diff.ts +50 -47
- package/src/edit/index.ts +86 -57
- package/src/edit/line-hash.ts +735 -19
- package/src/edit/modes/apply-patch.ts +0 -9
- package/src/edit/modes/atom.ts +658 -0
- package/src/edit/modes/chunk.ts +14 -24
- package/src/edit/modes/hashline.ts +188 -136
- package/src/edit/modes/patch.ts +5 -9
- package/src/edit/modes/replace.ts +6 -11
- package/src/edit/renderer.ts +14 -10
- package/src/edit/streaming.ts +50 -16
- package/src/exec/bash-executor.ts +2 -4
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +4 -12
- package/src/extensibility/custom-tools/types.ts +2 -0
- package/src/extensibility/custom-tools/wrapper.ts +2 -1
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/lsp/index.ts +1 -1
- package/src/mcp/render.ts +1 -8
- package/src/modes/components/assistant-message.ts +4 -0
- package/src/modes/components/diff.ts +23 -14
- package/src/modes/components/footer.ts +21 -16
- package/src/modes/components/settings-defs.ts +6 -1
- package/src/modes/components/todo-reminder.ts +1 -8
- package/src/modes/components/tool-execution.ts +1 -4
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/print-mode.ts +8 -0
- package/src/prompts/agents/librarian.md +1 -1
- package/src/prompts/agents/reviewer.md +4 -4
- package/src/prompts/ci-green-request.md +1 -1
- package/src/prompts/review-request.md +1 -1
- package/src/prompts/system/subagent-system-prompt.md +3 -3
- package/src/prompts/system/subagent-yield-reminder.md +11 -0
- package/src/prompts/system/system-prompt.md +3 -0
- package/src/prompts/tools/ask.md +3 -2
- package/src/prompts/tools/ast-edit.md +15 -19
- package/src/prompts/tools/ast-grep.md +18 -24
- package/src/prompts/tools/atom.md +96 -0
- package/src/prompts/tools/chunk-edit.md +37 -161
- package/src/prompts/tools/debug.md +4 -5
- package/src/prompts/tools/exit-plan-mode.md +4 -5
- package/src/prompts/tools/find.md +4 -8
- package/src/prompts/tools/github.md +18 -0
- package/src/prompts/tools/grep.md +4 -5
- package/src/prompts/tools/hashline.md +22 -89
- package/src/prompts/tools/{gemini-image.md → image-gen.md} +1 -1
- package/src/prompts/tools/inspect-image.md +6 -6
- package/src/prompts/tools/lsp.md +1 -1
- package/src/prompts/tools/patch.md +12 -19
- package/src/prompts/tools/python.md +3 -2
- package/src/prompts/tools/read-chunk.md +2 -3
- package/src/prompts/tools/read.md +2 -2
- package/src/prompts/tools/ssh.md +8 -17
- package/src/prompts/tools/todo-write.md +54 -41
- package/src/sdk.ts +14 -9
- package/src/session/agent-session.ts +25 -2
- package/src/task/executor.ts +43 -48
- package/src/task/render.ts +11 -13
- package/src/tools/ask.ts +7 -7
- package/src/tools/ast-edit.ts +45 -41
- package/src/tools/ast-grep.ts +77 -85
- package/src/tools/bash.ts +8 -9
- package/src/tools/browser.ts +32 -30
- package/src/tools/calculator.ts +4 -4
- package/src/tools/cancel-job.ts +1 -1
- package/src/tools/checkpoint.ts +2 -2
- package/src/tools/debug.ts +41 -37
- package/src/tools/exit-plan-mode.ts +1 -1
- package/src/tools/find.ts +4 -4
- package/src/tools/gh-renderer.ts +12 -4
- package/src/tools/gh.ts +509 -697
- package/src/tools/grep.ts +115 -130
- package/src/tools/{gemini-image.ts → image-gen.ts} +459 -60
- package/src/tools/index.ts +14 -32
- package/src/tools/inspect-image.ts +3 -3
- package/src/tools/json-tree.ts +114 -114
- package/src/tools/match-line-format.ts +9 -8
- package/src/tools/notebook.ts +8 -7
- package/src/tools/poll-tool.ts +2 -1
- package/src/tools/python.ts +9 -23
- package/src/tools/read.ts +32 -21
- package/src/tools/render-mermaid.ts +1 -1
- package/src/tools/render-utils.ts +18 -0
- package/src/tools/renderers.ts +2 -2
- package/src/tools/report-tool-issue.ts +3 -2
- package/src/tools/resolve.ts +1 -1
- package/src/tools/review.ts +12 -10
- package/src/tools/search-tool-bm25.ts +2 -4
- package/src/tools/ssh.ts +4 -4
- package/src/tools/todo-write.ts +172 -147
- package/src/tools/vim.ts +14 -15
- package/src/tools/write.ts +4 -4
- package/src/tools/{submit-result.ts → yield.ts} +11 -13
- package/src/utils/edit-mode.ts +2 -1
- package/src/utils/file-display-mode.ts +10 -5
- package/src/utils/git.ts +9 -5
- package/src/utils/shell-snapshot.ts +2 -3
- package/src/vim/render.ts +4 -4
- package/src/prompts/system/subagent-submit-reminder.md +0 -11
- package/src/prompts/tools/gh-issue-view.md +0 -11
- package/src/prompts/tools/gh-pr-checkout.md +0 -12
- package/src/prompts/tools/gh-pr-diff.md +0 -12
- package/src/prompts/tools/gh-pr-push.md +0 -12
- package/src/prompts/tools/gh-pr-view.md +0 -11
- package/src/prompts/tools/gh-repo-view.md +0 -11
- package/src/prompts/tools/gh-run-watch.md +0 -12
- package/src/prompts/tools/gh-search-issues.md +0 -11
- package/src/prompts/tools/gh-search-prs.md +0 -11
package/src/modes/print-mode.ts
CHANGED
|
@@ -161,6 +161,14 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
if (
|
|
165
|
+
assistantMsg.errorMessage &&
|
|
166
|
+
assistantMsg.stopReason !== "error" &&
|
|
167
|
+
assistantMsg.stopReason !== "aborted"
|
|
168
|
+
) {
|
|
169
|
+
process.stderr.write(`${sanitizeText(assistantMsg.errorMessage)}\n`);
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
// Output text content
|
|
165
173
|
for (const content of assistantMsg.content) {
|
|
166
174
|
if (content.type === "text") {
|
|
@@ -98,7 +98,7 @@ Before acting, determine what kind of question this is:
|
|
|
98
98
|
- For API signatures: copy verbatim from source. You **MUST NOT** paraphrase or reconstruct from memory.
|
|
99
99
|
|
|
100
100
|
## 5. Report
|
|
101
|
-
- Call `
|
|
101
|
+
- Call `yield` with structured findings.
|
|
102
102
|
- Every `sources` entry **MUST** include a verbatim excerpt.
|
|
103
103
|
- The `api` array **MUST** contain exact signatures copied from source.
|
|
104
104
|
- Clean up cloned repos: `rm -rf /tmp/librarian-*`.
|
|
@@ -44,7 +44,7 @@ output:
|
|
|
44
44
|
type: number
|
|
45
45
|
file_path:
|
|
46
46
|
metadata:
|
|
47
|
-
description:
|
|
47
|
+
description: Path to affected file
|
|
48
48
|
type: string
|
|
49
49
|
line_start:
|
|
50
50
|
metadata:
|
|
@@ -63,7 +63,7 @@ Your goal is to identify bugs the author would want fixed before merge.
|
|
|
63
63
|
1. Run `git diff` (or `gh pr diff <number>`) to view patch
|
|
64
64
|
2. Read modified files for full context
|
|
65
65
|
3. Call `report_finding` per issue
|
|
66
|
-
4. Call `
|
|
66
|
+
4. Call `yield` with verdict
|
|
67
67
|
|
|
68
68
|
Bash is read-only: `git diff`, `git log`, `git show`, `gh pr diff`. You **MUST NOT** make file edits or trigger builds.
|
|
69
69
|
</procedure>
|
|
@@ -108,10 +108,10 @@ Each `report_finding` requires:
|
|
|
108
108
|
- `body`: One paragraph
|
|
109
109
|
- `priority`: 0-3
|
|
110
110
|
- `confidence`: 0.0-1.0
|
|
111
|
-
- `file_path`:
|
|
111
|
+
- `file_path`: Path to affected file
|
|
112
112
|
- `line_start`, `line_end`: Range ≤10 lines, must overlap diff
|
|
113
113
|
|
|
114
|
-
Final `
|
|
114
|
+
Final `yield` call (payload under `result.data`):
|
|
115
115
|
- `result.data.overall_correctness`: "correct" (no bugs/blockers) or "incorrect"
|
|
116
116
|
- `result.data.explanation`: Plain text, 1-3 sentences summarizing verdict. Don't repeat findings (captured via `report_finding`).
|
|
117
117
|
- `result.data.confidence`: 0.0-1.0
|
|
@@ -4,7 +4,7 @@ Do not stop after a single fix attempt.
|
|
|
4
4
|
</critical>
|
|
5
5
|
|
|
6
6
|
<instruction>
|
|
7
|
-
- Prefer `
|
|
7
|
+
- Prefer the `github` tool with `op: run_watch` and no other arguments if that tool is available.
|
|
8
8
|
- Otherwise use `gh` cli.
|
|
9
9
|
- Use the workflow runs for the current HEAD commit as the source of truth after each push.
|
|
10
10
|
</instruction>
|
|
@@ -40,7 +40,7 @@ Reviewer **MUST**:
|
|
|
40
40
|
2. {{#if skipDiff}}**MUST** run `git diff`/`git show` for assigned files{{else}}**MUST** use diff hunks below (**MUST NOT** re-run git diff){{/if}}
|
|
41
41
|
3. **MAY** read full file context as needed via `read`
|
|
42
42
|
4. Call `report_finding` per issue
|
|
43
|
-
5. Call `
|
|
43
|
+
5. Call `yield` with verdict when done
|
|
44
44
|
|
|
45
45
|
{{#if skipDiff}}
|
|
46
46
|
### Diff Previews
|
|
@@ -15,9 +15,9 @@ If you need additional information, you can find your conversation with the user
|
|
|
15
15
|
{{/if}}
|
|
16
16
|
|
|
17
17
|
{{SECTION_SEPARATOR "Closure"}}
|
|
18
|
-
No TODO tracking, no progress updates. Execute, call `
|
|
18
|
+
No TODO tracking, no progress updates. Execute, call `yield`, done.
|
|
19
19
|
|
|
20
|
-
When finished, you **MUST** call `
|
|
20
|
+
When finished, you **MUST** call `yield` exactly once. This is like writing to a ticket, provide what is required, and close it.
|
|
21
21
|
|
|
22
22
|
This is your only way to return a result. You **MUST NOT** put JSON in plain text, and you **MUST NOT** substitute a text summary for the structured `result.data` parameter.
|
|
23
23
|
|
|
@@ -29,7 +29,7 @@ Your result **MUST** match this TypeScript interface:
|
|
|
29
29
|
{{/if}}
|
|
30
30
|
|
|
31
31
|
{{SECTION_SEPARATOR "Giving Up"}}
|
|
32
|
-
Giving up is a last resort. If truly blocked, you **MUST** call `
|
|
32
|
+
Giving up is a last resort. If truly blocked, you **MUST** call `yield` exactly once with `result.error` describing what you tried and the exact blocker.
|
|
33
33
|
You **MUST NOT** give up due to uncertainty, missing information obtainable via tools or repo context, or needing a design decision you can derive yourself.
|
|
34
34
|
|
|
35
35
|
You **MUST** keep going until this ticket is closed. This matters.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<system-reminder>
|
|
2
|
+
You stopped without calling yield. This is reminder {{retryCount}} of {{maxRetries}}.
|
|
3
|
+
|
|
4
|
+
You **MUST** call yield as your only action now. Choose one:
|
|
5
|
+
- If task is complete: call yield with your result in `result.data`
|
|
6
|
+
- If task failed: call yield with `result.error` describing what happened
|
|
7
|
+
|
|
8
|
+
You **MUST NOT** give up if you can still complete the task through exploration (using available tools or repo context). If you submit an error, you **MUST** include what you tried and the exact blocker.
|
|
9
|
+
|
|
10
|
+
You **MUST NOT** output text without a tool call. You **MUST** call yield to finish.
|
|
11
|
+
</system-reminder>
|
|
@@ -194,6 +194,9 @@ You **MUST NOT** use Python or Bash when a specialized tool exists.
|
|
|
194
194
|
{{#has tools "edit"}}- Use `edit` for surgical text changes, not `sed`.{{/has}}
|
|
195
195
|
{{/ifAny}}
|
|
196
196
|
|
|
197
|
+
### Paths
|
|
198
|
+
- For tools that take a `path` (or path-like field), prefer cwd-relative paths for files inside the cwd. Use absolute paths only when targeting files outside the cwd or when expanding `~`.
|
|
199
|
+
|
|
197
200
|
{{#has tools "lsp"}}
|
|
198
201
|
### LSP guidance
|
|
199
202
|
Use semantic tools for semantic questions:
|
package/src/prompts/tools/ask.md
CHANGED
|
@@ -21,8 +21,9 @@ Asks user when you need clarification or input during task execution.
|
|
|
21
21
|
- **Do NOT include "Other" option** — UI automatically adds "Other (type your own)" to every question.
|
|
22
22
|
</critical>
|
|
23
23
|
|
|
24
|
-
<
|
|
24
|
+
<examples>
|
|
25
|
+
# Single question
|
|
25
26
|
question: "Which authentication method should this API use?"
|
|
26
27
|
options: [{"label": "JWT"}, {"label": "OAuth2"}, {"label": "Session cookies"}]
|
|
27
28
|
recommended: 0
|
|
28
|
-
</
|
|
29
|
+
</examples>
|
|
@@ -2,12 +2,12 @@ Performs structural AST-aware rewrites via native ast-grep.
|
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
4
|
- Use for codemods and structural rewrites where plain text replace is unsafe
|
|
5
|
-
- `path` accepts a comma-separated list
|
|
6
|
-
-
|
|
5
|
+
- `path` is required and accepts a file, directory, glob, comma-separated path list, or internal URL
|
|
6
|
+
- Language is inferred from `path`; narrow `path` to one language for deterministic rewrites
|
|
7
7
|
- Metavariables captured in `pat` (`$A`, `$$$ARGS`) are substituted into that entry's `out` template
|
|
8
8
|
- **Patterns match AST structure, not text.** `$NAME` = one node (captured); `$_` = one without binding; `$$$NAME` = zero-or-more (lazy — stops at next matchable element); `$$$` = zero-or-more without binding. Use `$$$NAME`, **NOT** `$$NAME` — the two-dollar form is invalid. Metavariable names are UPPERCASE and **MUST** be the whole AST node — partial text like `prefix$VAR` or `"hello $NAME"` does NOT work
|
|
9
9
|
- When the same metavariable appears twice, both occurrences **MUST** match identical code (`$A == $A` matches `x == x`, not `x == y`)
|
|
10
|
-
- Rewrite patterns **MUST** parse as a single valid AST node. For method fragments or body snippets that don't parse standalone, wrap in context (e.g. `class $_ { … }`)
|
|
10
|
+
- Rewrite patterns **MUST** parse as a single valid AST node. For method fragments or body snippets that don't parse standalone, wrap in context (e.g. `class $_ { … }`)
|
|
11
11
|
- For TS declarations/methods, tolerate unknown annotations: `async function $NAME($$$ARGS): $_ { $$$BODY }` or `class $_ { method($ARG: $_): $_ { $$$BODY } }`
|
|
12
12
|
- Delete matched code with empty `out`: `{"pat":"console.log($$$)","out":""}`
|
|
13
13
|
- Each rewrite is a 1:1 structural substitution — cannot split one capture across multiple nodes or merge multiple captures into one
|
|
@@ -19,22 +19,18 @@ Performs structural AST-aware rewrites via native ast-grep.
|
|
|
19
19
|
</output>
|
|
20
20
|
|
|
21
21
|
<examples>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- Rewrite a method body fragment by wrapping in parseable context and selecting the method:
|
|
35
|
-
`{"ops":[{"pat":"class $_ { async execute($INPUT: $_) { $$$BEFORE; const $PARSED = $_.parse($INPUT); $$$AFTER } }","out":"class $_ { async execute($INPUT: $_) { $$$BEFORE; const $PARSED = $SCHEMA.parse($INPUT); $$$AFTER } }"}],"sel":"method_definition","lang":"typescript","path":"src/tools/todo.ts"}`
|
|
36
|
-
- Python — convert print calls to logging:
|
|
37
|
-
`{"ops":[{"pat":"print($$$ARGS)","out":"logger.info($$$ARGS)"}],"lang":"python","path":"src/"}`
|
|
22
|
+
# Rename a call site across TypeScript files
|
|
23
|
+
`{"ops":[{"pat":"oldApi($$$ARGS)","out":"newApi($$$ARGS)"}],"path":"src/**/*.ts"}`
|
|
24
|
+
# Delete matching calls
|
|
25
|
+
`{"ops":[{"pat":"console.log($$$ARGS)","out":""}],"path":"src/**/*.ts"}`
|
|
26
|
+
# Rewrite import source path
|
|
27
|
+
`{"ops":[{"pat":"import { $$$IMPORTS } from \"old-package\"","out":"import { $$$IMPORTS } from \"new-package\""}],"path":"src/**/*.ts"}`
|
|
28
|
+
# Modernize to optional chaining (same metavariable enforces identity)
|
|
29
|
+
`{"ops":[{"pat":"$A && $A()","out":"$A?.()"}],"path":"src/**/*.ts"}`
|
|
30
|
+
# Swap two arguments using captures
|
|
31
|
+
`{"ops":[{"pat":"assertEqual($A, $B)","out":"assertEqual($B, $A)"}],"path":"tests/**/*.ts"}`
|
|
32
|
+
# Python — convert print calls to logging
|
|
33
|
+
`{"ops":[{"pat":"print($$$ARGS)","out":"logger.info($$$ARGS)"}],"path":"src/**/*.py"}`
|
|
38
34
|
</examples>
|
|
39
35
|
|
|
40
36
|
<critical>
|
|
@@ -2,18 +2,18 @@ Performs structural code search using AST matching via native ast-grep.
|
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
4
|
- Use when syntax shape matters more than raw text (calls, declarations, specific language constructs)
|
|
5
|
-
- `path` accepts a comma-separated list
|
|
6
|
-
-
|
|
7
|
-
-
|
|
5
|
+
- `path` is required and accepts a file, directory, glob, comma-separated path list, or internal URL
|
|
6
|
+
- Language is inferred from `path`; narrow `path` to one language when mixed-language trees could cause parse noise
|
|
7
|
+
- `pat` is a single AST pattern. Run separate calls for distinct unrelated patterns
|
|
8
8
|
- **Patterns match AST structure, not text** — whitespace/formatting is ignored
|
|
9
9
|
- `$NAME` captures one node; `$_` matches one without binding; `$$$NAME` captures zero-or-more (lazy — stops at next matchable element); `$$$` matches zero-or-more without binding. Use `$$$NAME`, **NOT** `$$NAME` — the two-dollar form is invalid and produces a parse error
|
|
10
10
|
- Metavariable names are UPPERCASE and must be the whole AST node — partial-text like `prefix$VAR`, `"hello $NAME"`, or `a $OP b` does NOT work; match the whole node instead
|
|
11
11
|
- When the same metavariable appears twice, both occurrences **MUST** match identical code (`$A == $A` matches `x == x`, not `x == y`)
|
|
12
|
-
- Patterns **MUST** parse as a single valid AST node for the target language. For method fragments or body snippets that don't parse standalone, wrap in valid context (e.g. `class $_ { … }`)
|
|
13
|
-
- C++ qualified calls used as expression statements need the statement semicolon in the pattern: use `ns::doThing($ARG);`, `$CALLEE($ARG)
|
|
12
|
+
- Patterns **MUST** parse as a single valid AST node for the inferred target language. For method fragments or body snippets that don't parse standalone, wrap in valid context (e.g. `class $_ { … }`)
|
|
13
|
+
- C++ qualified calls used as expression statements need the statement semicolon in the pattern: use `ns::doThing($ARG);`, `$CALLEE($ARG);`, or wrap a statement snippet. Without `;`, tree-sitter-cpp may parse `ns::doThing($ARG)` as declaration-like syntax and return no matches
|
|
14
14
|
- For TS declarations/methods, tolerate unknown annotations: `async function $NAME($$$ARGS): $_ { $$$BODY }` or `class $_ { method($ARG: $_): $_ { $$$BODY } }`
|
|
15
15
|
- Declaration forms are structurally distinct — top-level `function foo`, class method `foo()`, and `const foo = () => {}` are different AST shapes; search the right form before concluding absence
|
|
16
|
-
- Loosest existence check: `pat:
|
|
16
|
+
- Loosest existence check: `pat: "executeBash"` with a narrow `path`
|
|
17
17
|
</instruction>
|
|
18
18
|
|
|
19
19
|
<output>
|
|
@@ -22,26 +22,20 @@ Performs structural code search using AST matching via native ast-grep.
|
|
|
22
22
|
</output>
|
|
23
23
|
|
|
24
24
|
<examples>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- Match a function declaration while tolerating any return type annotation (`sel` targets the inner node):
|
|
36
|
-
`{"pat":["async function processItems($$$ARGS): $_ { $$$BODY }"],"sel":"function_declaration","lang":"typescript","path":"src/worker.ts"}`
|
|
37
|
-
- Match a method body fragment by wrapping in parseable context and selecting the method:
|
|
38
|
-
`{"pat":["class $_ { async execute($INPUT: $_) { $$$BEFORE; const $PARSED = $_.parse($INPUT); $$$AFTER } }"],"sel":"method_definition","lang":"typescript","path":"src/tools/todo.ts"}`
|
|
39
|
-
- Loosest existence check for a symbol in one file:
|
|
40
|
-
`{"pat":["processItems"],"sel":"identifier","lang":"typescript","path":"src/worker.ts"}`
|
|
25
|
+
# Search TypeScript files under src
|
|
26
|
+
`{"pat":"console.log($$$)","path":"src/**/*.ts"}`
|
|
27
|
+
# Named imports from a specific package
|
|
28
|
+
`{"pat":"import { $$$IMPORTS } from \"react\"","path":"src/**/*.ts"}`
|
|
29
|
+
# Arrow functions assigned to a const
|
|
30
|
+
`{"pat":"const $NAME = ($$$ARGS) => $BODY","path":"src/utils/**/*.ts"}`
|
|
31
|
+
# Method call on any object, ignoring method name with `$_`
|
|
32
|
+
`{"pat":"logger.$_($$$ARGS)","path":"src/**/*.ts"}`
|
|
33
|
+
# Loosest existence check for a symbol in one file
|
|
34
|
+
`{"pat":"processItems","path":"src/worker.ts"}`
|
|
41
35
|
</examples>
|
|
42
36
|
|
|
43
37
|
<critical>
|
|
44
|
-
- Avoid repo-root
|
|
45
|
-
- Parse issues are query failure, not evidence of absence: repair the pattern or tighten `path
|
|
38
|
+
- Avoid repo-root scans — narrow `path` first
|
|
39
|
+
- Parse issues are query failure, not evidence of absence: repair the pattern or tighten `path` before concluding "no matches"
|
|
46
40
|
- For broad/open-ended exploration across subsystems, use Task tool with explore subagent first
|
|
47
41
|
</critical>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Applies precise file edits using full anchors from `read` output (for example `160sr`).
|
|
2
|
+
|
|
3
|
+
Read the file first. Copy the full anchors exactly as shown by `read`.
|
|
4
|
+
|
|
5
|
+
<operations>
|
|
6
|
+
**Top level**: `{ path, edits: […] }` — `path` is shared by all entries. You may still override the file inside `loc` with forms like `other.ts:160sr`.
|
|
7
|
+
|
|
8
|
+
Each entry has one shared locator plus one or more verbs:
|
|
9
|
+
- `loc: "160sr"` — single anchored line
|
|
10
|
+
- `loc: "^"` — beginning of file (only valid with `pre`)
|
|
11
|
+
- `loc: "$"` — end of file (only valid with `post`)
|
|
12
|
+
- `loc: "a.ts:160sr"` — cross-file override inside the locator
|
|
13
|
+
|
|
14
|
+
Verbs:
|
|
15
|
+
- `set: ["…"]` — replace the anchor line
|
|
16
|
+
- `pre: ["…"]` — insert before the anchor line (or at BOF when `loc:"^"`)
|
|
17
|
+
- `post: ["…"]` — insert after the anchor line (or at EOF when `loc:"$"`)
|
|
18
|
+
|
|
19
|
+
Combination rules:
|
|
20
|
+
- On a single-anchor `loc`, you may combine `pre`, `set`, and `post` in the same entry.
|
|
21
|
+
- `set: []` on a single-anchor `loc` deletes that line.
|
|
22
|
+
- `set:[""]` is **not** delete — it replaces the line with a blank line.
|
|
23
|
+
</operations>
|
|
24
|
+
|
|
25
|
+
<examples>
|
|
26
|
+
All examples below reference the same file:
|
|
27
|
+
|
|
28
|
+
```ts title="a.ts"
|
|
29
|
+
{{hline 1 "// @ts-ignore"}}
|
|
30
|
+
{{hline 2 "const timeout = 5000;"}}
|
|
31
|
+
{{hline 3 "const tag = \"DO NOT SHIP\";"}}
|
|
32
|
+
{{hline 4 "const fallback = group.targetFramework || 'All Frameworks';"}}
|
|
33
|
+
{{hline 5 "function alpha() {"}}
|
|
34
|
+
{{hline 6 "\tlog();"}}
|
|
35
|
+
{{hline 7 "}"}}
|
|
36
|
+
{{hline 8 ""}}
|
|
37
|
+
{{hline 9 "function beta(x) {"}}
|
|
38
|
+
{{hline 10 "\tif (x) {"}}
|
|
39
|
+
{{hline 11 "\t\treturn parse(data);"}}
|
|
40
|
+
{{hline 12 "\t}"}}
|
|
41
|
+
{{hline 13 "\treturn null;"}}
|
|
42
|
+
{{hline 14 "}"}}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
# Swap an operator by replacing the line
|
|
46
|
+
Original line 4: `const fallback = group.targetFramework || 'All Frameworks';`
|
|
47
|
+
`{path:"a.ts",edits:[{loc:{{href 4 "const fallback = group.targetFramework || 'All Frameworks';"}},set:["const fallback = group.targetFramework ?? 'All Frameworks';"]}]}`
|
|
48
|
+
|
|
49
|
+
# Flip a literal by replacing the line
|
|
50
|
+
Original line 2: `const timeout = 5000;`
|
|
51
|
+
`{path:"a.ts",edits:[{loc:{{href 2 "const timeout = 5000;"}},set:["const timeout = 30_000;"]}]}`
|
|
52
|
+
|
|
53
|
+
# Negate a condition by replacing the line
|
|
54
|
+
Original line 10: `\tif (x) {`
|
|
55
|
+
`{path:"a.ts",edits:[{loc:{{href 10 "\tif (x) {"}},set:["\tif (!x) {"]}]}`
|
|
56
|
+
|
|
57
|
+
# Combine `pre` + `set` + `post` in one entry
|
|
58
|
+
`{path:"a.ts",edits:[{loc:{{href 6 "\tlog();"}},pre:["\tvalidate();"],set:["\tlog();"],post:["\tcleanup();"]}]}`
|
|
59
|
+
|
|
60
|
+
# Replace one whole line with `set`
|
|
61
|
+
Use `set` to replace the full anchored line, preserving any unchanged surrounding lines yourself.
|
|
62
|
+
`{path:"a.ts",edits:[{loc:{{href 3 "const tag = \"DO NOT SHIP\";"}},set:["const tag = \"OK\";"]}]}`
|
|
63
|
+
|
|
64
|
+
# Replace multiple non-adjacent lines
|
|
65
|
+
`{path:"a.ts",edits:[{loc:{{href 11 "\t\treturn parse(data);"}},set:["\t\treturn parse(data) ?? fallback;"]},{loc:{{href 13 "\treturn null;"}},set:["\treturn fallback;"]}]}`
|
|
66
|
+
|
|
67
|
+
# Delete a line with `set: []`
|
|
68
|
+
`{path:"a.ts",edits:[{loc:{{href 11 "\t\treturn parse(data);"}},set:[]}]}`
|
|
69
|
+
|
|
70
|
+
# Preserve a blank line with `set:[""]`
|
|
71
|
+
`{path:"a.ts",edits:[{loc:{{href 8 ""}},set:[""]}]}`
|
|
72
|
+
|
|
73
|
+
# Insert before / after a line
|
|
74
|
+
`{path:"a.ts",edits:[{loc:{{href 9 "function beta(x) {"}},pre:["function gamma() {","\tvalidate();","}",""]}]}`
|
|
75
|
+
`{path:"a.ts",edits:[{loc:{{href 6 "\tlog();"}},post:["\tvalidate();"]}]}`
|
|
76
|
+
|
|
77
|
+
# Prepend / append at file edges
|
|
78
|
+
`{path:"a.ts",edits:[{loc:"^",pre:["// Copyright (c) 2026",""]}]}`
|
|
79
|
+
`{path:"a.ts",edits:[{loc:"$",post:["","export const VERSION = \"1.0.0\";"]}]}`
|
|
80
|
+
|
|
81
|
+
# Cross-file override inside `loc`
|
|
82
|
+
`{path:"a.ts",edits:[{loc:"b.ts:{{href 2 "const timeout = 5000;"}}",set:["const timeout = 30_000;"]}]}`
|
|
83
|
+
</examples>
|
|
84
|
+
|
|
85
|
+
<critical>
|
|
86
|
+
- Make the minimum exact edit.
|
|
87
|
+
- Copy the full anchors exactly as shown by `read/grep` (for example `160sr`, not just `sr`).
|
|
88
|
+
- `loc` chooses the target. Verbs describe what to do there.
|
|
89
|
+
- On a single-anchor `loc`, you may combine `pre`, `set`, and `post`.
|
|
90
|
+
- `loc:"^"` only supports `pre`. `loc:"$"` only supports `post`.
|
|
91
|
+
- `set: []` deletes the anchored line. `set:[""]` preserves a blank line.
|
|
92
|
+
- Within a single request you may submit edits in any order — the runtime applies them bottom-up so they don't shift each other. After any request that mutates a file, anchors below the mutation are stale on disk; re-read before issuing more edits to that file.
|
|
93
|
+
- `set` operations target the current file content only. Do not try to reference old line text after the file has changed.
|
|
94
|
+
- Text content must be literal file content with matching indentation. If the file uses tabs, use real tabs.
|
|
95
|
+
- You **MUST NOT** use this tool to reformat or clean up unrelated code.
|
|
96
|
+
</critical>
|
|
@@ -8,7 +8,7 @@ Call format: `{"edits": [{"path": "file:chunk#ID~", "write": "new body"}, …]}`
|
|
|
8
8
|
|
|
9
9
|
<rules>
|
|
10
10
|
- **MUST** inspect first with `read`. Never invent chunk paths or IDs. Copy them from the latest `read` output or edit response.
|
|
11
|
-
- `path` format: `file:selector` — e.g. `src/app.ts:fn_foo#
|
|
11
|
+
- `path` format: `file:selector` — e.g. `src/app.ts:fn_foo#thth~`. Append `~` for body, `^` for head, or nothing for the whole chunk. Include `#ID` for `write`/`delete`.
|
|
12
12
|
- If the exact chunk path is unclear, run `read(path="file", sel="?")` and copy a selector from that listing.
|
|
13
13
|
{{#if chunkAutoIndent}}
|
|
14
14
|
- Use `\t` for indentation in `content`. Write content at indent-level 0 — the tool re-indents it to match the chunk's position in the file. For example, to replace `~` of a method, write the body starting at column 0:
|
|
@@ -75,32 +75,32 @@ Each edit entry has `path` (`file:selector`) plus **exactly one** operation fiel
|
|
|
75
75
|
<examples>
|
|
76
76
|
Given this `read` output for `counter.rs`:
|
|
77
77
|
```
|
|
78
|
-
| counter.rs·62L·rust·#
|
|
78
|
+
| counter.rs·62L·rust·#anth
|
|
79
79
|
|
|
|
80
|
-
@imp#
|
|
80
|
+
@imp#erhe
|
|
81
81
|
1 |use std::fmt;
|
|
82
82
|
|
|
|
83
|
-
@struct_Counte#
|
|
83
|
+
@struct_Counte#onat
|
|
84
84
|
3^|/// A simple counter that tracks a value and its history.
|
|
85
85
|
4^|#[derive(Debug, Clone)]
|
|
86
86
|
5^|pub struct Counter {
|
|
87
|
-
-@struct_Counte.field_value#
|
|
87
|
+
-@struct_Counte.field_value#enth
|
|
88
88
|
6 | /// The current value.
|
|
89
89
|
7 | value: i32,
|
|
90
|
-
-@struct_Counte.field_max#
|
|
90
|
+
-@struct_Counte.field_max#seti
|
|
91
91
|
8 | /// Maximum allowed value.
|
|
92
92
|
9 | max: i32,
|
|
93
93
|
10 |}
|
|
94
94
|
|
|
|
95
|
-
@impl_Counte#
|
|
95
|
+
@impl_Counte#reha
|
|
96
96
|
12^|impl Counter {
|
|
97
|
-
-@impl_Counte.fn_new#
|
|
97
|
+
-@impl_Counte.fn_new#ndas
|
|
98
98
|
13^| /// Creates a new counter starting at zero.
|
|
99
99
|
14^| pub fn new(max: i32) -> Self {
|
|
100
100
|
15 | Self { value: 0, max }
|
|
101
101
|
16 | }
|
|
102
102
|
17 |
|
|
103
|
-
-@impl_Counte.fn_increm#
|
|
103
|
+
-@impl_Counte.fn_increm#ouer
|
|
104
104
|
18^| /// Increments the counter by one, clamping at max.
|
|
105
105
|
19^| pub fn increment(&mut self) {
|
|
106
106
|
20 | if self.value < self.max {
|
|
@@ -108,7 +108,7 @@ Given this `read` output for `counter.rs`:
|
|
|
108
108
|
22 | }
|
|
109
109
|
23 | }
|
|
110
110
|
24 |
|
|
111
|
-
-@impl_Counte.fn_decrem#
|
|
111
|
+
-@impl_Counte.fn_decrem#arve
|
|
112
112
|
25^| /// Decrements the counter by one, clamping at zero.
|
|
113
113
|
26^| pub fn decrement(&mut self) {
|
|
114
114
|
27 | if self.value > 0 {
|
|
@@ -116,167 +116,43 @@ Given this `read` output for `counter.rs`:
|
|
|
116
116
|
29 | }
|
|
117
117
|
30 | }
|
|
118
118
|
31 |
|
|
119
|
-
-@impl_Counte.fn_get#
|
|
119
|
+
-@impl_Counte.fn_get#arco
|
|
120
120
|
32^| /// Returns the current value.
|
|
121
121
|
33^| pub fn get(&self) -> i32 {
|
|
122
122
|
34 | self.value
|
|
123
123
|
35 | }
|
|
124
124
|
36 |}
|
|
125
125
|
|
|
|
126
|
-
@impl_Displa#
|
|
126
|
+
@impl_Displa#meha
|
|
127
127
|
38^|impl fmt::Display for Counter {
|
|
128
|
-
-@impl_Displa.fn_fmt#
|
|
128
|
+
-@impl_Displa.fn_fmt#deri
|
|
129
129
|
39^| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
130
130
|
40 | write!(f, "Counter({}/{})", self.value, self.max)
|
|
131
131
|
41 | }
|
|
132
132
|
42 |}
|
|
133
|
-
|
|
|
134
|
-
@mod_tests#YWXM
|
|
135
|
-
44^|#[cfg(test)]
|
|
136
|
-
45^|mod tests {
|
|
137
|
-
-@mod_tests.chunk#VSMY
|
|
138
|
-
46 | use super::*;
|
|
139
|
-
47 |
|
|
140
|
-
-@mod_tests.fn_test_i#YXQZ
|
|
141
|
-
48^| #[test]
|
|
142
|
-
49^| fn test_increment() {
|
|
143
|
-
50 | let mut c = Counter::new(10);
|
|
144
|
-
51 | c.increment();
|
|
145
|
-
52 | assert_eq!(c.get(), 1);
|
|
146
|
-
53 | }
|
|
147
|
-
54 |
|
|
148
|
-
-@mod_tests.fn_test_d#XPBQ
|
|
149
|
-
55^| #[test]
|
|
150
|
-
56^| fn test_decrement_at_zero() {
|
|
151
|
-
57 | let mut c = Counter::new(10);
|
|
152
|
-
58 | c.decrement();
|
|
153
|
-
59 | assert_eq!(c.get(), 0);
|
|
154
|
-
60 | }
|
|
155
|
-
61 |}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Understanding `^` markers in `read` output:** Lines marked with `^` between the line number and `|` (e.g. ` 3^|`) are **head** lines — doc comments, attributes, and the signature. Lines without `^` (e.g. ` 7 |`) are **body** lines. `~` replaces body lines only, keeping head lines intact.
|
|
159
|
-
|
|
160
|
-
**Put body** (`~` — the common case):
|
|
161
|
-
```
|
|
162
|
-
{ "path": "counter.rs:impl_Counte.fn_increm#MNHV~", "write": "self.value = (self.value + 1).min(self.max);\n" }
|
|
163
|
-
```
|
|
164
|
-
Result — only the body (non-`^` lines) changes; the doc comment, signature, and closing `}` are all preserved:
|
|
165
|
-
```
|
|
166
|
-
/// Increments the counter by one, clamping at max.
|
|
167
|
-
pub fn increment(&mut self) {
|
|
168
|
-
self.value = (self.value + 1).min(self.max);
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**Write whole chunk** (rewrite signature + doc comment + body):
|
|
173
|
-
```
|
|
174
|
-
{ "path": "counter.rs:impl_Counte.fn_increm#MNHV", "write": "/// Increments by the given step, clamping at max.\npub fn increment(&mut self, step: i32) {\n\tself.value = (self.value + step).min(self.max);\n}\n" }
|
|
175
|
-
```
|
|
176
|
-
Result — **everything** including the doc comment and signature is rewritten. You must include them; omitting them deletes them:
|
|
177
|
-
```
|
|
178
|
-
/// Increments by the given step, clamping at max.
|
|
179
|
-
pub fn increment(&mut self, step: i32) {
|
|
180
|
-
self.value = (self.value + step).min(self.max);
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Write head** (`^` — attributes, doc comments, signature):
|
|
185
|
-
```
|
|
186
|
-
{ "path": "counter.rs:impl_Counte.fn_get#PTNT^", "write": "/// Returns the current counter value.\n#[inline]\npub fn get(&self) -> i32 {\n" }
|
|
187
|
-
```
|
|
188
|
-
Result — the head (all `^` lines + opening brace) changes, body untouched:
|
|
189
|
-
```
|
|
190
|
-
/// Returns the current counter value.
|
|
191
|
-
#[inline]
|
|
192
|
-
pub fn get(&self) -> i32 {
|
|
193
|
-
self.value
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**Insert before a chunk** (`prepend`):
|
|
198
|
-
```
|
|
199
|
-
{ "path": "counter.rs:impl_Counte.fn_get", "insert": { "loc": "prepend", "body": "/// Resets the counter to zero.\npub fn reset(&mut self) {\n\tself.value = 0;\n}\n\n" } }
|
|
200
|
-
```
|
|
201
|
-
Result — a new method is inserted before `fn get`:
|
|
202
|
-
```
|
|
203
|
-
/// Resets the counter to zero.
|
|
204
|
-
pub fn reset(&mut self) {
|
|
205
|
-
self.value = 0;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/// Returns the current value.
|
|
209
|
-
pub fn get(&self) -> i32 {
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**Insert after a chunk** (`append`):
|
|
213
|
-
```
|
|
214
|
-
{ "path": "counter.rs:struct_Counte", "insert": { "loc": "append", "body": "\nimpl Default for Counter {\n\tfn default() -> Self {\n\t\tSelf { value: 0, max: 100 }\n\t}\n}\n" } }
|
|
215
133
|
```
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
/// Creates a new counter starting at zero.
|
|
242
|
-
pub fn new(max: i32) -> Self {
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
**Insert at end of container body** (`~` + `append`):
|
|
246
|
-
```
|
|
247
|
-
{ "path": "counter.rs:impl_Counte~", "insert": { "loc": "append", "body": "\n/// Returns true if the counter is at its maximum.\npub fn is_maxed(&self) -> bool {\n\tself.value >= self.max\n}\n" } }
|
|
248
|
-
```
|
|
249
|
-
Result — a new method is added at the end of the impl body, before the closing `}`:
|
|
250
|
-
```
|
|
251
|
-
pub fn get(&self) -> i32 {
|
|
252
|
-
self.value
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/// Returns true if the counter is at its maximum.
|
|
256
|
-
pub fn is_maxed(&self) -> bool {
|
|
257
|
-
self.value >= self.max
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
**Delete a chunk**:
|
|
263
|
-
```
|
|
264
|
-
{ "path": "counter.rs:impl_Counte.fn_decrem#TTWB", "delete": true }
|
|
265
|
-
```
|
|
266
|
-
Result — the method (including its doc comment and signature) is removed.
|
|
267
|
-
- Indentation rules (important):
|
|
268
|
-
{{#if chunkAutoIndent}}
|
|
269
|
-
- Use `\t` for each indent level. The tool converts tabs to the file's actual style (2-space, 4-space, etc.).
|
|
270
|
-
{{else}}
|
|
271
|
-
- Match the file's real indentation characters in your snippet. The tool preserves your literal tabs/spaces after adding the target region's base indent.
|
|
272
|
-
{{/if}}
|
|
273
|
-
- Do NOT include the chunk's base indentation — only indent relative to the region's opening level.
|
|
274
|
-
- For `write`, the tool strips common leading whitespace shared by all non-empty lines, then adds the target region's base indent. If lines have mixed relative indentation, write them at column 0 so the common-margin cleanup cannot change the structure.
|
|
275
|
-
- For `~` of a function: write at column 0, and use `\t` for *relative* nesting. Flat body: `"return x;\n"`. Multiple sibling lines: `"print(a)\nprint(b)\nprint(c)\n"` — all at column 0, the tool adds the function's base indent. Nested body: `"if (cond) {\n\treturn x;\n}\n"` — the `if` is at column 0, the `return` is one tab in. Python example — to replace `~` of `def divide(a, b):`, write: `"if b == 0:\n\treturn None\nreturn a / b\n"` — the `if` and `return a / b` are at column 0, `return None` is one `\t` in.
|
|
276
|
-
- For `^`: write at column 0 relative to the head region, just like `~`. A class member's head uses `"/// doc\n#[attr]\npub fn start() {"` — do not include the class/member base indentation.
|
|
277
|
-
{{#if chunkAutoIndent}}
|
|
278
|
-
- For a top-level item: start at zero indent. Write `"fn foo() {\n\treturn 1;\n}\n"`.
|
|
279
|
-
{{else}}
|
|
280
|
-
- For a top-level item: start at zero indent. Write `"fn foo() {\n return 1;\n}\n"`.
|
|
281
|
-
{{/if}}
|
|
134
|
+
Lines marked `^` between the line number and `|` are **head** lines (doc comments, attributes, signature). Lines without `^` are **body** lines. `~` replaces body lines only; `^` replaces head lines only.
|
|
135
|
+
|
|
136
|
+
# Put body (`~` — the common case)
|
|
137
|
+
`{ "path": "counter.rs:impl_Counte.fn_increm#ouer~", "write": "self.value = (self.value + 1).min(self.max);\n" }`
|
|
138
|
+
Only body changes; doc comment, signature, and closing `}` are preserved.
|
|
139
|
+
# Write whole chunk (rewrite signature + doc + body)
|
|
140
|
+
`{ "path": "counter.rs:impl_Counte.fn_increm#ouer", "write": "/// Increments by the given step, clamping at max.\npub fn increment(&mut self, step: i32) {\n\tself.value = (self.value + step).min(self.max);\n}\n" }`
|
|
141
|
+
Everything is rewritten. Omitting the doc comment or signature deletes them.
|
|
142
|
+
# Write head (`^` — attributes, doc comments, signature)
|
|
143
|
+
`{ "path": "counter.rs:impl_Counte.fn_get#arco^", "write": "/// Returns the current counter value.\n#[inline]\npub fn get(&self) → i32 {\n" }`
|
|
144
|
+
Head changes (all `^` lines + opening brace); body untouched.
|
|
145
|
+
# Insert before a chunk (`prepend`)
|
|
146
|
+
`{ "path": "counter.rs:impl_Counte.fn_get", "insert": { "loc": "prepend", "body": "/// Resets the counter to zero.\npub fn reset(&mut self) {\n\tself.value = 0;\n}\n\n" } }`
|
|
147
|
+
# Insert after a chunk (`append`)
|
|
148
|
+
`{ "path": "counter.rs:struct_Counte", "insert": { "loc": "append", "body": "\nimpl Default for Counter {\n\tfn default() → Self {\n\t\tSelf { value: 0, max: 100 }\n\t}\n}\n" } }`
|
|
149
|
+
# Insert at start of container body (`~` + `prepend`)
|
|
150
|
+
`{ "path": "counter.rs:impl_Counte~", "insert": { "loc": "prepend", "body": "/// Creates a counter starting at the given value.\npub fn with_value(value: i32, max: i32) → Self {\n\tSelf { value: value.min(max), max }\n}\n\n" } }`
|
|
151
|
+
Lands at the top of the impl body, before existing methods.
|
|
152
|
+
# Insert at end of container body (`~` + `append`)
|
|
153
|
+
`{ "path": "counter.rs:impl_Counte~", "insert": { "loc": "append", "body": "\n/// Returns true if the counter is at its maximum.\npub fn is_maxed(&self) → bool {\n\tself.value ≥ self.max\n}\n" } }`
|
|
154
|
+
Lands at the end of the impl body, before the closing `}`.
|
|
155
|
+
# Delete a chunk
|
|
156
|
+
`{ "path": "counter.rs:impl_Counte.fn_decrem#arve", "delete": true }`
|
|
157
|
+
Removes the method including its doc comment and signature.
|
|
282
158
|
</examples>
|
|
@@ -16,14 +16,13 @@ Provides debugger access through the Debug Adapter Protocol (DAP). Use this to l
|
|
|
16
16
|
- Adapter availability depends on local binaries. Common built-ins: `gdb`, `lldb-dap`, `python -m debugpy.adapter`, `dlv dap`.
|
|
17
17
|
</caution>
|
|
18
18
|
|
|
19
|
-
<
|
|
19
|
+
<examples>
|
|
20
|
+
# Launch and inspect hang
|
|
20
21
|
1. `debug(action: "launch", program: "./my_app")`
|
|
21
22
|
2. `debug(action: "set_breakpoint", file: "src/main.c", line: 42)`
|
|
22
23
|
3. `debug(action: "continue")`
|
|
23
24
|
4. If the program appears hung: `debug(action: "pause")`
|
|
24
25
|
5. Inspect state with `threads`, `stack_trace`, `scopes`, and `variables`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<example name="raw debugger command through repl">
|
|
26
|
+
# Raw debugger command through repl
|
|
28
27
|
`debug(action: "evaluate", expression: "info registers", context: "repl")`
|
|
29
|
-
</
|
|
28
|
+
</examples>
|