@chances-ai/tools 3.1.1 → 3.2.1
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/dist/builtins/_shared.d.ts +15 -0
- package/dist/builtins/_shared.d.ts.map +1 -0
- package/dist/builtins/_shared.js +52 -0
- package/dist/builtins/_shared.js.map +1 -0
- package/dist/builtins/bash.d.ts +3 -0
- package/dist/builtins/bash.d.ts.map +1 -0
- package/dist/builtins/bash.js +25 -0
- package/dist/builtins/bash.js.map +1 -0
- package/dist/builtins/diff.d.ts +3 -0
- package/dist/builtins/diff.d.ts.map +1 -0
- package/dist/builtins/diff.js +83 -0
- package/dist/builtins/diff.js.map +1 -0
- package/dist/builtins/edit.d.ts +3 -0
- package/dist/builtins/edit.d.ts.map +1 -0
- package/dist/builtins/edit.js +37 -0
- package/dist/builtins/edit.js.map +1 -0
- package/dist/builtins/glob.d.ts +3 -0
- package/dist/builtins/glob.d.ts.map +1 -0
- package/dist/builtins/glob.js +37 -0
- package/dist/builtins/glob.js.map +1 -0
- package/dist/builtins/grep.d.ts +3 -0
- package/dist/builtins/grep.d.ts.map +1 -0
- package/dist/builtins/grep.js +80 -0
- package/dist/builtins/grep.js.map +1 -0
- package/dist/builtins/read.d.ts +3 -0
- package/dist/builtins/read.d.ts.map +1 -0
- package/dist/builtins/read.js +18 -0
- package/dist/builtins/read.js.map +1 -0
- package/dist/builtins/web-fetch.d.ts +4 -0
- package/dist/builtins/web-fetch.d.ts.map +1 -0
- package/dist/builtins/web-fetch.js +335 -0
- package/dist/builtins/web-fetch.js.map +1 -0
- package/dist/builtins/write.d.ts +3 -0
- package/dist/builtins/write.d.ts.map +1 -0
- package/dist/builtins/write.js +44 -0
- package/dist/builtins/write.js.map +1 -0
- package/dist/builtins.d.ts +6 -0
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +24 -353
- package/dist/builtins.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JSONValue } from "@chances-ai/runtime";
|
|
2
|
+
import type { ToolContext } from "../types.js";
|
|
3
|
+
/** Diff/write-preview cap: refuses to read either side of a comparison when it
|
|
4
|
+
* exceeds this many bytes, so a `write` against a generated 50 MB file doesn't
|
|
5
|
+
* stall the approval prompt on a synchronous read. */
|
|
6
|
+
export declare const PREVIEW_BYTE_CAP: number;
|
|
7
|
+
export declare function str(args: JSONValue, key: string): string;
|
|
8
|
+
export declare function optStr(args: JSONValue, key: string): string | undefined;
|
|
9
|
+
export declare function optNum(args: JSONValue, key: string): number | undefined;
|
|
10
|
+
export declare function optBool(args: JSONValue, key: string): boolean | undefined;
|
|
11
|
+
/** Resolves a path and refuses to escape the workspace root. */
|
|
12
|
+
export declare function safePath(ctx: ToolContext, p: string): string;
|
|
13
|
+
/** Render a string as a short JSON-quoted preview for permission prompts. */
|
|
14
|
+
export declare function preview(s: string): string;
|
|
15
|
+
//# sourceMappingURL=_shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/builtins/_shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;sDAEsD;AACtD,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,wBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKvE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOvE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAKzE;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
2
|
+
import { AppError, ErrorCode } from "@chances-ai/runtime";
|
|
3
|
+
/** Diff/write-preview cap: refuses to read either side of a comparison when it
|
|
4
|
+
* exceeds this many bytes, so a `write` against a generated 50 MB file doesn't
|
|
5
|
+
* stall the approval prompt on a synchronous read. */
|
|
6
|
+
export const PREVIEW_BYTE_CAP = 256 * 1024;
|
|
7
|
+
export function str(args, key) {
|
|
8
|
+
const v = args[key];
|
|
9
|
+
if (typeof v !== "string")
|
|
10
|
+
throw new AppError(ErrorCode.Tool, `Expected string arg "${key}"`);
|
|
11
|
+
return v;
|
|
12
|
+
}
|
|
13
|
+
export function optStr(args, key) {
|
|
14
|
+
const v = args[key];
|
|
15
|
+
if (v === undefined || v === null)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (typeof v !== "string")
|
|
18
|
+
throw new AppError(ErrorCode.Tool, `Expected string arg "${key}"`);
|
|
19
|
+
return v;
|
|
20
|
+
}
|
|
21
|
+
export function optNum(args, key) {
|
|
22
|
+
const v = args[key];
|
|
23
|
+
if (v === undefined || v === null)
|
|
24
|
+
return undefined;
|
|
25
|
+
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
26
|
+
throw new AppError(ErrorCode.Tool, `Expected number arg "${key}"`);
|
|
27
|
+
}
|
|
28
|
+
return v;
|
|
29
|
+
}
|
|
30
|
+
export function optBool(args, key) {
|
|
31
|
+
const v = args[key];
|
|
32
|
+
if (v === undefined || v === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
if (typeof v !== "boolean")
|
|
35
|
+
throw new AppError(ErrorCode.Tool, `Expected boolean arg "${key}"`);
|
|
36
|
+
return v;
|
|
37
|
+
}
|
|
38
|
+
/** Resolves a path and refuses to escape the workspace root. */
|
|
39
|
+
export function safePath(ctx, p) {
|
|
40
|
+
const abs = isAbsolute(p) ? p : resolve(ctx.cwd, p);
|
|
41
|
+
const rel = relative(ctx.workspaceRoot, abs);
|
|
42
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
43
|
+
throw new AppError(ErrorCode.Permission, `Path escapes workspace: ${p}`);
|
|
44
|
+
}
|
|
45
|
+
return abs;
|
|
46
|
+
}
|
|
47
|
+
/** Render a string as a short JSON-quoted preview for permission prompts. */
|
|
48
|
+
export function preview(s) {
|
|
49
|
+
const one = s.replace(/\s+/g, " ").trim();
|
|
50
|
+
return JSON.stringify(one.length > 40 ? one.slice(0, 40) + "…" : one);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=_shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/builtins/_shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/builtins/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,QAAQ,EAAE,IAqBtB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { str } from "./_shared.js";
|
|
3
|
+
export const bashTool = {
|
|
4
|
+
name: "bash",
|
|
5
|
+
description: "Run a shell command in the workspace.",
|
|
6
|
+
category: "shell",
|
|
7
|
+
parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] },
|
|
8
|
+
summarize: (args) => `bash: ${str(args, "command")}`,
|
|
9
|
+
async execute(args, ctx) {
|
|
10
|
+
const command = str(args, "command");
|
|
11
|
+
return new Promise((resolveP) => {
|
|
12
|
+
const child = spawn(command, { cwd: ctx.cwd, shell: true, signal: ctx.signal });
|
|
13
|
+
let out = "";
|
|
14
|
+
let err = "";
|
|
15
|
+
child.stdout.on("data", (d) => (out += d.toString()));
|
|
16
|
+
child.stderr.on("data", (d) => (err += d.toString()));
|
|
17
|
+
child.on("error", (e) => resolveP({ ok: false, output: e.message }));
|
|
18
|
+
child.on("close", (code) => {
|
|
19
|
+
const body = [out, err].filter(Boolean).join("\n").slice(0, 60_000);
|
|
20
|
+
resolveP({ ok: code === 0, output: body || `(exit ${code})` });
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/builtins/bash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,uCAAuC;IACpD,QAAQ,EAAE,OAAO;IACjB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE;IAClG,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;IACpD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrC,OAAO,IAAI,OAAO,CAAa,CAAC,QAAQ,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAChF,IAAI,GAAG,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACtD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACtD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;gBACpE,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/builtins/diff.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAKpD,eAAO,MAAM,QAAQ,EAAE,IA6EtB,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { diffStats, linesDiff } from "../diff.js";
|
|
3
|
+
import { PREVIEW_BYTE_CAP, optNum, optStr, safePath, str } from "./_shared.js";
|
|
4
|
+
const DIFF_DEFAULT_MAX_LINES = 60;
|
|
5
|
+
export const diffTool = {
|
|
6
|
+
name: "diff",
|
|
7
|
+
description: "Compare two workspace files, or a workspace file vs inline content, and return a unified-style preview. Use this to see what a proposed change would look like before calling 'write' or 'edit'. Exactly one of 'pathB' or 'content' must be provided.",
|
|
8
|
+
category: "file-read",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
pathA: { type: "string", description: "Path to the baseline file (workspace-relative or absolute under the workspace root)." },
|
|
13
|
+
pathB: { type: "string", description: "Path to the comparison file. Mutually exclusive with 'content'." },
|
|
14
|
+
content: { type: "string", description: "Inline content to compare against pathA. Mutually exclusive with 'pathB'." },
|
|
15
|
+
maxLines: { type: "number", description: `Cap on diff rows in the preview. Default ${DIFF_DEFAULT_MAX_LINES}.` },
|
|
16
|
+
},
|
|
17
|
+
required: ["pathA"],
|
|
18
|
+
},
|
|
19
|
+
summarize: (args) => {
|
|
20
|
+
const pathA = str(args, "pathA");
|
|
21
|
+
const pathB = optStr(args, "pathB");
|
|
22
|
+
const content = optStr(args, "content");
|
|
23
|
+
if (pathB)
|
|
24
|
+
return `diff ${pathA} vs ${pathB}`;
|
|
25
|
+
if (content !== undefined)
|
|
26
|
+
return `diff ${pathA} vs ⟨${content.length}-byte input⟩`;
|
|
27
|
+
return `diff ${pathA}`;
|
|
28
|
+
},
|
|
29
|
+
async execute(args, ctx) {
|
|
30
|
+
const pathARaw = str(args, "pathA");
|
|
31
|
+
const pathBRaw = optStr(args, "pathB");
|
|
32
|
+
const inlineRaw = optStr(args, "content");
|
|
33
|
+
const maxLines = optNum(args, "maxLines") ?? DIFF_DEFAULT_MAX_LINES;
|
|
34
|
+
if (pathBRaw === undefined && inlineRaw === undefined) {
|
|
35
|
+
return { ok: false, output: "diff requires either 'pathB' or 'content'" };
|
|
36
|
+
}
|
|
37
|
+
if (pathBRaw !== undefined && inlineRaw !== undefined) {
|
|
38
|
+
return { ok: false, output: "diff cannot accept both 'pathB' and 'content'" };
|
|
39
|
+
}
|
|
40
|
+
const pathA = safePath(ctx, pathARaw);
|
|
41
|
+
if (!existsSync(pathA))
|
|
42
|
+
return { ok: false, output: `No such file: ${pathARaw}` };
|
|
43
|
+
const sizeA = statSync(pathA).size;
|
|
44
|
+
let after;
|
|
45
|
+
let afterLabel;
|
|
46
|
+
let afterSize;
|
|
47
|
+
if (pathBRaw !== undefined) {
|
|
48
|
+
const pathB = safePath(ctx, pathBRaw);
|
|
49
|
+
if (!existsSync(pathB))
|
|
50
|
+
return { ok: false, output: `No such file: ${pathBRaw}` };
|
|
51
|
+
afterSize = statSync(pathB).size;
|
|
52
|
+
if (sizeA > PREVIEW_BYTE_CAP || afterSize > PREVIEW_BYTE_CAP) {
|
|
53
|
+
return {
|
|
54
|
+
ok: true,
|
|
55
|
+
output: `${pathARaw} (${sizeA} bytes) vs ${pathBRaw} (${afterSize} bytes) — diff preview skipped (one side over ${PREVIEW_BYTE_CAP} bytes).`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
after = readFileSync(pathB, "utf8");
|
|
59
|
+
afterLabel = pathBRaw;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
afterSize = inlineRaw.length;
|
|
63
|
+
if (sizeA > PREVIEW_BYTE_CAP || afterSize > PREVIEW_BYTE_CAP) {
|
|
64
|
+
return {
|
|
65
|
+
ok: true,
|
|
66
|
+
output: `${pathARaw} (${sizeA} bytes) vs ⟨inline⟩ (${afterSize} bytes) — diff preview skipped (one side over ${PREVIEW_BYTE_CAP} bytes).`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
after = inlineRaw;
|
|
70
|
+
afterLabel = "⟨inline⟩";
|
|
71
|
+
}
|
|
72
|
+
const before = readFileSync(pathA, "utf8");
|
|
73
|
+
if (before === after)
|
|
74
|
+
return { ok: true, output: `${pathARaw} and ${afterLabel} are identical` };
|
|
75
|
+
const { removed, added } = diffStats(before, after);
|
|
76
|
+
const hunk = linesDiff(before, after, maxLines);
|
|
77
|
+
return {
|
|
78
|
+
ok: true,
|
|
79
|
+
output: `--- ${pathARaw}\n+++ ${afterLabel}\n${hunk}\n(${removed} removed, ${added} added)`,
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/builtins/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/builtins/edit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,QAAQ,EAAE,IA6BtB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { linesDiff } from "../diff.js";
|
|
3
|
+
import { preview, safePath, str } from "./_shared.js";
|
|
4
|
+
export const editTool = {
|
|
5
|
+
name: "edit",
|
|
6
|
+
description: "Replace an exact, unique substring in a workspace file.",
|
|
7
|
+
category: "file-write",
|
|
8
|
+
parameters: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: { path: { type: "string" }, find: { type: "string" }, replace: { type: "string" } },
|
|
11
|
+
required: ["path", "find", "replace"],
|
|
12
|
+
},
|
|
13
|
+
summarize: (args) => {
|
|
14
|
+
const path = str(args, "path");
|
|
15
|
+
const find = str(args, "find");
|
|
16
|
+
const replace = str(args, "replace");
|
|
17
|
+
if (!find.includes("\n") && !replace.includes("\n")) {
|
|
18
|
+
return `edit ${path}: replace ${preview(find)} → ${preview(replace)}`;
|
|
19
|
+
}
|
|
20
|
+
return `edit ${path}\n${linesDiff(find, replace)}`;
|
|
21
|
+
},
|
|
22
|
+
async execute(args, ctx) {
|
|
23
|
+
const path = safePath(ctx, str(args, "path"));
|
|
24
|
+
if (!existsSync(path))
|
|
25
|
+
return { ok: false, output: `No such file: ${str(args, "path")}` };
|
|
26
|
+
const find = str(args, "find");
|
|
27
|
+
const content = readFileSync(path, "utf8");
|
|
28
|
+
const count = content.split(find).length - 1;
|
|
29
|
+
if (count === 0)
|
|
30
|
+
return { ok: false, output: `Substring not found in ${str(args, "path")}` };
|
|
31
|
+
if (count > 1)
|
|
32
|
+
return { ok: false, output: `Substring not unique (${count} matches)` };
|
|
33
|
+
writeFileSync(path, content.replace(find, str(args, "replace")));
|
|
34
|
+
return { ok: true, output: `Edited ${str(args, "path")}` };
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/builtins/edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,yDAAyD;IACtE,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC/F,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACtC;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;QAClB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpD,OAAO,QAAQ,IAAI,aAAa,OAAO,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACxE,CAAC;QACD,OAAO,QAAQ,IAAI,KAAK,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;IACrD,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QAC1F,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QAC7F,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,KAAK,WAAW,EAAE,CAAC;QACvF,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC7D,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/builtins/glob.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAKpD,eAAO,MAAM,QAAQ,EAAE,IAgCtB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { native } from "@chances-ai/native";
|
|
3
|
+
import { optNum, optStr, safePath, str } from "./_shared.js";
|
|
4
|
+
const GLOB_DEFAULT_LIMIT = 100;
|
|
5
|
+
export const globTool = {
|
|
6
|
+
name: "glob",
|
|
7
|
+
description: "List workspace files matching a glob pattern (e.g. '**/*.ts', 'src/**/*.tsx'). Honors common ignore directories (node_modules, .git, dist, target, .turbo).",
|
|
8
|
+
category: "search",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
pattern: { type: "string", description: "Glob pattern to match against relative file paths." },
|
|
13
|
+
path: { type: "string", description: "Sub-path within the workspace to search. Defaults to the workspace root." },
|
|
14
|
+
limit: { type: "number", description: `Max paths returned. Default ${GLOB_DEFAULT_LIMIT}.` },
|
|
15
|
+
},
|
|
16
|
+
required: ["pattern"],
|
|
17
|
+
},
|
|
18
|
+
summarize: (args) => {
|
|
19
|
+
const where = optStr(args, "path");
|
|
20
|
+
return `glob ${str(args, "pattern")}${where ? ` in ${where}` : ""}`;
|
|
21
|
+
},
|
|
22
|
+
async execute(args, ctx) {
|
|
23
|
+
const pattern = str(args, "pattern");
|
|
24
|
+
const subPath = optStr(args, "path");
|
|
25
|
+
const limit = optNum(args, "limit") ?? GLOB_DEFAULT_LIMIT;
|
|
26
|
+
const searchRoot = subPath ? safePath(ctx, subPath) : ctx.workspaceRoot;
|
|
27
|
+
if (!existsSync(searchRoot))
|
|
28
|
+
return { ok: false, output: `No such path: ${subPath}` };
|
|
29
|
+
const files = native.glob(pattern, searchRoot, { maxResults: limit + 1 });
|
|
30
|
+
if (files.length === 0)
|
|
31
|
+
return { ok: true, output: "No files matched" };
|
|
32
|
+
const shown = files.slice(0, limit);
|
|
33
|
+
const more = files.length > limit ? `\n…(more results, raise limit to see them)` : "";
|
|
34
|
+
return { ok: true, output: shown.join("\n") + more };
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/builtins/glob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAE7D,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EACT,6JAA6J;IAC/J,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oDAAoD,EAAE;YAC9F,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0EAA0E,EAAE;YACjH,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,kBAAkB,GAAG,EAAE;SAC7F;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO,QAAQ,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtE,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,kBAAkB,CAAC;QAE1D,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;QACxE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,OAAO,EAAE,EAAE,CAAC;QAEtF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QACxE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,4CAA4C,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IACvD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/builtins/grep.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAKpD,eAAO,MAAM,QAAQ,EAAE,IAgFtB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { native } from "@chances-ai/native";
|
|
3
|
+
import { optBool, optNum, optStr, preview, safePath, str } from "./_shared.js";
|
|
4
|
+
const GREP_DEFAULT_HEAD = 100;
|
|
5
|
+
export const grepTool = {
|
|
6
|
+
name: "grep",
|
|
7
|
+
description: "Search workspace files for a regex pattern. Returns matching file paths by default; set outputMode to 'content' for line-level matches or 'count' for per-file counts. Use this instead of shelling out to grep/rg.",
|
|
8
|
+
category: "search",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
pattern: { type: "string", description: "Regular expression to search for." },
|
|
13
|
+
path: { type: "string", description: "Sub-path within the workspace to search. Defaults to the workspace root." },
|
|
14
|
+
glob: { type: "string", description: "Optional glob to filter file paths (e.g. '**/*.ts')." },
|
|
15
|
+
outputMode: {
|
|
16
|
+
type: "string",
|
|
17
|
+
enum: ["files_with_matches", "content", "count"],
|
|
18
|
+
description: "files_with_matches (default): unique paths. content: 'path:line:text'. count: 'path:count'.",
|
|
19
|
+
},
|
|
20
|
+
caseInsensitive: { type: "boolean" },
|
|
21
|
+
multiline: { type: "boolean", description: "Allow . to match newlines." },
|
|
22
|
+
headLimit: { type: "number", description: `Max rows in the output. Default ${GREP_DEFAULT_HEAD}.` },
|
|
23
|
+
},
|
|
24
|
+
required: ["pattern"],
|
|
25
|
+
},
|
|
26
|
+
summarize: (args) => {
|
|
27
|
+
const pattern = str(args, "pattern");
|
|
28
|
+
const where = optStr(args, "path");
|
|
29
|
+
return `grep ${preview(pattern)}${where ? ` in ${where}` : ""}`;
|
|
30
|
+
},
|
|
31
|
+
async execute(args, ctx) {
|
|
32
|
+
const pattern = str(args, "pattern");
|
|
33
|
+
const subPath = optStr(args, "path");
|
|
34
|
+
const globFilter = optStr(args, "glob");
|
|
35
|
+
const outputMode = (optStr(args, "outputMode") ?? "files_with_matches");
|
|
36
|
+
const caseInsensitive = optBool(args, "caseInsensitive");
|
|
37
|
+
const multiline = optBool(args, "multiline");
|
|
38
|
+
const headLimit = optNum(args, "headLimit") ?? GREP_DEFAULT_HEAD;
|
|
39
|
+
const searchRoot = subPath ? safePath(ctx, subPath) : ctx.workspaceRoot;
|
|
40
|
+
if (!existsSync(searchRoot))
|
|
41
|
+
return { ok: false, output: `No such path: ${subPath}` };
|
|
42
|
+
// Per-file cap is chosen so that one dense file can't starve later files:
|
|
43
|
+
// - files_with_matches: bail at the first hit per file (we only need presence).
|
|
44
|
+
// - count: no cap; aggregating requires every match.
|
|
45
|
+
// - content: small cap so output stays diverse across files.
|
|
46
|
+
const perFileLimit = outputMode === "files_with_matches" ? 1 : outputMode === "count" ? undefined : 50;
|
|
47
|
+
let matches;
|
|
48
|
+
try {
|
|
49
|
+
matches = native.grep(pattern, searchRoot, {
|
|
50
|
+
caseInsensitive,
|
|
51
|
+
multiline,
|
|
52
|
+
glob: globFilter,
|
|
53
|
+
perFileLimit,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return { ok: false, output: `Invalid pattern: ${e.message}` };
|
|
58
|
+
}
|
|
59
|
+
if (matches.length === 0)
|
|
60
|
+
return { ok: true, output: "No matches found" };
|
|
61
|
+
if (outputMode === "files_with_matches") {
|
|
62
|
+
const files = Array.from(new Set(matches.map((m) => m.file)));
|
|
63
|
+
const shown = files.slice(0, headLimit);
|
|
64
|
+
const more = files.length > shown.length ? `\n…(${files.length - shown.length} more files)` : "";
|
|
65
|
+
return { ok: true, output: shown.join("\n") + more };
|
|
66
|
+
}
|
|
67
|
+
if (outputMode === "count") {
|
|
68
|
+
const counts = new Map();
|
|
69
|
+
for (const m of matches)
|
|
70
|
+
counts.set(m.file, (counts.get(m.file) ?? 0) + 1);
|
|
71
|
+
const entries = Array.from(counts.entries()).slice(0, headLimit);
|
|
72
|
+
const more = counts.size > entries.length ? `\n…(${counts.size - entries.length} more files)` : "";
|
|
73
|
+
return { ok: true, output: entries.map(([f, c]) => `${f}:${c}`).join("\n") + more };
|
|
74
|
+
}
|
|
75
|
+
const shown = matches.slice(0, headLimit);
|
|
76
|
+
const more = matches.length > shown.length ? `\n…(${matches.length - shown.length} more matches)` : "";
|
|
77
|
+
return { ok: true, output: shown.map((m) => `${m.file}:${m.line}:${m.text}`).join("\n") + more };
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=grep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep.js","sourceRoot":"","sources":["../../src/builtins/grep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/builtins/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,QAAQ,EAAE,IAatB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { safePath, str } from "./_shared.js";
|
|
3
|
+
export const readTool = {
|
|
4
|
+
name: "read",
|
|
5
|
+
description: "Read a UTF-8 text file from the workspace.",
|
|
6
|
+
category: "file-read",
|
|
7
|
+
parameters: { type: "object", properties: { path: { type: "string" } }, required: ["path"] },
|
|
8
|
+
summarize: (args) => `read ${str(args, "path")}`,
|
|
9
|
+
async execute(args, ctx) {
|
|
10
|
+
const path = safePath(ctx, str(args, "path"));
|
|
11
|
+
if (!existsSync(path))
|
|
12
|
+
return { ok: false, output: `No such file: ${str(args, "path")}` };
|
|
13
|
+
const content = readFileSync(path, "utf8");
|
|
14
|
+
const clipped = content.length > 60_000 ? content.slice(0, 60_000) + "\n…(truncated)" : content;
|
|
15
|
+
return { ok: true, output: clipped };
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/builtins/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,4CAA4C;IACzD,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE;IAC5F,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;IAChD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QAC1F,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACvC,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/builtins/web-fetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAwIpD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA6B/C;AA0FD,eAAO,MAAM,YAAY,EAAE,IA4E1B,CAAC"}
|