@wrongstack/tools 0.319.0 → 0.319.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/_edit-match.d.ts +1 -3
- package/dist/_util.d.ts +7 -0
- package/dist/audit.js +4 -4
- package/dist/bash.js +2 -2
- package/dist/builtin.d.ts +10 -0
- package/dist/builtin.js +44 -42
- package/dist/{chunk-2472NT76.js → chunk-2OXHS3KZ.js} +17 -5
- package/dist/{chunk-X5K3U6GI.js → chunk-3M7LLN7W.js} +71 -7
- package/dist/{chunk-VFF3Q5Z3.js → chunk-5EUJF3WC.js} +36 -8
- package/dist/{chunk-QZDOQRF7.js → chunk-64VIJPFV.js} +34 -13
- package/dist/{chunk-UMXVT7ST.js → chunk-6AAOT4PW.js} +58 -10
- package/dist/{chunk-WNUJR3H4.js → chunk-AKHYMB4V.js} +36 -12
- package/dist/{chunk-ZDUGI5BC.js → chunk-ATSKPZUK.js} +2 -2
- package/dist/{chunk-H6AWAZ2Y.js → chunk-B4HTSV6Z.js} +57 -6
- package/dist/{chunk-5ZYEGP2P.js → chunk-BK732J7I.js} +72 -27
- package/dist/{chunk-PMHVSHMU.js → chunk-BSJSNVGA.js} +73 -14
- package/dist/{chunk-KD5EHYA2.js → chunk-C2DQKVLO.js} +61 -28
- package/dist/{chunk-PRXZOIEW.js → chunk-CFLJFDYV.js} +100 -58
- package/dist/{chunk-TX3R5NVV.js → chunk-CMOUCKGC.js} +2 -2
- package/dist/{chunk-SYXW3Y5Z.js → chunk-DC4KMPJO.js} +2 -2
- package/dist/{chunk-MRKWZCHZ.js → chunk-DP6CXMJZ.js} +3 -3
- package/dist/{chunk-ODFVG54U.js → chunk-EADULOZV.js} +36 -12
- package/dist/{chunk-6RNIFLG4.js → chunk-ELRRTWNP.js} +38 -6
- package/dist/{chunk-YZHK4TLF.js → chunk-FQNXYA6W.js} +45 -6
- package/dist/{chunk-65EMYN5G.js → chunk-GMZYW52L.js} +3 -3
- package/dist/{chunk-HBM4QNXU.js → chunk-IU4DV2PA.js} +18 -8
- package/dist/{chunk-COUNXG4X.js → chunk-IWS56OY7.js} +30 -7
- package/dist/{chunk-Z4VBTVUM.js → chunk-IYKXK356.js} +98 -11
- package/dist/{chunk-OJ4FIBAN.js → chunk-JDPQOR7C.js} +14 -7
- package/dist/{chunk-TFMVHYJI.js → chunk-KY4PXYSO.js} +9 -15
- package/dist/{chunk-ZKSBHXVB.js → chunk-LOBRWKCR.js} +63 -14
- package/dist/{chunk-HWDB2G7J.js → chunk-MNP3GE7H.js} +38 -27
- package/dist/{chunk-MYRMD6PZ.js → chunk-O44IMQCN.js} +31 -7
- package/dist/{chunk-7WV3D4S3.js → chunk-OG2BEUBY.js} +69 -34
- package/dist/{chunk-VALQFAY2.js → chunk-OTINMOKK.js} +153 -40
- package/dist/{chunk-PQTONQ4P.js → chunk-QPNYDH5B.js} +19 -5
- package/dist/{chunk-4Q7LFU4T.js → chunk-RLMX75EM.js} +19 -8
- package/dist/{chunk-C3W3V54D.js → chunk-RNWUCZ2U.js} +53 -25
- package/dist/{chunk-RK47IWO3.js → chunk-RTZWBNTY.js} +59 -28
- package/dist/{chunk-UC3RKRIV.js → chunk-TTZOK6IY.js} +2 -2
- package/dist/{chunk-W4GAAI3M.js → chunk-UDVKRX5R.js} +2 -2
- package/dist/{chunk-Y7QXSE7N.js → chunk-UQQS3VNT.js} +43 -9
- package/dist/{chunk-D4CXUZIF.js → chunk-VD2LV5WO.js} +82 -13
- package/dist/{chunk-DPKTXJQS.js → chunk-VPALDFYM.js} +2 -2
- package/dist/{chunk-FJEQZHZN.js → chunk-W2CECGTG.js} +24 -14
- package/dist/{chunk-OYVPBPCL.js → chunk-X5FOFGXX.js} +72 -33
- package/dist/{chunk-CWALNI6K.js → chunk-X6KXNHUO.js} +1 -1
- package/dist/{chunk-OCUXN6Y3.js → chunk-XRNN44QY.js} +1 -1
- package/dist/{chunk-N5O3FK5Q.js → chunk-YOKD4GWJ.js} +67 -27
- package/dist/{chunk-QLF74MSV.js → chunk-ZUFHAHTE.js} +12 -6
- package/dist/codebase-index/index.js +7 -7
- package/dist/codebase-index/parser-worker-script.js +1 -1
- package/dist/codebase-index/project-server.js +3 -3
- package/dist/codebase-index/worker.js +2 -2
- package/dist/design.d.ts +1 -1
- package/dist/design.js +1 -1
- package/dist/diff.js +3 -2
- package/dist/document.js +2 -2
- package/dist/e2e.js +2 -2
- package/dist/edit.js +6 -6
- package/dist/exec.js +2 -2
- package/dist/fetch.js +2 -2
- package/dist/format.js +4 -4
- package/dist/git.js +2 -2
- package/dist/glob.js +2 -2
- package/dist/grep.d.ts +2 -0
- package/dist/grep.js +4 -2
- package/dist/index.js +44 -44
- package/dist/install.js +4 -4
- package/dist/json.js +2 -2
- package/dist/kanban-tool-types.d.ts +2 -0
- package/dist/kanban.js +2 -2
- package/dist/languages/index.js +2 -2
- package/dist/{legacy-bridge-EC7GM2IW.js → legacy-bridge-3T7SR4SK.js} +4 -4
- package/dist/lint.js +4 -4
- package/dist/logs.js +2 -2
- package/dist/outdated.js +4 -2
- package/dist/pack.js +43 -43
- package/dist/{parser-dispatch-3PDBKIQ7.js → parser-dispatch-QGC4HSP5.js} +2 -2
- package/dist/patch.js +6 -6
- package/dist/plan.js +4 -4
- package/dist/read.js +6 -6
- package/dist/replace.js +7 -6
- package/dist/scaffold.js +2 -2
- package/dist/search.js +1 -1
- package/dist/session-kanban.js +1 -1
- package/dist/task.js +4 -4
- package/dist/test.js +4 -4
- package/dist/todo.js +3 -3
- package/dist/tool-tier.js +44 -44
- package/dist/{tree-sitter-parser-FGKHJGSX.js → tree-sitter-parser-GILYQLS4.js} +2 -2
- package/dist/tree.js +2 -2
- package/dist/typecheck.js +4 -4
- package/dist/write.js +6 -6
- package/package.json +5 -5
|
@@ -20,10 +20,11 @@ import {
|
|
|
20
20
|
COMMAND_OUTPUT_MAX_BYTES,
|
|
21
21
|
normalizeCommandOutput,
|
|
22
22
|
safeResolveReal
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-ZUFHAHTE.js";
|
|
24
24
|
|
|
25
25
|
// src/exec.ts
|
|
26
26
|
import { spawn } from "node:child_process";
|
|
27
|
+
import { StringDecoder } from "node:string_decoder";
|
|
27
28
|
import {
|
|
28
29
|
emitProcessCompleted,
|
|
29
30
|
emitProcessOutput,
|
|
@@ -85,9 +86,9 @@ var RULES = [
|
|
|
85
86
|
level: "destructive",
|
|
86
87
|
test: (cmd, args) => {
|
|
87
88
|
if (cmd !== "powershell" && cmd !== "pwsh") return false;
|
|
88
|
-
const hasRecurse = argMatches(args, /^-(?:r|recurse)
|
|
89
|
-
const hasForce = argMatches(args, /^-(?:f|force)
|
|
90
|
-
if (argMatches(args, /^-whatif
|
|
89
|
+
const hasRecurse = argMatches(args, /^-(?:r|recurse)(?::\$true)?$/i);
|
|
90
|
+
const hasForce = argMatches(args, /^-(?:f|force)(?::\$true)?$/i);
|
|
91
|
+
if (argMatches(args, /^-whatif(?::\$true)?$/i)) return false;
|
|
91
92
|
return hasRecurse && hasForce;
|
|
92
93
|
},
|
|
93
94
|
reason: "Remove-Item with -Recurse -Force"
|
|
@@ -99,7 +100,9 @@ var RULES = [
|
|
|
99
100
|
test: (cmd, args) => {
|
|
100
101
|
if (cmd !== "powershell" && cmd !== "pwsh") return false;
|
|
101
102
|
return args.some(
|
|
102
|
-
(a) => /^(?:Format-Volume|Clear-Disk|Initialize-Disk|Remove-Partition|Clear-Volume)(?:\s|$)/i.test(
|
|
103
|
+
(a) => /^(?:Format-Volume|Clear-Disk|Initialize-Disk|Remove-Partition|Clear-Volume)(?:\s|$)/i.test(
|
|
104
|
+
a
|
|
105
|
+
)
|
|
103
106
|
);
|
|
104
107
|
},
|
|
105
108
|
reason: "PowerShell disk/volume partition destruction"
|
|
@@ -233,6 +236,7 @@ var RULES = [
|
|
|
233
236
|
continue;
|
|
234
237
|
}
|
|
235
238
|
if (a.startsWith("--force")) return true;
|
|
239
|
+
if (/^-[a-z]+$/i.test(a) && a.toLowerCase().includes("f")) return true;
|
|
236
240
|
}
|
|
237
241
|
return false;
|
|
238
242
|
},
|
|
@@ -1537,7 +1541,8 @@ var execTool = {
|
|
|
1537
1541
|
};
|
|
1538
1542
|
}
|
|
1539
1543
|
const args = (input.args ?? []).slice(0, MAX_ARGS);
|
|
1540
|
-
const
|
|
1544
|
+
const rawTimeout = typeof input.timeout === "number" && !Number.isNaN(input.timeout) ? input.timeout : DEFAULT_TIMEOUT_MS;
|
|
1545
|
+
const timeout = Math.max(1, Math.min(rawTimeout, MAX_TIMEOUT_MS));
|
|
1541
1546
|
const danger = detectDanger(cmd, args, dangerBypass);
|
|
1542
1547
|
const killCheck = await checkExecKillCommand(cmd, args);
|
|
1543
1548
|
if (killCheck.blocked) {
|
|
@@ -1582,7 +1587,30 @@ var execTool = {
|
|
|
1582
1587
|
};
|
|
1583
1588
|
}
|
|
1584
1589
|
const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
|
|
1590
|
+
if (signal.aborted) {
|
|
1591
|
+
return {
|
|
1592
|
+
command: cmd,
|
|
1593
|
+
args,
|
|
1594
|
+
stdout: "",
|
|
1595
|
+
stderr: "Aborted",
|
|
1596
|
+
exitCode: 124,
|
|
1597
|
+
truncated: false,
|
|
1598
|
+
allowed: true,
|
|
1599
|
+
danger
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1585
1602
|
return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id, danger);
|
|
1603
|
+
},
|
|
1604
|
+
async cleanup(_input, ctx) {
|
|
1605
|
+
const registry = getProcessRegistry();
|
|
1606
|
+
const sessionId = ctx.session?.id;
|
|
1607
|
+
if (!sessionId) return;
|
|
1608
|
+
for (const entry of registry.bySession(sessionId)) {
|
|
1609
|
+
if (entry.name !== "exec") continue;
|
|
1610
|
+
if (entry.child && entry.child.exitCode !== null) continue;
|
|
1611
|
+
if (entry.protected) continue;
|
|
1612
|
+
registry.kill(entry.pid, { force: true });
|
|
1613
|
+
}
|
|
1586
1614
|
}
|
|
1587
1615
|
};
|
|
1588
1616
|
function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
@@ -1602,6 +1630,20 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
1602
1630
|
let telemetryCompleted = false;
|
|
1603
1631
|
let timedOut = false;
|
|
1604
1632
|
const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT });
|
|
1633
|
+
if (signal.aborted) {
|
|
1634
|
+
spool.finalize();
|
|
1635
|
+
finish({
|
|
1636
|
+
command: cmd,
|
|
1637
|
+
args,
|
|
1638
|
+
stdout: "",
|
|
1639
|
+
stderr: "Aborted",
|
|
1640
|
+
exitCode: 124,
|
|
1641
|
+
truncated: false,
|
|
1642
|
+
allowed: true,
|
|
1643
|
+
danger
|
|
1644
|
+
});
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1605
1647
|
const resolved = resolveWin32Command(cmd);
|
|
1606
1648
|
const needsShell = isWin2 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
1607
1649
|
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
|
|
@@ -1711,19 +1753,25 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
1711
1753
|
if (signal.aborted) onAbort();
|
|
1712
1754
|
else signal.addEventListener("abort", onAbort, { once: true });
|
|
1713
1755
|
}
|
|
1756
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
1757
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
1714
1758
|
child.stdout?.on("data", (chunk) => {
|
|
1715
|
-
const text =
|
|
1759
|
+
const text = stdoutDecoder.write(chunk);
|
|
1716
1760
|
stdoutBytes += chunk.byteLength;
|
|
1717
1761
|
emitProcessOutput({ pid, stream: "stdout", chunk });
|
|
1718
|
-
if (
|
|
1719
|
-
|
|
1762
|
+
if (text.length > 0) {
|
|
1763
|
+
if (stdout.length < MAX_OUTPUT) stdout += text.slice(0, MAX_OUTPUT - stdout.length);
|
|
1764
|
+
spool.write(text);
|
|
1765
|
+
}
|
|
1720
1766
|
});
|
|
1721
1767
|
child.stderr?.on("data", (chunk) => {
|
|
1722
|
-
const text =
|
|
1768
|
+
const text = stderrDecoder.write(chunk);
|
|
1723
1769
|
stderrBytes += chunk.byteLength;
|
|
1724
1770
|
emitProcessOutput({ pid, stream: "stderr", chunk });
|
|
1725
|
-
if (
|
|
1726
|
-
|
|
1771
|
+
if (text.length > 0) {
|
|
1772
|
+
if (stderr.length < MAX_OUTPUT) stderr += text.slice(0, MAX_OUTPUT - stderr.length);
|
|
1773
|
+
spool.write(text);
|
|
1774
|
+
}
|
|
1727
1775
|
});
|
|
1728
1776
|
child.on("close", (code) => {
|
|
1729
1777
|
clearTimeout(timer);
|
|
@@ -1733,14 +1781,25 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
1733
1781
|
const exitCode = killed ? 124 : code ?? 1;
|
|
1734
1782
|
emitCompletedOnce(exitCode, pid);
|
|
1735
1783
|
registry.afterCall(durationMs, exitCode !== 0);
|
|
1784
|
+
const stdoutTail = stdoutDecoder.end();
|
|
1785
|
+
if (stdoutTail) {
|
|
1786
|
+
if (stdout.length < MAX_OUTPUT) stdout += stdoutTail.slice(0, MAX_OUTPUT - stdout.length);
|
|
1787
|
+
spool.write(stdoutTail);
|
|
1788
|
+
}
|
|
1789
|
+
const stderrTail = stderrDecoder.end();
|
|
1790
|
+
if (stderrTail) {
|
|
1791
|
+
if (stderr.length < MAX_OUTPUT) stderr += stderrTail.slice(0, MAX_OUTPUT - stderr.length);
|
|
1792
|
+
spool.write(stderrTail);
|
|
1793
|
+
}
|
|
1736
1794
|
const spooled = spool.finalize();
|
|
1795
|
+
const isTruncated = stdoutBytes > MAX_OUTPUT || stderrBytes > MAX_OUTPUT || Buffer.byteLength(stdout, "utf8") > COMMAND_OUTPUT_MAX_BYTES || Buffer.byteLength(stderr, "utf8") > COMMAND_OUTPUT_MAX_BYTES;
|
|
1737
1796
|
finish({
|
|
1738
1797
|
command: cmd,
|
|
1739
1798
|
args,
|
|
1740
1799
|
stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ""),
|
|
1741
1800
|
stderr: normalizeCommandOutput(stderr),
|
|
1742
1801
|
exitCode,
|
|
1743
|
-
truncated:
|
|
1802
|
+
truncated: isTruncated,
|
|
1744
1803
|
allowed: true,
|
|
1745
1804
|
danger
|
|
1746
1805
|
});
|
|
@@ -1760,4 +1819,4 @@ export {
|
|
|
1760
1819
|
getExecAllowlist,
|
|
1761
1820
|
execTool
|
|
1762
1821
|
};
|
|
1763
|
-
//# sourceMappingURL=chunk-
|
|
1822
|
+
//# sourceMappingURL=chunk-BSJSNVGA.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-NBDZMMG2.js";
|
|
6
6
|
import {
|
|
7
7
|
truncateMiddle
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZUFHAHTE.js";
|
|
9
9
|
|
|
10
10
|
// src/fetch.ts
|
|
11
11
|
import { FetchError, ToolError, ToolValidationError } from "@wrongstack/core/types";
|
|
@@ -79,13 +79,29 @@ var fetchTool = {
|
|
|
79
79
|
return final;
|
|
80
80
|
},
|
|
81
81
|
async *executeStream(input, ctx, opts) {
|
|
82
|
-
if (!input?.url) {
|
|
82
|
+
if (!input?.url || typeof input.url !== "string" || !input.url.trim()) {
|
|
83
83
|
throw new ToolValidationError({
|
|
84
|
-
message: "fetch: url is required",
|
|
84
|
+
message: "fetch: url is required and cannot be empty",
|
|
85
85
|
field: "url"
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
|
-
const
|
|
88
|
+
const trimmedUrl = input.url.trim();
|
|
89
|
+
let u;
|
|
90
|
+
try {
|
|
91
|
+
u = new URL(trimmedUrl);
|
|
92
|
+
} catch {
|
|
93
|
+
throw new ToolValidationError({
|
|
94
|
+
message: `fetch: invalid URL "${input.url}"`,
|
|
95
|
+
field: "url"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const ALLOWED_FORMATS = /* @__PURE__ */ new Set(["markdown", "text", "raw"]);
|
|
99
|
+
if (input.format !== void 0 && !ALLOWED_FORMATS.has(input.format)) {
|
|
100
|
+
throw new ToolValidationError({
|
|
101
|
+
message: `fetch: unsupported format "${input.format}". Allowed formats: markdown, text, raw`,
|
|
102
|
+
field: "format"
|
|
103
|
+
});
|
|
104
|
+
}
|
|
89
105
|
if (u.username || u.password) {
|
|
90
106
|
throw new ToolValidationError({
|
|
91
107
|
message: "fetch: URLs with embedded credentials (user:pass@host) are not allowed",
|
|
@@ -105,8 +121,9 @@ var fetchTool = {
|
|
|
105
121
|
});
|
|
106
122
|
}
|
|
107
123
|
await assertNotPrivate(u.hostname);
|
|
108
|
-
yield { type: "log", text: `GET ${
|
|
124
|
+
yield { type: "log", text: `GET ${trimmedUrl}` };
|
|
109
125
|
const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
|
|
126
|
+
signal.throwIfAborted();
|
|
110
127
|
const ctrl = new AbortController();
|
|
111
128
|
const timer = setTimeout(
|
|
112
129
|
() => ctrl.abort(
|
|
@@ -122,10 +139,10 @@ var fetchTool = {
|
|
|
122
139
|
try {
|
|
123
140
|
let res;
|
|
124
141
|
try {
|
|
125
|
-
res = await guardedFetch(
|
|
142
|
+
res = await guardedFetch(trimmedUrl, 5, combined);
|
|
126
143
|
} catch (err) {
|
|
127
144
|
if (signal.aborted) throw err;
|
|
128
|
-
throw describeFetchError(err,
|
|
145
|
+
throw describeFetchError(err, trimmedUrl, ctrl.signal.aborted);
|
|
129
146
|
}
|
|
130
147
|
const ct = res.headers.get("content-type") ?? "application/octet-stream";
|
|
131
148
|
if (/^image\/|^audio\/|^video\/|application\/octet-stream/.test(ct)) {
|
|
@@ -146,31 +163,46 @@ var fetchTool = {
|
|
|
146
163
|
let pendingBytes = 0;
|
|
147
164
|
const FLUSH_AT = 4 * 1024;
|
|
148
165
|
if (reader) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
try {
|
|
167
|
+
for (; ; ) {
|
|
168
|
+
const { value, done } = await reader.read();
|
|
169
|
+
if (done) break;
|
|
170
|
+
if (!value) continue;
|
|
171
|
+
received += value.byteLength;
|
|
172
|
+
pendingBytes += value.byteLength;
|
|
173
|
+
chunks.push(value);
|
|
174
|
+
if (pendingBytes >= FLUSH_AT) {
|
|
175
|
+
const recent = Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString(
|
|
176
|
+
"utf8"
|
|
177
|
+
);
|
|
178
|
+
yield {
|
|
179
|
+
type: "partial_output",
|
|
180
|
+
text: recent,
|
|
181
|
+
data: { received }
|
|
182
|
+
};
|
|
183
|
+
pendingBytes = 0;
|
|
184
|
+
}
|
|
185
|
+
if (received > MAX_BYTES) {
|
|
186
|
+
await reader.cancel().catch(() => {
|
|
187
|
+
});
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
164
190
|
}
|
|
165
|
-
|
|
191
|
+
} finally {
|
|
192
|
+
reader.releaseLock();
|
|
166
193
|
}
|
|
167
194
|
}
|
|
168
|
-
const text = Buffer.concat(chunks
|
|
169
|
-
const
|
|
195
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
196
|
+
const isHtml = ct.includes("text/html");
|
|
197
|
+
const isJson = /[\/+]json(;|$)/i.test(ct);
|
|
198
|
+
const format = input.format ?? (isHtml ? "markdown" : "text");
|
|
170
199
|
let content;
|
|
171
200
|
if (format === "raw") content = text;
|
|
172
|
-
else if (format === "markdown" &&
|
|
173
|
-
else if (
|
|
201
|
+
else if (format === "markdown" && isHtml) content = TD.turndown(text);
|
|
202
|
+
else if (format === "markdown" && isJson) content = `\`\`\`json
|
|
203
|
+
${prettyJson(text)}
|
|
204
|
+
\`\`\``;
|
|
205
|
+
else if (isJson) content = prettyJson(text);
|
|
174
206
|
else content = text;
|
|
175
207
|
yield {
|
|
176
208
|
type: "final",
|
|
@@ -226,6 +258,7 @@ function describeFetchError(err, url, timedOut) {
|
|
|
226
258
|
});
|
|
227
259
|
}
|
|
228
260
|
function prettyJson(s) {
|
|
261
|
+
if (!s || s.length > 5e5) return s;
|
|
229
262
|
try {
|
|
230
263
|
return JSON.stringify(JSON.parse(s), null, 2);
|
|
231
264
|
} catch {
|
|
@@ -236,4 +269,4 @@ function prettyJson(s) {
|
|
|
236
269
|
export {
|
|
237
270
|
fetchTool
|
|
238
271
|
};
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
272
|
+
//# sourceMappingURL=chunk-C2DQKVLO.js.map
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
} from "./chunk-FQZOHLG3.js";
|
|
4
4
|
import {
|
|
5
5
|
enqueueReindex
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DP6CXMJZ.js";
|
|
7
7
|
import {
|
|
8
8
|
safeResolveReal,
|
|
9
9
|
sha256hex,
|
|
10
10
|
truncateDiffPayload
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZUFHAHTE.js";
|
|
12
12
|
|
|
13
13
|
// src/edit.ts
|
|
14
14
|
import * as fs from "node:fs/promises";
|
|
@@ -41,43 +41,50 @@ var FUZZY_MAX_INTERIOR_CHARS = 2e3;
|
|
|
41
41
|
function findLadderMatches(fileLf, oldLf) {
|
|
42
42
|
const exact = [];
|
|
43
43
|
let idx = fileLf.indexOf(oldLf);
|
|
44
|
+
let currentLine = 1;
|
|
45
|
+
let lastPos = 0;
|
|
44
46
|
while (idx !== -1) {
|
|
45
|
-
|
|
47
|
+
while (lastPos < idx) {
|
|
48
|
+
const nextNewline = fileLf.indexOf("\n", lastPos);
|
|
49
|
+
if (nextNewline === -1 || nextNewline >= idx) break;
|
|
50
|
+
currentLine++;
|
|
51
|
+
lastPos = nextNewline + 1;
|
|
52
|
+
}
|
|
53
|
+
exact.push({ start: idx, end: idx + oldLf.length, startLine: currentLine });
|
|
46
54
|
idx = fileLf.indexOf(oldLf, idx + 1);
|
|
47
55
|
}
|
|
48
56
|
if (exact.length > 0) return { tier: "exact", matches: exact };
|
|
49
57
|
const fileLines = fileLf.split("\n");
|
|
50
|
-
const
|
|
51
|
-
|
|
58
|
+
const needleEndsWithNewline = oldLf.endsWith("\n");
|
|
59
|
+
const rawNeedleLines = oldLf.split("\n");
|
|
60
|
+
const needleLines = needleEndsWithNewline && rawNeedleLines[rawNeedleLines.length - 1] === "" ? rawNeedleLines.slice(0, -1) : rawNeedleLines;
|
|
61
|
+
if (needleLines.length === 0 || needleLines.length > fileLines.length) return void 0;
|
|
52
62
|
const offsets = lineOffsets(fileLines);
|
|
53
63
|
const fileTrimEnd = fileLines.map((l) => l.trimEnd());
|
|
54
64
|
const needleTrimEnd = needleLines.map((l) => l.trimEnd());
|
|
55
|
-
const trailing = windowScan(
|
|
65
|
+
const trailing = windowScan(
|
|
66
|
+
fileTrimEnd,
|
|
67
|
+
needleTrimEnd,
|
|
68
|
+
offsets,
|
|
69
|
+
fileLines,
|
|
70
|
+
(a, b) => a === b,
|
|
71
|
+
needleEndsWithNewline
|
|
72
|
+
);
|
|
56
73
|
if (trailing.length > 0) return { tier: "trailing-whitespace", matches: trailing };
|
|
57
74
|
const normalizedLen = needleTrimEnd.reduce((n, l) => n + l.trimStart().length, 0);
|
|
58
75
|
if (normalizedLen < MIN_NORMALIZED_NEEDLE_CHARS) return void 0;
|
|
59
76
|
const fileTrimmed = fileTrimEnd.map((l) => l.trimStart());
|
|
60
77
|
const needleTrimmed = needleTrimEnd.map((l) => l.trimStart());
|
|
61
|
-
const normalized = windowScan(
|
|
78
|
+
const normalized = windowScan(
|
|
79
|
+
fileTrimmed,
|
|
80
|
+
needleTrimmed,
|
|
81
|
+
offsets,
|
|
82
|
+
fileLines,
|
|
83
|
+
(a, b) => a === b,
|
|
84
|
+
needleEndsWithNewline
|
|
85
|
+
);
|
|
62
86
|
if (normalized.length > 0) return { tier: "whitespace-normalized", matches: normalized };
|
|
63
|
-
return fuzzyScan(fileLines, needleLines, offsets);
|
|
64
|
-
}
|
|
65
|
-
function lineAt(text, pos) {
|
|
66
|
-
if (pos < 512) {
|
|
67
|
-
let line2 = 1;
|
|
68
|
-
for (let i = 0; i < pos; i++) {
|
|
69
|
-
if (text.charCodeAt(i) === 10) line2++;
|
|
70
|
-
}
|
|
71
|
-
return line2;
|
|
72
|
-
}
|
|
73
|
-
let line = 1;
|
|
74
|
-
let search = 0;
|
|
75
|
-
while (true) {
|
|
76
|
-
const idx = text.indexOf("\n", search);
|
|
77
|
-
if (idx === -1 || idx >= pos) return line;
|
|
78
|
-
search = idx + 1;
|
|
79
|
-
line++;
|
|
80
|
-
}
|
|
87
|
+
return fuzzyScan(fileLines, needleLines, offsets, needleEndsWithNewline);
|
|
81
88
|
}
|
|
82
89
|
function lineOffsets(lines) {
|
|
83
90
|
const out = new Array(lines.length);
|
|
@@ -88,15 +95,17 @@ function lineOffsets(lines) {
|
|
|
88
95
|
}
|
|
89
96
|
return out;
|
|
90
97
|
}
|
|
91
|
-
function windowToMatch(fileLines, offsets, start, windowLen) {
|
|
98
|
+
function windowToMatch(fileLines, offsets, start, windowLen, includeTrailingNewline = false) {
|
|
92
99
|
const lastLine = start + windowLen - 1;
|
|
100
|
+
const lineEnd = offsets[lastLine] + fileLines[lastLine].length;
|
|
101
|
+
const end = includeTrailingNewline && lastLine < fileLines.length - 1 ? lineEnd + 1 : lineEnd;
|
|
93
102
|
return {
|
|
94
103
|
start: offsets[start],
|
|
95
|
-
end
|
|
104
|
+
end,
|
|
96
105
|
startLine: start + 1
|
|
97
106
|
};
|
|
98
107
|
}
|
|
99
|
-
function windowScan(comparisonLines, needleLines, offsets, originalLines, eq) {
|
|
108
|
+
function windowScan(comparisonLines, needleLines, offsets, originalLines, eq, includeTrailingNewline = false) {
|
|
100
109
|
const n = needleLines.length;
|
|
101
110
|
const out = [];
|
|
102
111
|
for (let i = 0; i + n <= comparisonLines.length; i++) {
|
|
@@ -108,28 +117,32 @@ function windowScan(comparisonLines, needleLines, offsets, originalLines, eq) {
|
|
|
108
117
|
}
|
|
109
118
|
}
|
|
110
119
|
if (all) {
|
|
111
|
-
out.push(windowToMatch(originalLines, offsets, i, n));
|
|
120
|
+
out.push(windowToMatch(originalLines, offsets, i, n, includeTrailingNewline));
|
|
112
121
|
i += n - 1;
|
|
113
122
|
}
|
|
114
123
|
}
|
|
115
124
|
return out;
|
|
116
125
|
}
|
|
117
|
-
function fuzzyScan(fileLines, needleLines, offsets) {
|
|
126
|
+
function fuzzyScan(fileLines, needleLines, offsets, includeTrailingNewline = false) {
|
|
118
127
|
const n = needleLines.length;
|
|
119
128
|
if (n < 3) return void 0;
|
|
120
129
|
const firstNeedle = needleLines[0].trim();
|
|
121
130
|
const lastNeedle = needleLines[n - 1].trim();
|
|
122
131
|
const needleInterior = needleLines.slice(1, -1).map((l) => l.trim()).join("\n");
|
|
123
132
|
if (needleInterior.length > FUZZY_MAX_INTERIOR_CHARS) return void 0;
|
|
133
|
+
const fileTrimmed = fileLines.map((l) => l.trim());
|
|
124
134
|
const candidates = [];
|
|
125
135
|
for (let i = 0; i + n <= fileLines.length; i++) {
|
|
126
|
-
if (
|
|
127
|
-
if (
|
|
128
|
-
const windowInterior =
|
|
136
|
+
if (fileTrimmed[i] !== firstNeedle) continue;
|
|
137
|
+
if (fileTrimmed[i + n - 1] !== lastNeedle) continue;
|
|
138
|
+
const windowInterior = fileTrimmed.slice(i + 1, i + n - 1).join("\n");
|
|
129
139
|
if (windowInterior.length > FUZZY_MAX_INTERIOR_CHARS) continue;
|
|
130
140
|
const score = similarity(needleInterior, windowInterior);
|
|
131
141
|
if (score >= FUZZY_MIN_SIMILARITY) {
|
|
132
|
-
candidates.push({
|
|
142
|
+
candidates.push({
|
|
143
|
+
match: windowToMatch(fileLines, offsets, i, n, includeTrailingNewline),
|
|
144
|
+
score
|
|
145
|
+
});
|
|
133
146
|
}
|
|
134
147
|
}
|
|
135
148
|
if (candidates.length === 0) return void 0;
|
|
@@ -150,21 +163,29 @@ function similarity(a, b) {
|
|
|
150
163
|
if (a === b) return 1;
|
|
151
164
|
const max = Math.max(a.length, b.length);
|
|
152
165
|
if (max === 0) return 1;
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
const lenDiff = Math.abs(a.length - b.length);
|
|
167
|
+
if (lenDiff / max > 1 - FUZZY_MIN_SIMILARITY) {
|
|
168
|
+
return 1 - lenDiff / max;
|
|
155
169
|
}
|
|
156
170
|
return 1 - levenshtein(a, b) / max;
|
|
157
171
|
}
|
|
158
172
|
function levenshtein(a, b) {
|
|
159
173
|
if (a.length === 0) return b.length;
|
|
160
174
|
if (b.length === 0) return a.length;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
175
|
+
if (a.length < b.length) {
|
|
176
|
+
const tmp = a;
|
|
177
|
+
a = b;
|
|
178
|
+
b = tmp;
|
|
179
|
+
}
|
|
180
|
+
const bLen = b.length;
|
|
181
|
+
const aLen = a.length;
|
|
182
|
+
let prev = new Int32Array(bLen + 1);
|
|
183
|
+
let cur = new Int32Array(bLen + 1);
|
|
184
|
+
for (let j = 0; j <= bLen; j++) prev[j] = j;
|
|
185
|
+
for (let i = 1; i <= aLen; i++) {
|
|
165
186
|
cur[0] = i;
|
|
166
187
|
const ca = a.charCodeAt(i - 1);
|
|
167
|
-
for (let j = 1; j <=
|
|
188
|
+
for (let j = 1; j <= bLen; j++) {
|
|
168
189
|
const cost = ca === b.charCodeAt(j - 1) ? 0 : 1;
|
|
169
190
|
cur[j] = Math.min(
|
|
170
191
|
prev[j] + 1,
|
|
@@ -172,9 +193,11 @@ function levenshtein(a, b) {
|
|
|
172
193
|
prev[j - 1] + cost
|
|
173
194
|
);
|
|
174
195
|
}
|
|
175
|
-
|
|
196
|
+
const tmp = prev;
|
|
197
|
+
prev = cur;
|
|
198
|
+
cur = tmp;
|
|
176
199
|
}
|
|
177
|
-
return prev[
|
|
200
|
+
return prev[bLen];
|
|
178
201
|
}
|
|
179
202
|
function firstLineIndent(text) {
|
|
180
203
|
for (const line of text.split("\n")) {
|
|
@@ -189,14 +212,17 @@ function adjustIndent(newLf, fromIndent, toIndent) {
|
|
|
189
212
|
if (toIndent.startsWith(fromIndent)) {
|
|
190
213
|
const extra = toIndent.slice(fromIndent.length);
|
|
191
214
|
return {
|
|
192
|
-
text: lines.map((l) => l.trim() === "" ?
|
|
215
|
+
text: lines.map((l) => l.trim() === "" ? "" : extra + l).join("\n"),
|
|
193
216
|
adjusted: true
|
|
194
217
|
};
|
|
195
218
|
}
|
|
196
219
|
if (fromIndent.startsWith(toIndent)) {
|
|
197
220
|
const remove = fromIndent.slice(toIndent.length);
|
|
198
221
|
return {
|
|
199
|
-
text: lines.map((l) =>
|
|
222
|
+
text: lines.map((l) => {
|
|
223
|
+
if (l.trim() === "") return "";
|
|
224
|
+
return l.startsWith(remove) ? l.slice(remove.length) : l;
|
|
225
|
+
}).join("\n"),
|
|
200
226
|
adjusted: true
|
|
201
227
|
};
|
|
202
228
|
}
|
|
@@ -204,34 +230,50 @@ function adjustIndent(newLf, fromIndent, toIndent) {
|
|
|
204
230
|
}
|
|
205
231
|
function nearestMatchHint(fileLf, oldLf) {
|
|
206
232
|
const fileLines = fileLf.split("\n");
|
|
207
|
-
const
|
|
208
|
-
|
|
233
|
+
const rawNeedle = oldLf.split("\n");
|
|
234
|
+
const needleLines = oldLf.endsWith("\n") && rawNeedle[rawNeedle.length - 1] === "" ? rawNeedle.slice(0, -1) : rawNeedle;
|
|
235
|
+
const n = needleLines.length;
|
|
236
|
+
if (n === 0 || n > fileLines.length) return void 0;
|
|
209
237
|
const needleTrimmed = needleLines.map((l) => l.trim());
|
|
238
|
+
const fileTrimmed = fileLines.map((l) => l.trim());
|
|
210
239
|
let bestScore = 0;
|
|
211
240
|
let bestStart = -1;
|
|
212
|
-
|
|
241
|
+
const maxI = fileLines.length - n;
|
|
242
|
+
for (let i = 0; i <= maxI; i++) {
|
|
213
243
|
let sum = 0;
|
|
214
|
-
|
|
215
|
-
|
|
244
|
+
let possible = true;
|
|
245
|
+
for (let j = 0; j < n; j++) {
|
|
246
|
+
sum += lineSimilarity(needleTrimmed[j], fileTrimmed[i + j]);
|
|
247
|
+
if (sum + (n - 1 - j) <= bestScore * n) {
|
|
248
|
+
possible = false;
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
216
251
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
bestScore
|
|
220
|
-
|
|
252
|
+
if (possible) {
|
|
253
|
+
const score = sum / n;
|
|
254
|
+
if (score > bestScore) {
|
|
255
|
+
bestScore = score;
|
|
256
|
+
bestStart = i;
|
|
257
|
+
}
|
|
221
258
|
}
|
|
222
259
|
}
|
|
223
260
|
if (bestStart === -1 || bestScore < 0.5) return void 0;
|
|
224
|
-
const snippet = fileLines.slice(bestStart, bestStart + Math.min(3,
|
|
261
|
+
const snippet = fileLines.slice(bestStart, bestStart + Math.min(3, n)).map((l) => l.length > 120 ? `${l.slice(0, 120)}\u2026` : l).join("\n");
|
|
225
262
|
return { line: bestStart + 1, snippet };
|
|
226
263
|
}
|
|
227
|
-
function
|
|
264
|
+
function lineSimilarity(a, b) {
|
|
228
265
|
if (a === b) return 1;
|
|
229
266
|
const max = Math.max(a.length, b.length);
|
|
230
267
|
if (max === 0) return 1;
|
|
268
|
+
if (a.includes(b) || b.includes(a)) {
|
|
269
|
+
return Math.min(a.length, b.length) / max;
|
|
270
|
+
}
|
|
231
271
|
let p = 0;
|
|
232
272
|
const lim = Math.min(a.length, b.length);
|
|
233
273
|
while (p < lim && a.charCodeAt(p) === b.charCodeAt(p)) p++;
|
|
234
|
-
|
|
274
|
+
let s = 0;
|
|
275
|
+
while (s < lim - p && a.charCodeAt(a.length - 1 - s) === b.charCodeAt(b.length - 1 - s)) s++;
|
|
276
|
+
return (p + s) / max;
|
|
235
277
|
}
|
|
236
278
|
|
|
237
279
|
// src/edit.ts
|
|
@@ -473,4 +515,4 @@ Compare this against your old_string and retry with the file's actual text.` : "
|
|
|
473
515
|
export {
|
|
474
516
|
editTool
|
|
475
517
|
};
|
|
476
|
-
//# sourceMappingURL=chunk-
|
|
518
|
+
//# sourceMappingURL=chunk-CFLJFDYV.js.map
|
|
@@ -863,7 +863,7 @@ async function dispatch(file, content, lang) {
|
|
|
863
863
|
case "shell":
|
|
864
864
|
case "elixir": {
|
|
865
865
|
try {
|
|
866
|
-
const { parseSymbols: parseSymbols2 } = await import("./tree-sitter-parser-
|
|
866
|
+
const { parseSymbols: parseSymbols2 } = await import("./tree-sitter-parser-GILYQLS4.js");
|
|
867
867
|
const parsed = await parseSymbols2({ file, content, lang });
|
|
868
868
|
if (parsed.symbols.length > 0) return parsed;
|
|
869
869
|
} catch {
|
|
@@ -889,4 +889,4 @@ export {
|
|
|
889
889
|
parseFileContent,
|
|
890
890
|
parseFilesContent
|
|
891
891
|
};
|
|
892
|
-
//# sourceMappingURL=chunk-
|
|
892
|
+
//# sourceMappingURL=chunk-CMOUCKGC.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
builtinTools
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OTINMOKK.js";
|
|
4
4
|
|
|
5
5
|
// src/pack.ts
|
|
6
6
|
var builtinToolsPack = {
|
|
@@ -12,4 +12,4 @@ var builtinToolsPack = {
|
|
|
12
12
|
export {
|
|
13
13
|
builtinToolsPack
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=chunk-
|
|
15
|
+
//# sourceMappingURL=chunk-DC4KMPJO.js.map
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
projectIndexServerBuildId,
|
|
10
10
|
projectIndexServerEndpoint,
|
|
11
11
|
projectIndexServerMetadataPath
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UDVKRX5R.js";
|
|
13
13
|
import {
|
|
14
14
|
CircuitOpenError,
|
|
15
15
|
IndexTimeoutError,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
searchService,
|
|
25
25
|
statsService,
|
|
26
26
|
symbolGraphService
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-KY4PXYSO.js";
|
|
28
28
|
import {
|
|
29
29
|
isIndexablePath
|
|
30
30
|
} from "./chunk-YOHO4DVT.js";
|
|
@@ -1269,4 +1269,4 @@ export {
|
|
|
1269
1269
|
checkCodebaseIndexServerHealth,
|
|
1270
1270
|
ensureCodebaseIndexServer
|
|
1271
1271
|
};
|
|
1272
|
-
//# sourceMappingURL=chunk-
|
|
1272
|
+
//# sourceMappingURL=chunk-DP6CXMJZ.js.map
|