@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/tools/ast-grep.ts
CHANGED
|
@@ -15,7 +15,6 @@ import { createFileRecorder, formatResultPath } from "./file-recorder";
|
|
|
15
15
|
import { formatMatchLine } from "./match-line-format";
|
|
16
16
|
import type { OutputMeta } from "./output-meta";
|
|
17
17
|
import {
|
|
18
|
-
combineSearchGlobs,
|
|
19
18
|
hasGlobPathChars,
|
|
20
19
|
normalizePathLikeInput,
|
|
21
20
|
parseSearchPath,
|
|
@@ -24,6 +23,7 @@ import {
|
|
|
24
23
|
} from "./path-utils";
|
|
25
24
|
import {
|
|
26
25
|
dedupeParseErrors,
|
|
26
|
+
formatCodeFrameLine,
|
|
27
27
|
formatCount,
|
|
28
28
|
formatEmptyMessage,
|
|
29
29
|
formatErrorMessage,
|
|
@@ -35,14 +35,12 @@ import { ToolError } from "./tool-errors";
|
|
|
35
35
|
import { toolResult } from "./tool-result";
|
|
36
36
|
|
|
37
37
|
const astGrepSchema = Type.Object({
|
|
38
|
-
pat: Type.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
offset: Type.Optional(Type.Number({ description: "Skip first N matches", default: 0 })),
|
|
45
|
-
context: Type.Optional(Type.Number({ description: "Context lines around each match" })),
|
|
38
|
+
pat: Type.String({ description: "ast pattern", examples: ["console.log($$$)"] }),
|
|
39
|
+
path: Type.String({
|
|
40
|
+
description: "file, directory, glob, or comma-separated paths to search",
|
|
41
|
+
examples: ["src/", "src/foo.ts", "src/**/*.ts"],
|
|
42
|
+
}),
|
|
43
|
+
skip: Type.Optional(Type.Number({ description: "matches to skip", default: 0 })),
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
export interface AstGrepToolDetails {
|
|
@@ -55,6 +53,9 @@ export interface AstGrepToolDetails {
|
|
|
55
53
|
files?: string[];
|
|
56
54
|
fileMatches?: Array<{ path: string; count: number }>;
|
|
57
55
|
meta?: OutputMeta;
|
|
56
|
+
/** Pre-formatted text for the user-visible TUI render. Mirrors `result.text` lines but uses
|
|
57
|
+
* a `│` gutter and `*` to mark match lines. The TUI uses this directly so it never parses model-facing text. */
|
|
58
|
+
displayContent?: string;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolDetails> {
|
|
@@ -76,55 +77,48 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
76
77
|
_context?: AgentToolContext,
|
|
77
78
|
): Promise<AgentToolResult<AstGrepToolDetails>> {
|
|
78
79
|
return untilAborted(signal, async () => {
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
throw new ToolError("`pat` must
|
|
80
|
+
const pattern = params.pat.trim();
|
|
81
|
+
if (pattern.length === 0) {
|
|
82
|
+
throw new ToolError("`pat` must be a non-empty pattern");
|
|
82
83
|
}
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
const patterns = [pattern];
|
|
85
|
+
const skip = params.skip === undefined ? 0 : Math.floor(params.skip);
|
|
86
|
+
if (!Number.isFinite(skip) || skip < 0) {
|
|
87
|
+
throw new ToolError("skip must be a non-negative number");
|
|
86
88
|
}
|
|
87
|
-
const offset = params.offset === undefined ? 0 : Math.floor(params.offset);
|
|
88
|
-
if (!Number.isFinite(offset) || offset < 0) {
|
|
89
|
-
throw new ToolError("Offset must be a non-negative number");
|
|
90
|
-
}
|
|
91
|
-
const context = params.context === undefined ? undefined : Math.floor(params.context);
|
|
92
|
-
if (context !== undefined && (!Number.isFinite(context) || context < 0)) {
|
|
93
|
-
throw new ToolError("Context must be a non-negative number");
|
|
94
|
-
}
|
|
95
|
-
|
|
96
89
|
const formatScopePath = (targetPath: string): string => {
|
|
97
90
|
const relative = path.relative(this.session.cwd, targetPath).replace(/\\/g, "/");
|
|
98
91
|
return relative.length === 0 ? "." : relative;
|
|
99
92
|
};
|
|
100
93
|
let searchPath: string | undefined;
|
|
101
94
|
let scopePath: string | undefined;
|
|
102
|
-
let globFilter
|
|
103
|
-
const rawPath =
|
|
104
|
-
if (rawPath) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
95
|
+
let globFilter: string | undefined;
|
|
96
|
+
const rawPath = normalizePathLikeInput(params.path);
|
|
97
|
+
if (rawPath.length === 0) {
|
|
98
|
+
throw new ToolError("`path` must be a non-empty path or glob");
|
|
99
|
+
}
|
|
100
|
+
const internalRouter = this.session.internalRouter;
|
|
101
|
+
if (internalRouter?.canHandle(rawPath)) {
|
|
102
|
+
if (hasGlobPathChars(rawPath)) {
|
|
103
|
+
throw new ToolError(`Glob patterns are not supported for internal URLs: ${rawPath}`);
|
|
104
|
+
}
|
|
105
|
+
const resource = await internalRouter.resolve(rawPath);
|
|
106
|
+
if (!resource.sourcePath) {
|
|
107
|
+
throw new ToolError(`Cannot search internal URL without backing file: ${rawPath}`);
|
|
108
|
+
}
|
|
109
|
+
searchPath = resource.sourcePath;
|
|
110
|
+
scopePath = formatScopePath(searchPath);
|
|
111
|
+
} else {
|
|
112
|
+
const multiSearchPath = await resolveMultiSearchPath(rawPath, this.session.cwd, globFilter);
|
|
113
|
+
if (multiSearchPath) {
|
|
114
|
+
searchPath = multiSearchPath.basePath;
|
|
115
|
+
globFilter = multiSearchPath.glob;
|
|
116
|
+
scopePath = multiSearchPath.scopePath;
|
|
116
117
|
} else {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
scopePath = multiSearchPath.scopePath;
|
|
122
|
-
} else {
|
|
123
|
-
const parsedPath = parseSearchPath(rawPath);
|
|
124
|
-
searchPath = resolveToCwd(parsedPath.basePath, this.session.cwd);
|
|
125
|
-
globFilter = combineSearchGlobs(parsedPath.glob, globFilter);
|
|
126
|
-
scopePath = formatScopePath(searchPath);
|
|
127
|
-
}
|
|
118
|
+
const parsedPath = parseSearchPath(rawPath);
|
|
119
|
+
searchPath = resolveToCwd(parsedPath.basePath, this.session.cwd);
|
|
120
|
+
globFilter = parsedPath.glob;
|
|
121
|
+
scopePath = formatScopePath(searchPath);
|
|
128
122
|
}
|
|
129
123
|
}
|
|
130
124
|
|
|
@@ -140,13 +134,9 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
140
134
|
|
|
141
135
|
const result = await astGrep({
|
|
142
136
|
patterns,
|
|
143
|
-
lang: params.lang?.trim(),
|
|
144
137
|
path: resolvedSearchPath,
|
|
145
138
|
glob: globFilter,
|
|
146
|
-
|
|
147
|
-
limit,
|
|
148
|
-
offset,
|
|
149
|
-
context,
|
|
139
|
+
offset: skip,
|
|
150
140
|
includeMeta: true,
|
|
151
141
|
signal,
|
|
152
142
|
});
|
|
@@ -183,7 +173,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
183
173
|
|
|
184
174
|
if (result.matches.length === 0) {
|
|
185
175
|
const noMatchMessage = dedupedParseErrors.length
|
|
186
|
-
? "No matches found. Parse issues mean the query may be mis-scoped; narrow `path
|
|
176
|
+
? "No matches found. Parse issues mean the query may be mis-scoped; narrow `path` before concluding absence."
|
|
187
177
|
: "No matches found";
|
|
188
178
|
const parseMessage = dedupedParseErrors.length
|
|
189
179
|
? `\n${formatParseErrors(dedupedParseErrors).join("\n")}`
|
|
@@ -193,16 +183,22 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
193
183
|
|
|
194
184
|
const useHashLines = resolveFileDisplayMode(this.session).hashLines;
|
|
195
185
|
const outputLines: string[] = [];
|
|
186
|
+
const displayLines: string[] = [];
|
|
196
187
|
const renderMatchesForFile = (relativePath: string) => {
|
|
197
188
|
const fileMatches = matchesByFile.get(relativePath) ?? [];
|
|
189
|
+
const lineNumberWidth = fileMatches.reduce((width, match) => {
|
|
190
|
+
const lineCount = match.text.split("\n").length;
|
|
191
|
+
const endLine = match.startLine + lineCount - 1;
|
|
192
|
+
return Math.max(width, String(match.startLine).length, String(endLine).length);
|
|
193
|
+
}, 0);
|
|
198
194
|
for (const match of fileMatches) {
|
|
199
195
|
const matchLines = match.text.split("\n");
|
|
200
|
-
const lineNumbers = matchLines.map((_, index) => match.startLine + index);
|
|
201
|
-
const lineWidth = Math.max(...lineNumbers.map(value => value.toString().length));
|
|
202
|
-
const formatLine = (lineNumber: number, line: string, isMatch: boolean): string =>
|
|
203
|
-
formatMatchLine(lineNumber, line, isMatch, { useHashLines, lineWidth });
|
|
204
196
|
for (let index = 0; index < matchLines.length; index++) {
|
|
205
|
-
|
|
197
|
+
const lineNumber = match.startLine + index;
|
|
198
|
+
const isMatch = index === 0;
|
|
199
|
+
const line = matchLines[index] ?? "";
|
|
200
|
+
outputLines.push(formatMatchLine(lineNumber, line, isMatch, { useHashLines }));
|
|
201
|
+
displayLines.push(formatCodeFrameLine(isMatch ? "*" : " ", lineNumber, line, lineNumberWidth));
|
|
206
202
|
}
|
|
207
203
|
if (match.metaVariables && Object.keys(match.metaVariables).length > 0) {
|
|
208
204
|
const serializedMeta = Object.entries(match.metaVariables)
|
|
@@ -210,6 +206,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
210
206
|
.map(([key, value]) => `${key}=${value}`)
|
|
211
207
|
.join(", ");
|
|
212
208
|
outputLines.push(` meta: ${serializedMeta}`);
|
|
209
|
+
displayLines.push(` meta: ${serializedMeta}`);
|
|
213
210
|
}
|
|
214
211
|
fileMatchCounts.set(relativePath, (fileMatchCounts.get(relativePath) ?? 0) + 1);
|
|
215
212
|
}
|
|
@@ -229,18 +226,26 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
229
226
|
for (const relativePath of directoryFiles) {
|
|
230
227
|
if (outputLines.length > 0) {
|
|
231
228
|
outputLines.push("");
|
|
229
|
+
displayLines.push("");
|
|
232
230
|
}
|
|
233
|
-
|
|
231
|
+
const header = `# ${path.basename(relativePath)}`;
|
|
232
|
+
outputLines.push(header);
|
|
233
|
+
displayLines.push(header);
|
|
234
234
|
renderMatchesForFile(relativePath);
|
|
235
235
|
}
|
|
236
236
|
continue;
|
|
237
237
|
}
|
|
238
238
|
if (outputLines.length > 0) {
|
|
239
239
|
outputLines.push("");
|
|
240
|
+
displayLines.push("");
|
|
240
241
|
}
|
|
241
|
-
|
|
242
|
+
const dirHeader = `# ${directory}`;
|
|
243
|
+
outputLines.push(dirHeader);
|
|
244
|
+
displayLines.push(dirHeader);
|
|
242
245
|
for (const relativePath of directoryFiles) {
|
|
243
|
-
|
|
246
|
+
const fileHeader = `## └─ ${path.basename(relativePath)}`;
|
|
247
|
+
outputLines.push(fileHeader);
|
|
248
|
+
displayLines.push(fileHeader);
|
|
244
249
|
renderMatchesForFile(relativePath);
|
|
245
250
|
}
|
|
246
251
|
}
|
|
@@ -256,6 +261,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
256
261
|
path: filePath,
|
|
257
262
|
count: fileMatchCounts.get(filePath) ?? 0,
|
|
258
263
|
})),
|
|
264
|
+
displayContent: displayLines.join("\n"),
|
|
259
265
|
};
|
|
260
266
|
if (result.limitReached) {
|
|
261
267
|
outputLines.push("", "Result limit reached; narrow path pattern or increase limit.");
|
|
@@ -274,13 +280,9 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
274
280
|
// =============================================================================
|
|
275
281
|
|
|
276
282
|
interface AstGrepRenderArgs {
|
|
277
|
-
pat?: string
|
|
278
|
-
lang?: string;
|
|
283
|
+
pat?: string;
|
|
279
284
|
path?: string;
|
|
280
|
-
|
|
281
|
-
limit?: number;
|
|
282
|
-
offset?: number;
|
|
283
|
-
context?: number;
|
|
285
|
+
skip?: number;
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
const COLLAPSED_MATCH_LIMIT = PREVIEW_LIMITS.COLLAPSED_LINES * 2;
|
|
@@ -289,15 +291,10 @@ export const astGrepToolRenderer = {
|
|
|
289
291
|
inline: true,
|
|
290
292
|
renderCall(args: AstGrepRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
291
293
|
const meta: string[] = [];
|
|
292
|
-
if (args.lang) meta.push(`lang:${args.lang}`);
|
|
293
294
|
if (args.path) meta.push(`in ${args.path}`);
|
|
294
|
-
if (args.
|
|
295
|
-
if (args.limit !== undefined && args.limit > 0) meta.push(`limit:${args.limit}`);
|
|
296
|
-
if (args.offset !== undefined && args.offset > 0) meta.push(`offset:${args.offset}`);
|
|
297
|
-
if (args.context !== undefined) meta.push(`context:${args.context}`);
|
|
298
|
-
if (args.pat && args.pat.length > 1) meta.push(`${args.pat.length} patterns`);
|
|
295
|
+
if (args.skip !== undefined && args.skip > 0) meta.push(`skip:${args.skip}`);
|
|
299
296
|
|
|
300
|
-
const description = args.pat
|
|
297
|
+
const description = args.pat ?? "?";
|
|
301
298
|
const text = renderStatusLine({ icon: "pending", title: "AST Grep", description, meta }, uiTheme);
|
|
302
299
|
return new Text(text, 0, 0);
|
|
303
300
|
},
|
|
@@ -321,19 +318,14 @@ export const astGrepToolRenderer = {
|
|
|
321
318
|
const limitReached = details?.limitReached ?? false;
|
|
322
319
|
|
|
323
320
|
if (matchCount === 0) {
|
|
324
|
-
const description = args?.pat
|
|
321
|
+
const description = args?.pat;
|
|
325
322
|
const meta = ["0 matches"];
|
|
326
323
|
if (details?.scopePath) meta.push(`in ${details.scopePath}`);
|
|
327
324
|
if (filesSearched > 0) meta.push(`searched ${filesSearched}`);
|
|
328
325
|
const header = renderStatusLine({ icon: "warning", title: "AST Grep", description, meta }, uiTheme);
|
|
329
326
|
const lines = [header, formatEmptyMessage("No matches found", uiTheme)];
|
|
330
327
|
if (details?.parseErrors?.length) {
|
|
331
|
-
lines.push(
|
|
332
|
-
uiTheme.fg(
|
|
333
|
-
"warning",
|
|
334
|
-
"Query may be mis-scoped; narrow `path`/`glob` or set `lang` before concluding absence",
|
|
335
|
-
),
|
|
336
|
-
);
|
|
328
|
+
lines.push(uiTheme.fg("warning", "Query may be mis-scoped; narrow `path` before concluding absence"));
|
|
337
329
|
const capped = details.parseErrors.slice(0, PARSE_ERRORS_LIMIT);
|
|
338
330
|
for (const err of capped) {
|
|
339
331
|
lines.push(uiTheme.fg("warning", ` - ${err}`));
|
|
@@ -350,13 +342,13 @@ export const astGrepToolRenderer = {
|
|
|
350
342
|
if (details?.scopePath) meta.push(`in ${details.scopePath}`);
|
|
351
343
|
meta.push(`searched ${filesSearched}`);
|
|
352
344
|
if (limitReached) meta.push(uiTheme.fg("warning", "limit reached"));
|
|
353
|
-
const description = args?.pat
|
|
345
|
+
const description = args?.pat;
|
|
354
346
|
const header = renderStatusLine(
|
|
355
347
|
{ icon: limitReached ? "warning" : "success", title: "AST Grep", description, meta },
|
|
356
348
|
uiTheme,
|
|
357
349
|
);
|
|
358
350
|
|
|
359
|
-
const textContent = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
351
|
+
const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text ?? "";
|
|
360
352
|
const rawLines = textContent.split("\n");
|
|
361
353
|
const hasSeparators = rawLines.some(line => line.trim().length === 0);
|
|
362
354
|
const allGroups: string[][] = [];
|
package/src/tools/bash.ts
CHANGED
|
@@ -42,20 +42,19 @@ async function saveBashOriginalArtifact(session: ToolSession, originalText: stri
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const bashSchemaBase = Type.Object({
|
|
45
|
-
command: Type.String({ description: "
|
|
45
|
+
command: Type.String({ description: "command to execute", examples: ["ls -la", "echo hi"] }),
|
|
46
46
|
env: Type.Optional(
|
|
47
47
|
Type.Record(Type.String({ pattern: BASH_ENV_NAME_PATTERN.source }), Type.String(), {
|
|
48
|
-
description:
|
|
49
|
-
"Additional environment variables passed to the command and rendered inline as shell assignments; prefer this for multiline or quote-heavy content",
|
|
48
|
+
description: "extra env vars",
|
|
50
49
|
}),
|
|
51
50
|
),
|
|
52
|
-
timeout: Type.Optional(Type.Number({ description: "
|
|
53
|
-
cwd: Type.Optional(Type.String({ description: "
|
|
54
|
-
head: Type.Optional(Type.Number({ description: "
|
|
55
|
-
tail: Type.Optional(Type.Number({ description: "
|
|
51
|
+
timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 300 })),
|
|
52
|
+
cwd: Type.Optional(Type.String({ description: "working directory", examples: ["src/", "/tmp"] })),
|
|
53
|
+
head: Type.Optional(Type.Number({ description: "first n lines of output" })),
|
|
54
|
+
tail: Type.Optional(Type.Number({ description: "last n lines of output" })),
|
|
56
55
|
pty: Type.Optional(
|
|
57
56
|
Type.Boolean({
|
|
58
|
-
description: "
|
|
57
|
+
description: "run in pty mode",
|
|
59
58
|
}),
|
|
60
59
|
),
|
|
61
60
|
});
|
|
@@ -64,7 +63,7 @@ const bashSchemaWithAsync = Type.Object({
|
|
|
64
63
|
...bashSchemaBase.properties,
|
|
65
64
|
async: Type.Optional(
|
|
66
65
|
Type.Boolean({
|
|
67
|
-
description: "
|
|
66
|
+
description: "run in background",
|
|
68
67
|
}),
|
|
69
68
|
),
|
|
70
69
|
});
|
package/src/tools/browser.ts
CHANGED
|
@@ -361,12 +361,12 @@ function resolvePageClient(page: Page): PuppeteerCdpClient | null {
|
|
|
361
361
|
const puppeteerGetArgsSchema = Type.Array(
|
|
362
362
|
Type.Object({
|
|
363
363
|
selector: Type.String({
|
|
364
|
-
description:
|
|
365
|
-
|
|
364
|
+
description: "target element selector",
|
|
365
|
+
examples: ["aria/Sign in", "text/Continue", "xpath/...", "pierce/..."],
|
|
366
366
|
}),
|
|
367
|
-
attribute: Type.Optional(Type.String({ description: "
|
|
367
|
+
attribute: Type.Optional(Type.String({ description: "attribute name", examples: ["href", "data-id"] })),
|
|
368
368
|
}),
|
|
369
|
-
{ description: "
|
|
369
|
+
{ description: "batch get_* args", minItems: 1 },
|
|
370
370
|
);
|
|
371
371
|
|
|
372
372
|
const browserSchema = Type.Object({
|
|
@@ -393,56 +393,58 @@ const browserSchema = Type.Object({
|
|
|
393
393
|
"screenshot",
|
|
394
394
|
"close",
|
|
395
395
|
],
|
|
396
|
-
{ description: "
|
|
396
|
+
{ description: "action to perform" },
|
|
397
397
|
),
|
|
398
|
-
url: Type.Optional(Type.String({ description: "
|
|
398
|
+
url: Type.Optional(Type.String({ description: "url to navigate to", examples: ["https://example.com"] })),
|
|
399
399
|
selector: Type.Optional(
|
|
400
400
|
Type.String({
|
|
401
|
-
description:
|
|
402
|
-
|
|
401
|
+
description: "target element selector",
|
|
402
|
+
examples: ["aria/Sign in", "text/Continue", "xpath/...", "pierce/..."],
|
|
403
403
|
}),
|
|
404
404
|
),
|
|
405
|
-
element_id: Type.Optional(Type.Number({ description: "
|
|
406
|
-
include_all: Type.Optional(Type.Boolean({ description: "
|
|
407
|
-
viewport_only: Type.Optional(Type.Boolean({ description: "
|
|
405
|
+
element_id: Type.Optional(Type.Number({ description: "observed element id" })),
|
|
406
|
+
include_all: Type.Optional(Type.Boolean({ description: "include non-interactive nodes" })),
|
|
407
|
+
viewport_only: Type.Optional(Type.Boolean({ description: "limit to viewport" })),
|
|
408
408
|
args: Type.Optional(puppeteerGetArgsSchema),
|
|
409
|
-
script: Type.Optional(
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
409
|
+
script: Type.Optional(
|
|
410
|
+
Type.String({ description: "javascript expression", examples: ["document.title", "window.location.href"] }),
|
|
411
|
+
),
|
|
412
|
+
text: Type.Optional(Type.String({ description: "text to type", examples: ["hello world"] })),
|
|
413
|
+
value: Type.Optional(Type.String({ description: "value to set", examples: ["hello"] })),
|
|
414
|
+
attribute: Type.Optional(Type.String({ description: "attribute to read", examples: ["href", "data-id"] })),
|
|
415
|
+
key: Type.Optional(Type.String({ description: "keyboard key", examples: ["Enter", "Tab", "Escape"] })),
|
|
416
|
+
timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 30 })),
|
|
415
417
|
wait_until: Type.Optional(
|
|
416
418
|
StringEnum(["load", "domcontentloaded", "networkidle0", "networkidle2"], {
|
|
417
|
-
description: "
|
|
419
|
+
description: "navigation wait condition",
|
|
418
420
|
}),
|
|
419
421
|
),
|
|
420
|
-
full_page: Type.Optional(Type.Boolean({ description: "
|
|
422
|
+
full_page: Type.Optional(Type.Boolean({ description: "full page screenshot" })),
|
|
421
423
|
format: Type.Optional(
|
|
422
424
|
StringEnum(["text", "markdown"], {
|
|
423
|
-
description: "
|
|
425
|
+
description: "output format",
|
|
424
426
|
}),
|
|
425
427
|
),
|
|
426
|
-
path: Type.Optional(Type.String({ description: "
|
|
428
|
+
path: Type.Optional(Type.String({ description: "screenshot save path", examples: ["out.png"] })),
|
|
427
429
|
viewport: Type.Optional(
|
|
428
430
|
Type.Object({
|
|
429
|
-
width: Type.Number({ description: "
|
|
430
|
-
height: Type.Number({ description: "
|
|
431
|
-
device_scale_factor: Type.Optional(Type.Number({ description: "
|
|
431
|
+
width: Type.Number({ description: "viewport width" }),
|
|
432
|
+
height: Type.Number({ description: "viewport height" }),
|
|
433
|
+
device_scale_factor: Type.Optional(Type.Number({ description: "device scale factor" })),
|
|
432
434
|
}),
|
|
433
435
|
),
|
|
434
|
-
delta_x: Type.Optional(Type.Number({ description: "
|
|
435
|
-
delta_y: Type.Optional(Type.Number({ description: "
|
|
436
|
+
delta_x: Type.Optional(Type.Number({ description: "scroll delta x" })),
|
|
437
|
+
delta_y: Type.Optional(Type.Number({ description: "scroll delta y" })),
|
|
436
438
|
from_selector: Type.Optional(
|
|
437
439
|
Type.String({
|
|
438
|
-
description:
|
|
439
|
-
|
|
440
|
+
description: "drag start selector",
|
|
441
|
+
examples: ["aria/Drag handle"],
|
|
440
442
|
}),
|
|
441
443
|
),
|
|
442
444
|
to_selector: Type.Optional(
|
|
443
445
|
Type.String({
|
|
444
|
-
description:
|
|
445
|
-
|
|
446
|
+
description: "drag end selector",
|
|
447
|
+
examples: ["text/Drop zone"],
|
|
446
448
|
}),
|
|
447
449
|
),
|
|
448
450
|
});
|
package/src/tools/calculator.ts
CHANGED
|
@@ -31,11 +31,11 @@ type Token =
|
|
|
31
31
|
const calculatorSchema = Type.Object({
|
|
32
32
|
calculations: Type.Array(
|
|
33
33
|
Type.Object({
|
|
34
|
-
expression: Type.String({ description: "
|
|
35
|
-
prefix: Type.String({ description: "
|
|
36
|
-
suffix: Type.String({ description: "
|
|
34
|
+
expression: Type.String({ description: "math expression", examples: ["2 + 2", "sqrt(16)"] }),
|
|
35
|
+
prefix: Type.String({ description: "prefix text" }),
|
|
36
|
+
suffix: Type.String({ description: "suffix text" }),
|
|
37
37
|
}),
|
|
38
|
-
{ description: "
|
|
38
|
+
{ description: "calculations to evaluate" },
|
|
39
39
|
),
|
|
40
40
|
});
|
|
41
41
|
|
package/src/tools/cancel-job.ts
CHANGED
|
@@ -6,7 +6,7 @@ import cancelJobDescription from "../prompts/tools/cancel-job.md" with { type: "
|
|
|
6
6
|
import type { ToolSession } from "./index";
|
|
7
7
|
|
|
8
8
|
const cancelJobSchema = Type.Object({
|
|
9
|
-
job_id: Type.String({ description: "
|
|
9
|
+
job_id: Type.String({ description: "background job id", examples: ["job-1234"] }),
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
type CancelJobParams = Static<typeof cancelJobSchema>;
|
package/src/tools/checkpoint.ts
CHANGED
|
@@ -18,13 +18,13 @@ export interface CheckpointState {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const checkpointSchema = Type.Object({
|
|
21
|
-
goal: Type.String({ description: "
|
|
21
|
+
goal: Type.String({ description: "investigation goal", examples: ["investigate retry logic"] }),
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
type CheckpointParams = Static<typeof checkpointSchema>;
|
|
25
25
|
|
|
26
26
|
const rewindSchema = Type.Object({
|
|
27
|
-
report: Type.String({ description: "
|
|
27
|
+
report: Type.String({ description: "investigation findings" }),
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
type RewindParams = Static<typeof rewindSchema>;
|
package/src/tools/debug.ts
CHANGED
|
@@ -83,51 +83,55 @@ const debugSchema = Type.Object({
|
|
|
83
83
|
"terminate",
|
|
84
84
|
"sessions",
|
|
85
85
|
],
|
|
86
|
-
{ description: "
|
|
86
|
+
{ description: "dap debugger action" },
|
|
87
87
|
),
|
|
88
|
-
program: Type.Optional(Type.String({ description: "
|
|
89
|
-
args: Type.Optional(Type.Array(Type.String(), { description: "
|
|
90
|
-
adapter: Type.Optional(
|
|
91
|
-
|
|
92
|
-
file: Type.Optional(Type.String({ description: "Source file for source breakpoints" })),
|
|
93
|
-
line: Type.Optional(Type.Number({ description: "1-indexed source line for source breakpoints" })),
|
|
94
|
-
function: Type.Optional(Type.String({ description: "Function name for function breakpoints" })),
|
|
95
|
-
name: Type.Optional(Type.String({ description: "Variable or data name for data breakpoint info" })),
|
|
96
|
-
condition: Type.Optional(Type.String({ description: "Breakpoint condition expression" })),
|
|
97
|
-
hit_condition: Type.Optional(Type.String({ description: "Breakpoint hit condition expression" })),
|
|
98
|
-
expression: Type.Optional(Type.String({ description: "Expression to evaluate in debugger context" })),
|
|
99
|
-
context: Type.Optional(Type.String({ description: "Evaluate context (watch, repl, hover, variables, clipboard)" })),
|
|
100
|
-
frame_id: Type.Optional(Type.Number({ description: "Stack frame ID for scopes/evaluate" })),
|
|
101
|
-
scope_id: Type.Optional(Type.Number({ description: "Scope variablesReference for variables requests" })),
|
|
102
|
-
variable_ref: Type.Optional(Type.Number({ description: "Variable reference for variables requests" })),
|
|
103
|
-
pid: Type.Optional(Type.Number({ description: "Process ID for attach" })),
|
|
104
|
-
port: Type.Optional(Type.Number({ description: "Port for remote attach when adapter supports it" })),
|
|
105
|
-
host: Type.Optional(Type.String({ description: "Host for remote attach when adapter supports it" })),
|
|
106
|
-
levels: Type.Optional(Type.Number({ description: "Maximum stack frames to fetch" })),
|
|
107
|
-
memory_reference: Type.Optional(Type.String({ description: "Memory reference or address" })),
|
|
108
|
-
instruction_reference: Type.Optional(
|
|
109
|
-
Type.String({ description: "Instruction address/reference for instruction breakpoints" }),
|
|
88
|
+
program: Type.Optional(Type.String({ description: "program path", examples: ["./my_app", "src/main.py"] })),
|
|
89
|
+
args: Type.Optional(Type.Array(Type.String(), { description: "program arguments", examples: [["--verbose"]] })),
|
|
90
|
+
adapter: Type.Optional(
|
|
91
|
+
Type.String({ description: "debugger adapter", examples: ["gdb", "lldb-dap", "debugpy", "dlv"] }),
|
|
110
92
|
),
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
cwd: Type.Optional(Type.String({ description: "working directory", examples: ["src/"] })),
|
|
94
|
+
file: Type.Optional(Type.String({ description: "source file", examples: ["src/main.c"] })),
|
|
95
|
+
line: Type.Optional(Type.Number({ description: "source line", examples: [42] })),
|
|
96
|
+
function: Type.Optional(Type.String({ description: "function name", examples: ["main", "handle_request"] })),
|
|
97
|
+
name: Type.Optional(Type.String({ description: "variable or data name", examples: ["counter", "buffer"] })),
|
|
98
|
+
condition: Type.Optional(Type.String({ description: "breakpoint condition", examples: ["i == 10", "x > 0"] })),
|
|
99
|
+
hit_condition: Type.Optional(Type.String({ description: "hit condition" })),
|
|
100
|
+
expression: Type.Optional(Type.String({ description: "expression to evaluate", examples: ["x + 1", "obj.field"] })),
|
|
101
|
+
context: Type.Optional(
|
|
102
|
+
Type.String({ description: "evaluate context", examples: ["watch", "repl", "hover", "variables", "clipboard"] }),
|
|
103
|
+
),
|
|
104
|
+
frame_id: Type.Optional(Type.Number({ description: "stack frame id" })),
|
|
105
|
+
scope_id: Type.Optional(Type.Number({ description: "scope variables reference" })),
|
|
106
|
+
variable_ref: Type.Optional(Type.Number({ description: "variable reference" })),
|
|
107
|
+
pid: Type.Optional(Type.Number({ description: "process id for attach", examples: [12345] })),
|
|
108
|
+
port: Type.Optional(Type.Number({ description: "remote attach port", examples: [4711] })),
|
|
109
|
+
host: Type.Optional(Type.String({ description: "remote attach host", examples: ["127.0.0.1"] })),
|
|
110
|
+
levels: Type.Optional(Type.Number({ description: "max stack frames" })),
|
|
111
|
+
memory_reference: Type.Optional(
|
|
112
|
+
Type.String({ description: "memory reference or address", examples: ["0x7ffd1234"] }),
|
|
113
|
+
),
|
|
114
|
+
instruction_reference: Type.Optional(Type.String({ description: "instruction address or reference" })),
|
|
115
|
+
instruction_count: Type.Optional(Type.Number({ description: "instructions to disassemble" })),
|
|
116
|
+
instruction_offset: Type.Optional(Type.Number({ description: "instruction offset" })),
|
|
117
|
+
count: Type.Optional(Type.Number({ description: "bytes to read" })),
|
|
118
|
+
data: Type.Optional(Type.String({ description: "base64 memory payload" })),
|
|
119
|
+
data_id: Type.Optional(Type.String({ description: "data breakpoint id" })),
|
|
116
120
|
access_type: Type.Optional(
|
|
117
|
-
StringEnum(["read", "write", "readWrite"], { description: "
|
|
121
|
+
StringEnum(["read", "write", "readWrite"], { description: "data breakpoint access type" }),
|
|
118
122
|
),
|
|
119
|
-
command: Type.Optional(Type.String({ description: "
|
|
123
|
+
command: Type.Optional(Type.String({ description: "custom dap request command" })),
|
|
120
124
|
arguments: Type.Optional(
|
|
121
125
|
Type.Record(Type.String(), Type.Any(), {
|
|
122
|
-
description: "
|
|
126
|
+
description: "custom request arguments",
|
|
123
127
|
}),
|
|
124
128
|
),
|
|
125
|
-
offset: Type.Optional(Type.Number({ description: "
|
|
126
|
-
resolve_symbols: Type.Optional(Type.Boolean({ description: "
|
|
127
|
-
allow_partial: Type.Optional(Type.Boolean({ description: "
|
|
128
|
-
start_module: Type.Optional(Type.Number({ description: "
|
|
129
|
-
module_count: Type.Optional(Type.Number({ description: "
|
|
130
|
-
timeout: Type.Optional(Type.Number({ description: "
|
|
129
|
+
offset: Type.Optional(Type.Number({ description: "memory or instruction offset" })),
|
|
130
|
+
resolve_symbols: Type.Optional(Type.Boolean({ description: "resolve symbols during disassembly" })),
|
|
131
|
+
allow_partial: Type.Optional(Type.Boolean({ description: "allow partial writes" })),
|
|
132
|
+
start_module: Type.Optional(Type.Number({ description: "modules start index" })),
|
|
133
|
+
module_count: Type.Optional(Type.Number({ description: "max modules to fetch" })),
|
|
134
|
+
timeout: Type.Optional(Type.Number({ description: "per-request timeout seconds" })),
|
|
131
135
|
});
|
|
132
136
|
|
|
133
137
|
export type DebugParams = Static<typeof debugSchema>;
|
|
@@ -8,7 +8,7 @@ import { resolvePlanPath } from "./plan-mode-guard";
|
|
|
8
8
|
import { ToolError } from "./tool-errors";
|
|
9
9
|
|
|
10
10
|
const exitPlanModeSchema = Type.Object({
|
|
11
|
-
title: Type.String({ description: "
|
|
11
|
+
title: Type.String({ description: "final plan title", examples: ["WP_MIGRATION_PLAN"] }),
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
type ExitPlanModeParams = Static<typeof exitPlanModeSchema>;
|
package/src/tools/find.ts
CHANGED
|
@@ -30,11 +30,11 @@ import { toolResult } from "./tool-result";
|
|
|
30
30
|
|
|
31
31
|
const findSchema = Type.Object({
|
|
32
32
|
pattern: Type.String({
|
|
33
|
-
description:
|
|
34
|
-
|
|
33
|
+
description: "glob including search path",
|
|
34
|
+
examples: ["src/**/*.ts", "lib/*.json", "apps/,packages/", "*.ts"],
|
|
35
35
|
}),
|
|
36
|
-
hidden: Type.Optional(Type.Boolean({ description: "
|
|
37
|
-
limit: Type.Optional(Type.Number({ description: "
|
|
36
|
+
hidden: Type.Optional(Type.Boolean({ description: "include hidden files", default: true })),
|
|
37
|
+
limit: Type.Optional(Type.Number({ description: "max results", default: 1000 })),
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
export type FindToolInput = Static<typeof findSchema>;
|