@wrongstack/tools 0.1.9 → 0.2.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/dist/audit.js +19 -17
- package/dist/audit.js.map +1 -1
- package/dist/bash.js +2 -80
- package/dist/bash.js.map +1 -1
- package/dist/batch-tool-use.js +1 -1
- package/dist/batch-tool-use.js.map +1 -1
- package/dist/builtin.js +3002 -2867
- package/dist/builtin.js.map +1 -1
- package/dist/diff.js +8 -3
- package/dist/diff.js.map +1 -1
- package/dist/document.js +31 -5
- package/dist/document.js.map +1 -1
- package/dist/edit.js +1 -3
- package/dist/edit.js.map +1 -1
- package/dist/exec.js +26 -82
- package/dist/exec.js.map +1 -1
- package/dist/fetch.js +5 -1
- package/dist/fetch.js.map +1 -1
- package/dist/format.js +24 -18
- package/dist/format.js.map +1 -1
- package/dist/git.js +6 -6
- package/dist/git.js.map +1 -1
- package/dist/glob.js.map +1 -1
- package/dist/grep.js +23 -23
- package/dist/grep.js.map +1 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +310 -169
- package/dist/index.js.map +1 -1
- package/dist/install.js +31 -20
- package/dist/install.js.map +1 -1
- package/dist/json.js +4 -1
- package/dist/json.js.map +1 -1
- package/dist/lint.js +19 -17
- package/dist/lint.js.map +1 -1
- package/dist/logs.js +25 -22
- package/dist/logs.js.map +1 -1
- package/dist/memory.js.map +1 -1
- package/dist/mode.js +5 -1
- package/dist/mode.js.map +1 -1
- package/dist/outdated.js +10 -7
- package/dist/outdated.js.map +1 -1
- package/dist/patch.js +4 -9
- package/dist/patch.js.map +1 -1
- package/dist/read.js +5 -1
- package/dist/read.js.map +1 -1
- package/dist/replace.js +43 -30
- package/dist/replace.js.map +1 -1
- package/dist/scaffold.js +35 -20
- package/dist/scaffold.js.map +1 -1
- package/dist/search.js +5 -1
- package/dist/search.js.map +1 -1
- package/dist/test.js +17 -15
- package/dist/test.js.map +1 -1
- package/dist/todo.js.map +1 -1
- package/dist/tool-help.js +10 -8
- package/dist/tool-help.js.map +1 -1
- package/dist/tool-search.js.map +1 -1
- package/dist/tool-use.js +1 -1
- package/dist/tool-use.js.map +1 -1
- package/dist/tree.js +9 -1
- package/dist/tree.js.map +1 -1
- package/dist/typecheck.js +17 -15
- package/dist/typecheck.js.map +1 -1
- package/dist/write.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs4 from 'fs/promises';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { dirname } from 'path';
|
|
4
|
-
import { atomicWrite, unifiedDiff, detectNewlineStyle, normalizeToLf, toStyle, compileGlob, stripAnsi } from '@wrongstack/core';
|
|
4
|
+
import { atomicWrite, unifiedDiff, detectNewlineStyle, normalizeToLf, toStyle, compileGlob, buildChildEnv, stripAnsi, loadPlan, emptyPlan, clearPlan, savePlan, removePlanItem, setPlanItemStatus, addPlanItem, formatPlan } from '@wrongstack/core';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
6
|
import * as os from 'os';
|
|
7
7
|
import * as dns from 'dns/promises';
|
|
@@ -79,7 +79,11 @@ var readTool = {
|
|
|
79
79
|
const allLines = text.split(/\r\n|\r|\n/);
|
|
80
80
|
const total = allLines.length;
|
|
81
81
|
const offset = Math.max(1, input.offset ?? 1);
|
|
82
|
-
const limit = Math.max(
|
|
82
|
+
const limit = Math.max(0, Math.min(input.limit ?? 2e3, 5e3));
|
|
83
|
+
if (limit === 0) {
|
|
84
|
+
ctx.recordRead(absPath, stat9.mtimeMs);
|
|
85
|
+
return { text: "", total_lines: total, encoding: "utf8", truncated: total > 0 };
|
|
86
|
+
}
|
|
83
87
|
const slice = allLines.slice(offset - 1, offset - 1 + limit);
|
|
84
88
|
const truncated = offset - 1 + slice.length < total;
|
|
85
89
|
const width = String(offset + slice.length - 1).length;
|
|
@@ -174,9 +178,7 @@ var editTool = {
|
|
|
174
178
|
});
|
|
175
179
|
if (!stat9.isFile()) throw new Error(`edit: "${input.path}" is not a regular file`);
|
|
176
180
|
if (!ctx.hasRead(absPath)) {
|
|
177
|
-
throw new Error(
|
|
178
|
-
`edit: file "${input.path}" was not read in this session. Read it first.`
|
|
179
|
-
);
|
|
181
|
+
throw new Error(`edit: file "${input.path}" was not read in this session. Read it first.`);
|
|
180
182
|
}
|
|
181
183
|
const lastReadMtime = ctx.lastReadMtime(absPath);
|
|
182
184
|
const mtimeTolerance = process.platform === "win32" ? 2e3 : 1;
|
|
@@ -315,7 +317,10 @@ var replaceTool = {
|
|
|
315
317
|
description: "File(s) to target: single path, comma-separated list, or glob pattern"
|
|
316
318
|
},
|
|
317
319
|
glob: { type: "string", description: 'Additional glob filter (e.g. "*.ts")' },
|
|
318
|
-
replace_all: {
|
|
320
|
+
replace_all: {
|
|
321
|
+
type: "boolean",
|
|
322
|
+
description: "Replace all occurrences in each file (default: true)"
|
|
323
|
+
},
|
|
319
324
|
dry_run: { type: "boolean", description: "Preview changes without writing" }
|
|
320
325
|
},
|
|
321
326
|
required: ["pattern", "replacement", "files"]
|
|
@@ -325,7 +330,7 @@ var replaceTool = {
|
|
|
325
330
|
if (input.replacement === void 0) throw new Error("replace: replacement is required");
|
|
326
331
|
if (!input?.files) throw new Error("replace: files is required");
|
|
327
332
|
const replaceAll = input.replace_all ?? true;
|
|
328
|
-
const compiled = compileUserRegex(input.pattern,
|
|
333
|
+
const compiled = compileUserRegex(input.pattern, "g");
|
|
329
334
|
if (!compiled.ok) {
|
|
330
335
|
throw new Error(`replace: ${compiled.reason}`);
|
|
331
336
|
}
|
|
@@ -364,16 +369,25 @@ var replaceTool = {
|
|
|
364
369
|
const style = detectNewlineStyle(content);
|
|
365
370
|
const contentLf = normalizeToLf(content);
|
|
366
371
|
re.lastIndex = 0;
|
|
367
|
-
const
|
|
368
|
-
if (
|
|
369
|
-
const
|
|
372
|
+
const allMatches = [...contentLf.matchAll(re)];
|
|
373
|
+
if (allMatches.length === 0) continue;
|
|
374
|
+
const matches = replaceAll ? allMatches : allMatches.slice(0, 1);
|
|
375
|
+
const count = matches.length;
|
|
376
|
+
let newContentLf = contentLf;
|
|
377
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
378
|
+
const m = matches[i];
|
|
379
|
+
newContentLf = newContentLf.slice(0, m.index) + input.replacement + newContentLf.slice(m.index + m[0].length);
|
|
380
|
+
}
|
|
370
381
|
re.lastIndex = 0;
|
|
371
|
-
totalReplacements +=
|
|
382
|
+
totalReplacements += count;
|
|
372
383
|
if (!dryRun) {
|
|
373
384
|
const newContent = toStyle(newContentLf, style);
|
|
374
385
|
await atomicWrite(realPath, newContent, { mode: stat9.mode & 511 });
|
|
375
386
|
}
|
|
376
|
-
const diff = dryRun || matches.length > 0 ? unifiedDiff(content, toStyle(newContentLf, style), {
|
|
387
|
+
const diff = dryRun || matches.length > 0 ? unifiedDiff(content, toStyle(newContentLf, style), {
|
|
388
|
+
fromFile: absPath,
|
|
389
|
+
toFile: absPath
|
|
390
|
+
}) : void 0;
|
|
377
391
|
results.push({
|
|
378
392
|
path: absPath,
|
|
379
393
|
replacements: matches.length,
|
|
@@ -457,6 +471,7 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
457
471
|
for (const e of entries) {
|
|
458
472
|
if (DEFAULT_IGNORE.includes(e.name)) continue;
|
|
459
473
|
const full = path.join(dir, e.name);
|
|
474
|
+
if (e.isSymbolicLink()) continue;
|
|
460
475
|
if (e.isDirectory()) {
|
|
461
476
|
await walk(full);
|
|
462
477
|
} else if (e.isFile()) {
|
|
@@ -793,84 +808,6 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
793
808
|
};
|
|
794
809
|
}
|
|
795
810
|
|
|
796
|
-
// src/_env.ts
|
|
797
|
-
var ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
798
|
-
"PATH",
|
|
799
|
-
"HOME",
|
|
800
|
-
"USER",
|
|
801
|
-
"USERNAME",
|
|
802
|
-
"LOGNAME",
|
|
803
|
-
"SHELL",
|
|
804
|
-
"LANG",
|
|
805
|
-
"LC_ALL",
|
|
806
|
-
"LC_CTYPE",
|
|
807
|
-
"TERM",
|
|
808
|
-
"TZ",
|
|
809
|
-
"TMPDIR",
|
|
810
|
-
"TEMP",
|
|
811
|
-
"TMP",
|
|
812
|
-
"PWD",
|
|
813
|
-
"OLDPWD",
|
|
814
|
-
"COMSPEC",
|
|
815
|
-
"SYSTEMROOT",
|
|
816
|
-
"SYSTEMDRIVE",
|
|
817
|
-
"WINDIR",
|
|
818
|
-
"PROGRAMFILES",
|
|
819
|
-
"PROGRAMFILES(X86)",
|
|
820
|
-
"PROGRAMDATA",
|
|
821
|
-
"APPDATA",
|
|
822
|
-
"LOCALAPPDATA",
|
|
823
|
-
"USERPROFILE",
|
|
824
|
-
"PUBLIC",
|
|
825
|
-
"PATHEXT"
|
|
826
|
-
]);
|
|
827
|
-
var SECRET_NAME_PARTS = [
|
|
828
|
-
"TOKEN",
|
|
829
|
-
"SECRET",
|
|
830
|
-
"PASSWORD",
|
|
831
|
-
"PASSWD",
|
|
832
|
-
"AUTH",
|
|
833
|
-
"CRED",
|
|
834
|
-
"BEARER",
|
|
835
|
-
"COOKIE",
|
|
836
|
-
"PRIVATE"
|
|
837
|
-
];
|
|
838
|
-
function looksSecret(name) {
|
|
839
|
-
const upper = name.toUpperCase();
|
|
840
|
-
for (const p of SECRET_NAME_PARTS) {
|
|
841
|
-
if (upper.includes(p)) return true;
|
|
842
|
-
}
|
|
843
|
-
if (/(?:^|_)KEY(?:$|_|S$)/i.test(upper)) return true;
|
|
844
|
-
if (/API[_-]?KEY/i.test(upper)) return true;
|
|
845
|
-
if (/ACCESS[_-]?KEY/i.test(upper)) return true;
|
|
846
|
-
if (/SESSION[_-]?ID/i.test(upper) === false && /SESSION/i.test(upper)) {
|
|
847
|
-
return true;
|
|
848
|
-
}
|
|
849
|
-
return false;
|
|
850
|
-
}
|
|
851
|
-
function buildChildEnv(sessionId) {
|
|
852
|
-
const passthrough = process.env["WRONGSTACK_BASH_ENV_PASSTHROUGH"] === "1";
|
|
853
|
-
const out = {};
|
|
854
|
-
for (const [k, v] of Object.entries(process.env)) {
|
|
855
|
-
if (v === void 0) continue;
|
|
856
|
-
if (passthrough) {
|
|
857
|
-
out[k] = v;
|
|
858
|
-
continue;
|
|
859
|
-
}
|
|
860
|
-
const upper = k.toUpperCase();
|
|
861
|
-
if (ALLOWED_KEYS.has(upper)) {
|
|
862
|
-
out[k] = v;
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
if (looksSecret(upper)) continue;
|
|
866
|
-
if (upper.startsWith("NODE_") || upper.startsWith("NPM_") || upper.startsWith("PNPM_") || upper.startsWith("YARN_") || upper.startsWith("GIT_") || upper.startsWith("CI") || upper.startsWith("XDG_") || upper === "EDITOR" || upper === "VISUAL" || upper === "PAGER") {
|
|
867
|
-
out[k] = v;
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
if (sessionId) out["WRONGSTACK_SESSION_ID"] = sessionId;
|
|
871
|
-
return out;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
811
|
// src/bash.ts
|
|
875
812
|
var MAX_OUTPUT = 32768;
|
|
876
813
|
var DEFAULT_TIMEOUT = 3e4;
|
|
@@ -908,7 +845,7 @@ var bashTool = {
|
|
|
908
845
|
},
|
|
909
846
|
async *executeStream(input, ctx, opts) {
|
|
910
847
|
if (!input?.command) throw new Error("bash: command is required");
|
|
911
|
-
const timeoutMs = Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT, 6e5);
|
|
848
|
+
const timeoutMs = Math.max(1, Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT, 6e5));
|
|
912
849
|
const isWin = os.platform() === "win32";
|
|
913
850
|
const shell = isWin ? process.env["COMSPEC"] ?? "cmd.exe" : process.env["SHELL"] ?? "/bin/bash";
|
|
914
851
|
const args = isWin ? ["/c", input.command] : ["-c", input.command];
|
|
@@ -1058,7 +995,19 @@ var ALLOWED_COMMANDS = {
|
|
|
1058
995
|
npm: ["--version", "init", "install", "test", "run", "list", "pkg", "doctor"],
|
|
1059
996
|
pnpm: ["--version", "init", "install", "add", "remove", "exec", "list", "run", "dlx"],
|
|
1060
997
|
npx: ["--version"],
|
|
1061
|
-
git: [
|
|
998
|
+
git: [
|
|
999
|
+
"--version",
|
|
1000
|
+
"status",
|
|
1001
|
+
"log",
|
|
1002
|
+
"diff",
|
|
1003
|
+
"branch",
|
|
1004
|
+
"checkout",
|
|
1005
|
+
"stash",
|
|
1006
|
+
"add",
|
|
1007
|
+
"commit",
|
|
1008
|
+
"push",
|
|
1009
|
+
"pull"
|
|
1010
|
+
],
|
|
1062
1011
|
ls: ["-la", "-l", "-a"],
|
|
1063
1012
|
cat: [],
|
|
1064
1013
|
head: ["-n"],
|
|
@@ -1092,7 +1041,7 @@ var execTool = {
|
|
|
1092
1041
|
description: "Restricted shell that only runs pre-approved commands with constrained arguments. Safer alternative to `bash`.",
|
|
1093
1042
|
usageHint: "Set `command` (must be in allowlist). `args` passed through. For arbitrary shell access use the `bash` tool instead.",
|
|
1094
1043
|
permission: "confirm",
|
|
1095
|
-
mutating:
|
|
1044
|
+
mutating: true,
|
|
1096
1045
|
timeoutMs: TIMEOUT_MS,
|
|
1097
1046
|
inputSchema: {
|
|
1098
1047
|
type: "object",
|
|
@@ -1106,7 +1055,16 @@ var execTool = {
|
|
|
1106
1055
|
},
|
|
1107
1056
|
async execute(input, ctx, opts) {
|
|
1108
1057
|
const cmd = input.command.trim();
|
|
1109
|
-
if (!cmd)
|
|
1058
|
+
if (!cmd)
|
|
1059
|
+
return {
|
|
1060
|
+
command: cmd,
|
|
1061
|
+
args: [],
|
|
1062
|
+
stdout: "",
|
|
1063
|
+
stderr: "Empty command",
|
|
1064
|
+
exitCode: 1,
|
|
1065
|
+
truncated: false,
|
|
1066
|
+
allowed: false
|
|
1067
|
+
};
|
|
1110
1068
|
if (!(cmd in ALLOWED_COMMANDS)) {
|
|
1111
1069
|
return {
|
|
1112
1070
|
command: cmd,
|
|
@@ -1119,7 +1077,7 @@ var execTool = {
|
|
|
1119
1077
|
};
|
|
1120
1078
|
}
|
|
1121
1079
|
const args = (input.args ?? []).slice(0, MAX_ARGS);
|
|
1122
|
-
const timeout = Math.min(input.timeout ?? TIMEOUT_MS, TIMEOUT_MS);
|
|
1080
|
+
const timeout = Math.max(1, Math.min(input.timeout ?? TIMEOUT_MS, TIMEOUT_MS));
|
|
1123
1081
|
const requestedCwd = input.cwd ? path.resolve(ctx.projectRoot, input.cwd) : ctx.cwd;
|
|
1124
1082
|
const rel = path.relative(ctx.projectRoot, requestedCwd);
|
|
1125
1083
|
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
@@ -1272,7 +1230,11 @@ var fetchTool = {
|
|
|
1272
1230
|
if (/^image\/|^audio\/|^video\/|application\/octet-stream/.test(ct)) {
|
|
1273
1231
|
throw new Error(`fetch: refusing to read binary content-type "${ct}"`);
|
|
1274
1232
|
}
|
|
1275
|
-
yield {
|
|
1233
|
+
yield {
|
|
1234
|
+
type: "log",
|
|
1235
|
+
text: `HTTP ${res.status} ${ct}`,
|
|
1236
|
+
data: { status: res.status, contentType: ct }
|
|
1237
|
+
};
|
|
1276
1238
|
const reader = res.body?.getReader();
|
|
1277
1239
|
let received = 0;
|
|
1278
1240
|
const chunks = [];
|
|
@@ -1507,7 +1469,11 @@ var searchTool = {
|
|
|
1507
1469
|
if (!input?.query) throw new Error("search: query is required");
|
|
1508
1470
|
const num = Math.max(1, Math.min(input.num_results ?? DEFAULT_NUM, MAX_RESULTS));
|
|
1509
1471
|
const source = input.source ?? "duckduckgo";
|
|
1510
|
-
yield {
|
|
1472
|
+
yield {
|
|
1473
|
+
type: "log",
|
|
1474
|
+
text: `Querying ${source} for "${input.query}"\u2026`,
|
|
1475
|
+
data: { source, query: input.query }
|
|
1476
|
+
};
|
|
1511
1477
|
let output;
|
|
1512
1478
|
switch (source) {
|
|
1513
1479
|
case "duckduckgo":
|
|
@@ -1724,6 +1690,103 @@ var todoTool = {
|
|
|
1724
1690
|
};
|
|
1725
1691
|
}
|
|
1726
1692
|
};
|
|
1693
|
+
var planTool = {
|
|
1694
|
+
name: "plan",
|
|
1695
|
+
description: "Inspect or edit the strategic plan board for this session. Plans persist across resume (unlike todos). Use this to lay out the multi-step approach before diving in, then mark steps in_progress/done as the work proceeds.",
|
|
1696
|
+
usageHint: "Set action to one of: show | add | start | done | remove | clear. Pass `title` for add. Pass `target` (item id, 1-based index, or title substring) for start/done/remove. Always returns the formatted plan plus open/total counts.",
|
|
1697
|
+
permission: "auto",
|
|
1698
|
+
mutating: false,
|
|
1699
|
+
timeoutMs: 2e3,
|
|
1700
|
+
inputSchema: {
|
|
1701
|
+
type: "object",
|
|
1702
|
+
properties: {
|
|
1703
|
+
action: {
|
|
1704
|
+
type: "string",
|
|
1705
|
+
enum: ["show", "add", "start", "done", "remove", "clear"]
|
|
1706
|
+
},
|
|
1707
|
+
title: { type: "string", description: "Required when action = add." },
|
|
1708
|
+
details: { type: "string", description: "Optional extra context for add." },
|
|
1709
|
+
target: {
|
|
1710
|
+
type: "string",
|
|
1711
|
+
description: "Plan item id, 1-based index, or title substring. Required for start/done/remove."
|
|
1712
|
+
}
|
|
1713
|
+
},
|
|
1714
|
+
required: ["action"]
|
|
1715
|
+
},
|
|
1716
|
+
async execute(input, ctx) {
|
|
1717
|
+
const planPath = ctx.meta["plan.path"];
|
|
1718
|
+
if (typeof planPath !== "string" || !planPath) {
|
|
1719
|
+
return {
|
|
1720
|
+
ok: false,
|
|
1721
|
+
message: "Plan storage path is not configured for this session.",
|
|
1722
|
+
plan: "",
|
|
1723
|
+
count: 0,
|
|
1724
|
+
open: 0
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
const sessionId = ctx.session?.id ?? "unknown";
|
|
1728
|
+
let plan = await loadPlan(planPath) ?? emptyPlan(sessionId);
|
|
1729
|
+
switch (input.action) {
|
|
1730
|
+
case "show":
|
|
1731
|
+
break;
|
|
1732
|
+
case "add": {
|
|
1733
|
+
const title = input.title?.trim();
|
|
1734
|
+
if (!title) {
|
|
1735
|
+
return mkResult(plan, false, "add requires `title`.");
|
|
1736
|
+
}
|
|
1737
|
+
({ plan } = addPlanItem(plan, title, input.details?.trim() || void 0));
|
|
1738
|
+
await savePlan(planPath, plan);
|
|
1739
|
+
break;
|
|
1740
|
+
}
|
|
1741
|
+
case "start":
|
|
1742
|
+
case "done": {
|
|
1743
|
+
if (!input.target) {
|
|
1744
|
+
return mkResult(plan, false, `${input.action} requires \`target\` (id|index|substring).`);
|
|
1745
|
+
}
|
|
1746
|
+
const next = setPlanItemStatus(
|
|
1747
|
+
plan,
|
|
1748
|
+
input.target,
|
|
1749
|
+
input.action === "start" ? "in_progress" : "done"
|
|
1750
|
+
);
|
|
1751
|
+
if (next === plan) {
|
|
1752
|
+
return mkResult(plan, false, `No plan item matched "${input.target}".`);
|
|
1753
|
+
}
|
|
1754
|
+
plan = next;
|
|
1755
|
+
await savePlan(planPath, plan);
|
|
1756
|
+
break;
|
|
1757
|
+
}
|
|
1758
|
+
case "remove": {
|
|
1759
|
+
if (!input.target) {
|
|
1760
|
+
return mkResult(plan, false, "remove requires `target` (id|index|substring).");
|
|
1761
|
+
}
|
|
1762
|
+
const next = removePlanItem(plan, input.target);
|
|
1763
|
+
if (next === plan) {
|
|
1764
|
+
return mkResult(plan, false, `No plan item matched "${input.target}".`);
|
|
1765
|
+
}
|
|
1766
|
+
plan = next;
|
|
1767
|
+
await savePlan(planPath, plan);
|
|
1768
|
+
break;
|
|
1769
|
+
}
|
|
1770
|
+
case "clear":
|
|
1771
|
+
plan = clearPlan(plan);
|
|
1772
|
+
await savePlan(planPath, plan);
|
|
1773
|
+
break;
|
|
1774
|
+
default:
|
|
1775
|
+
return mkResult(plan, false, `Unknown action "${input.action}".`);
|
|
1776
|
+
}
|
|
1777
|
+
return mkResult(plan, true, `Plan ${input.action} ok.`);
|
|
1778
|
+
}
|
|
1779
|
+
};
|
|
1780
|
+
function mkResult(plan, ok, message) {
|
|
1781
|
+
const open = plan.items.filter((i) => i.status !== "done").length;
|
|
1782
|
+
return {
|
|
1783
|
+
ok,
|
|
1784
|
+
message,
|
|
1785
|
+
plan: formatPlan(plan),
|
|
1786
|
+
count: plan.items.length,
|
|
1787
|
+
open
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1727
1790
|
var TIMEOUT_MS4 = 3e4;
|
|
1728
1791
|
var MAX_OUTPUT3 = 1e5;
|
|
1729
1792
|
var gitTool = {
|
|
@@ -1820,11 +1883,7 @@ function buildArgs(input) {
|
|
|
1820
1883
|
...input.format === "short" || !input.format ? [] : []
|
|
1821
1884
|
];
|
|
1822
1885
|
case "diff":
|
|
1823
|
-
return [
|
|
1824
|
-
"diff",
|
|
1825
|
-
"--no-color",
|
|
1826
|
-
...files.length ? ["--", ...files] : []
|
|
1827
|
-
];
|
|
1886
|
+
return ["diff", "--no-color", ...files.length ? ["--", ...files] : []];
|
|
1828
1887
|
case "commit":
|
|
1829
1888
|
return [
|
|
1830
1889
|
"commit",
|
|
@@ -1835,7 +1894,11 @@ function buildArgs(input) {
|
|
|
1835
1894
|
case "branch":
|
|
1836
1895
|
return input.branch ? ["branch", input.branch] : ["branch"];
|
|
1837
1896
|
case "checkout":
|
|
1838
|
-
return [
|
|
1897
|
+
return [
|
|
1898
|
+
"checkout",
|
|
1899
|
+
...input.branch ? [input.branch] : [],
|
|
1900
|
+
...files.length ? ["--", ...files] : []
|
|
1901
|
+
];
|
|
1839
1902
|
case "stash":
|
|
1840
1903
|
return input.message ? ["stash", "push", "-m", input.message] : ["stash", "push"];
|
|
1841
1904
|
case "push":
|
|
@@ -1933,13 +1996,7 @@ var patchTool = {
|
|
|
1933
1996
|
});
|
|
1934
1997
|
const patchFile = path.join(tmpDir, "in.diff");
|
|
1935
1998
|
await fs4.writeFile(patchFile, input.patch, { mode: 384 });
|
|
1936
|
-
const args = [
|
|
1937
|
-
`-p${strip}`,
|
|
1938
|
-
"--merge",
|
|
1939
|
-
...dryRun ? ["--dry-run"] : [],
|
|
1940
|
-
"-i",
|
|
1941
|
-
patchFile
|
|
1942
|
-
];
|
|
1999
|
+
const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
|
|
1943
2000
|
const result = await runPatch(args, dir, opts.signal);
|
|
1944
2001
|
if (result.exitCode !== 0 && !dryRun) {
|
|
1945
2002
|
return {
|
|
@@ -1983,7 +2040,7 @@ function runPatch(args, cwd, signal) {
|
|
|
1983
2040
|
return new Promise((resolve4) => {
|
|
1984
2041
|
let stdout = "";
|
|
1985
2042
|
let stderr = "";
|
|
1986
|
-
const env = { ...
|
|
2043
|
+
const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
|
|
1987
2044
|
const child = spawn("patch", args, { cwd, signal, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
1988
2045
|
child.stdout?.on("data", (c) => {
|
|
1989
2046
|
stdout += c.toString();
|
|
@@ -2015,7 +2072,10 @@ var jsonTool = {
|
|
|
2015
2072
|
properties: {
|
|
2016
2073
|
file: { type: "string", description: "Path to JSON/JSON5/YAML file" },
|
|
2017
2074
|
data: { type: "string", description: "JSON/JSON5/YAML string (alternative to file)" },
|
|
2018
|
-
query: {
|
|
2075
|
+
query: {
|
|
2076
|
+
type: "string",
|
|
2077
|
+
description: 'JMESPath-like query (e.g. "a.b[0].c" or "a[*].name")'
|
|
2078
|
+
},
|
|
2019
2079
|
format: {
|
|
2020
2080
|
type: "string",
|
|
2021
2081
|
enum: ["json", "json5", "yaml"],
|
|
@@ -2208,7 +2268,12 @@ async function fileDiff(input, ctx, signal) {
|
|
|
2208
2268
|
input.context ?? 3;
|
|
2209
2269
|
const files = input.files ? (Array.isArray(input.files) ? input.files : input.files.split(",")).map((f) => f.trim()).filter(Boolean) : [];
|
|
2210
2270
|
if (files.length === 0) {
|
|
2211
|
-
return {
|
|
2271
|
+
return {
|
|
2272
|
+
diff: "No files specified",
|
|
2273
|
+
files: [],
|
|
2274
|
+
truncated: false,
|
|
2275
|
+
mode: input.mode ?? "unified"
|
|
2276
|
+
};
|
|
2212
2277
|
}
|
|
2213
2278
|
const results = [];
|
|
2214
2279
|
for (const file of files) {
|
|
@@ -2231,7 +2296,15 @@ ${formatUnified(lines)}`);
|
|
|
2231
2296
|
function formatUnified(lines, context) {
|
|
2232
2297
|
return lines.map((line, i) => ` ${line}`).join("\n");
|
|
2233
2298
|
}
|
|
2234
|
-
var DEFAULT_IGNORE4 = [
|
|
2299
|
+
var DEFAULT_IGNORE4 = [
|
|
2300
|
+
"node_modules",
|
|
2301
|
+
".git",
|
|
2302
|
+
"dist",
|
|
2303
|
+
"build",
|
|
2304
|
+
".next",
|
|
2305
|
+
"coverage",
|
|
2306
|
+
"__pycache__"
|
|
2307
|
+
];
|
|
2235
2308
|
var treeTool = {
|
|
2236
2309
|
name: "tree",
|
|
2237
2310
|
description: "Display directory structure as an ASCII tree. Shows files and folders with indentation.",
|
|
@@ -2396,6 +2469,7 @@ async function* spawnStream(opts) {
|
|
|
2396
2469
|
const child = spawn(opts.cmd, opts.args, {
|
|
2397
2470
|
cwd: opts.cwd,
|
|
2398
2471
|
signal: opts.signal,
|
|
2472
|
+
env: buildChildEnv(),
|
|
2399
2473
|
stdio: ["ignore", "pipe", "pipe"]
|
|
2400
2474
|
});
|
|
2401
2475
|
const queue = [];
|
|
@@ -2607,7 +2681,11 @@ var formatTool = {
|
|
|
2607
2681
|
};
|
|
2608
2682
|
return;
|
|
2609
2683
|
}
|
|
2610
|
-
yield {
|
|
2684
|
+
yield {
|
|
2685
|
+
type: "log",
|
|
2686
|
+
text: `Running ${detected}\u2026`,
|
|
2687
|
+
data: { fixer: detected, check: !!input.check }
|
|
2688
|
+
};
|
|
2611
2689
|
const args = ["format", "--write"];
|
|
2612
2690
|
if (input.check) args[args.length - 1] = "--check";
|
|
2613
2691
|
if (input.files) {
|
|
@@ -2894,7 +2972,10 @@ var installTool = {
|
|
|
2894
2972
|
description: "Save as regular, dev, or optional dependency"
|
|
2895
2973
|
},
|
|
2896
2974
|
cwd: { type: "string", description: "Working directory (default: cwd)" },
|
|
2897
|
-
dry_run: {
|
|
2975
|
+
dry_run: {
|
|
2976
|
+
type: "boolean",
|
|
2977
|
+
description: "Preview install without modifying (default: false)"
|
|
2978
|
+
},
|
|
2898
2979
|
global: { type: "boolean", description: "Install globally (default: false)" }
|
|
2899
2980
|
}
|
|
2900
2981
|
},
|
|
@@ -2922,9 +3003,15 @@ var installTool = {
|
|
|
2922
3003
|
} else {
|
|
2923
3004
|
args.push("install", ...globalFlag);
|
|
2924
3005
|
}
|
|
2925
|
-
const pkgList = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).map(
|
|
3006
|
+
const pkgList = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).map(
|
|
3007
|
+
(p) => p.trim()
|
|
3008
|
+
) : [];
|
|
2926
3009
|
if (pkgList.length > 0) args.push(...pkgList);
|
|
2927
|
-
yield {
|
|
3010
|
+
yield {
|
|
3011
|
+
type: "log",
|
|
3012
|
+
text: `Fetching ${pkgList.length || "all"} packages\u2026`,
|
|
3013
|
+
data: { phase: "fetch" }
|
|
3014
|
+
};
|
|
2928
3015
|
const result = yield* spawnStream({
|
|
2929
3016
|
cmd: pkgManager,
|
|
2930
3017
|
args,
|
|
@@ -3132,13 +3219,16 @@ function runOutdated(manager, args, cwd, signal) {
|
|
|
3132
3219
|
const result = parseOutdatedOutput(stdout, code ?? 0);
|
|
3133
3220
|
resolve4(result);
|
|
3134
3221
|
});
|
|
3135
|
-
child.on(
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3222
|
+
child.on(
|
|
3223
|
+
"error",
|
|
3224
|
+
(e) => resolve4({
|
|
3225
|
+
exit_code: 1,
|
|
3226
|
+
packages: [],
|
|
3227
|
+
total: 0,
|
|
3228
|
+
output: e.message,
|
|
3229
|
+
truncated: false
|
|
3230
|
+
})
|
|
3231
|
+
);
|
|
3142
3232
|
});
|
|
3143
3233
|
}
|
|
3144
3234
|
function parseOutdatedOutput(json, exitCode) {
|
|
@@ -3267,13 +3357,16 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
3267
3357
|
stream_mode: false
|
|
3268
3358
|
});
|
|
3269
3359
|
});
|
|
3270
|
-
child.on(
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3360
|
+
child.on(
|
|
3361
|
+
"error",
|
|
3362
|
+
(e) => resolve4({
|
|
3363
|
+
source: `docker:${service}`,
|
|
3364
|
+
entries: [],
|
|
3365
|
+
total: 0,
|
|
3366
|
+
truncated: false,
|
|
3367
|
+
stream_mode: false
|
|
3368
|
+
})
|
|
3369
|
+
);
|
|
3277
3370
|
});
|
|
3278
3371
|
}
|
|
3279
3372
|
var MAX_TAIL_LINES = 1e5;
|
|
@@ -3395,7 +3488,13 @@ var documentTool = {
|
|
|
3395
3488
|
try {
|
|
3396
3489
|
const content = await fs4.readFile(absPath, "utf8");
|
|
3397
3490
|
filesProcessed++;
|
|
3398
|
-
const processed = processFile(
|
|
3491
|
+
const processed = processFile(
|
|
3492
|
+
content,
|
|
3493
|
+
absPath,
|
|
3494
|
+
style,
|
|
3495
|
+
input.overwrite ?? false,
|
|
3496
|
+
input.target ?? "all"
|
|
3497
|
+
);
|
|
3399
3498
|
results.push(...processed);
|
|
3400
3499
|
itemsDocumented += processed.filter((r) => r.status === "documented").length;
|
|
3401
3500
|
} catch (e) {
|
|
@@ -3441,23 +3540,43 @@ function processFile(content, absPath, style, overwrite, target) {
|
|
|
3441
3540
|
if (target === "all" || target === "function") {
|
|
3442
3541
|
for (const m of content.matchAll(functionRegex)) {
|
|
3443
3542
|
if (!m[1]) continue;
|
|
3444
|
-
allMatches.push({
|
|
3543
|
+
allMatches.push({
|
|
3544
|
+
name: m[1],
|
|
3545
|
+
sig: m[2] ?? "",
|
|
3546
|
+
type: "function",
|
|
3547
|
+
line: content.slice(0, m.index).split("\n").length
|
|
3548
|
+
});
|
|
3445
3549
|
}
|
|
3446
3550
|
for (const m of content.matchAll(arrowRegex)) {
|
|
3447
3551
|
if (!m[1]) continue;
|
|
3448
|
-
allMatches.push({
|
|
3552
|
+
allMatches.push({
|
|
3553
|
+
name: m[1],
|
|
3554
|
+
sig: m[2] ?? "",
|
|
3555
|
+
type: "arrow",
|
|
3556
|
+
line: content.slice(0, m.index).split("\n").length
|
|
3557
|
+
});
|
|
3449
3558
|
}
|
|
3450
3559
|
}
|
|
3451
3560
|
if (target === "all" || target === "class") {
|
|
3452
3561
|
for (const m of content.matchAll(classRegex)) {
|
|
3453
3562
|
if (!m[1]) continue;
|
|
3454
|
-
allMatches.push({
|
|
3563
|
+
allMatches.push({
|
|
3564
|
+
name: m[1],
|
|
3565
|
+
sig: "",
|
|
3566
|
+
type: "class",
|
|
3567
|
+
line: content.slice(0, m.index).split("\n").length
|
|
3568
|
+
});
|
|
3455
3569
|
}
|
|
3456
3570
|
}
|
|
3457
3571
|
if (target === "all" || target === "type") {
|
|
3458
3572
|
for (const m of content.matchAll(typeRegex)) {
|
|
3459
3573
|
if (!m[1]) continue;
|
|
3460
|
-
allMatches.push({
|
|
3574
|
+
allMatches.push({
|
|
3575
|
+
name: m[1],
|
|
3576
|
+
sig: m[0] ?? "",
|
|
3577
|
+
type: "type",
|
|
3578
|
+
line: content.slice(0, m.index).split("\n").length
|
|
3579
|
+
});
|
|
3461
3580
|
}
|
|
3462
3581
|
}
|
|
3463
3582
|
for (const m of allMatches) {
|
|
@@ -3475,18 +3594,26 @@ var BUILT_IN_TEMPLATES = {
|
|
|
3475
3594
|
"npm-package": {
|
|
3476
3595
|
description: "Basic npm package with ESM",
|
|
3477
3596
|
files: {
|
|
3478
|
-
"package.json": JSON.stringify(
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3597
|
+
"package.json": JSON.stringify(
|
|
3598
|
+
{
|
|
3599
|
+
name: "{{name}}",
|
|
3600
|
+
version: "0.1.1",
|
|
3601
|
+
type: "module",
|
|
3602
|
+
main: "./dist/index.js",
|
|
3603
|
+
scripts: { build: "tsc", test: "vitest run" },
|
|
3604
|
+
devDependencies: { typescript: "^5.0.0" }
|
|
3605
|
+
},
|
|
3606
|
+
null,
|
|
3607
|
+
2
|
|
3608
|
+
),
|
|
3609
|
+
"tsconfig.json": JSON.stringify(
|
|
3610
|
+
{
|
|
3611
|
+
compilerOptions: { target: "ES2022", module: "ESNext", strict: true },
|
|
3612
|
+
include: ["src"]
|
|
3613
|
+
},
|
|
3614
|
+
null,
|
|
3615
|
+
2
|
|
3616
|
+
),
|
|
3490
3617
|
"src/index.ts": `export function hello() {
|
|
3491
3618
|
return 'Hello from {{name}}';
|
|
3492
3619
|
}
|
|
@@ -3505,13 +3632,17 @@ describe('hello', () => {
|
|
|
3505
3632
|
"cli-tool": {
|
|
3506
3633
|
description: "CLI tool with argparse",
|
|
3507
3634
|
files: {
|
|
3508
|
-
"package.json": JSON.stringify(
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3635
|
+
"package.json": JSON.stringify(
|
|
3636
|
+
{
|
|
3637
|
+
name: "{{name}}",
|
|
3638
|
+
version: "0.1.1",
|
|
3639
|
+
type: "module",
|
|
3640
|
+
bin: { "{{name}}": "./src/index.js" },
|
|
3641
|
+
scripts: { build: "tsc", start: "node dist/index.js" }
|
|
3642
|
+
},
|
|
3643
|
+
null,
|
|
3644
|
+
2
|
|
3645
|
+
),
|
|
3515
3646
|
"src/index.ts": `#!/usr/bin/env node
|
|
3516
3647
|
|
|
3517
3648
|
async function main() {
|
|
@@ -3624,7 +3755,10 @@ async function handleBuiltIn(name, templateFiles, cwd, dryRun, vars) {
|
|
|
3624
3755
|
function substituteVars(content, name, vars) {
|
|
3625
3756
|
let result = content;
|
|
3626
3757
|
result = result.replace(/\{\{name\}\}/g, name.toLowerCase().replace(/\s+/g, "-"));
|
|
3627
|
-
result = result.replace(
|
|
3758
|
+
result = result.replace(
|
|
3759
|
+
/\{\{Name\}\}/g,
|
|
3760
|
+
name.replace(/(?:^|[-_\s]+)([a-z])/g, (_, c) => c.toUpperCase())
|
|
3761
|
+
);
|
|
3628
3762
|
for (const [k, v] of Object.entries(vars)) {
|
|
3629
3763
|
result = result.replace(new RegExp(`\\{\\{${k}\\}\\}`, "g"), v);
|
|
3630
3764
|
}
|
|
@@ -3704,7 +3838,7 @@ var toolUseTool = {
|
|
|
3704
3838
|
description: "Execute a specific tool by name with given input. Useful when the agent knows exactly which tool to call.",
|
|
3705
3839
|
usageHint: "Set `tool` with exact tool name and `input` with the tool parameters. Returns result or error.",
|
|
3706
3840
|
permission: "confirm",
|
|
3707
|
-
mutating:
|
|
3841
|
+
mutating: true,
|
|
3708
3842
|
timeoutMs: 6e4,
|
|
3709
3843
|
inputSchema: {
|
|
3710
3844
|
type: "object",
|
|
@@ -3772,7 +3906,7 @@ var batchToolUseTool = {
|
|
|
3772
3906
|
description: "Execute multiple tool calls in sequence or parallel. Returns all results.",
|
|
3773
3907
|
usageHint: "Set `calls` array with tool names and inputs. `stop_on_error` halts on first failure. `parallel` runs concurrently (default: true).",
|
|
3774
3908
|
permission: "confirm",
|
|
3775
|
-
mutating:
|
|
3909
|
+
mutating: true,
|
|
3776
3910
|
timeoutMs: 12e4,
|
|
3777
3911
|
inputSchema: {
|
|
3778
3912
|
type: "object",
|
|
@@ -3911,14 +4045,16 @@ var toolHelpTool = {
|
|
|
3911
4045
|
return {
|
|
3912
4046
|
tool: tool.name,
|
|
3913
4047
|
help: formatToolHelp(tool, format, includeExamples),
|
|
3914
|
-
tools: [
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
4048
|
+
tools: [
|
|
4049
|
+
{
|
|
4050
|
+
name: tool.name,
|
|
4051
|
+
description: tool.description,
|
|
4052
|
+
usageHint: tool.usageHint ?? "",
|
|
4053
|
+
inputSchema: tool.inputSchema,
|
|
4054
|
+
permission: tool.permission,
|
|
4055
|
+
mutating: tool.mutating
|
|
4056
|
+
}
|
|
4057
|
+
],
|
|
3922
4058
|
total: 1
|
|
3923
4059
|
};
|
|
3924
4060
|
}
|
|
@@ -4110,7 +4246,11 @@ ${mode.description}`
|
|
|
4110
4246
|
};
|
|
4111
4247
|
}
|
|
4112
4248
|
default:
|
|
4113
|
-
return {
|
|
4249
|
+
return {
|
|
4250
|
+
action: input.action,
|
|
4251
|
+
success: false,
|
|
4252
|
+
message: `Unknown action "${input.action}"`
|
|
4253
|
+
};
|
|
4114
4254
|
}
|
|
4115
4255
|
}
|
|
4116
4256
|
};
|
|
@@ -4129,6 +4269,7 @@ var builtinTools = [
|
|
|
4129
4269
|
fetchTool,
|
|
4130
4270
|
searchTool,
|
|
4131
4271
|
todoTool,
|
|
4272
|
+
planTool,
|
|
4132
4273
|
gitTool,
|
|
4133
4274
|
patchTool,
|
|
4134
4275
|
jsonTool,
|
|
@@ -4150,6 +4291,6 @@ var builtinTools = [
|
|
|
4150
4291
|
toolHelpTool
|
|
4151
4292
|
];
|
|
4152
4293
|
|
|
4153
|
-
export { auditTool, bashTool, batchToolUseTool, builtinTools, createModeTool, diffTool, documentTool, editTool, execTool, fetchTool, forgetTool, formatTool, gitTool, globTool, grepTool, installTool, jsonTool, lintTool, logsTool, outdatedTool, patchTool, readTool, rememberTool, replaceTool, scaffoldTool, searchTool, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
|
|
4294
|
+
export { auditTool, bashTool, batchToolUseTool, builtinTools, createModeTool, diffTool, documentTool, editTool, execTool, fetchTool, forgetTool, formatTool, gitTool, globTool, grepTool, installTool, jsonTool, lintTool, logsTool, outdatedTool, patchTool, planTool, readTool, rememberTool, replaceTool, scaffoldTool, searchTool, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
|
|
4154
4295
|
//# sourceMappingURL=index.js.map
|
|
4155
4296
|
//# sourceMappingURL=index.js.map
|