@kenkaiiii/ggcoder 5.49.0 → 5.49.2
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/core/agent-session-verification-flow.test.d.ts +2 -0
- package/dist/core/agent-session-verification-flow.test.d.ts.map +1 -0
- package/dist/core/agent-session-verification-flow.test.js +125 -0
- package/dist/core/agent-session-verification-flow.test.js.map +1 -0
- package/dist/core/agent-session-verification-gate.test.js +6 -4
- package/dist/core/agent-session-verification-gate.test.js.map +1 -1
- package/dist/core/agent-session.d.ts +9 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +33 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/event-bus.d.ts +6 -6
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/process-manager-notifications.test.js +31 -13
- package/dist/core/process-manager-notifications.test.js.map +1 -1
- package/dist/core/process-manager.d.ts +11 -0
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +1 -1
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/sandbox.d.ts.map +1 -1
- package/dist/core/sandbox.js +66 -1
- package/dist/core/sandbox.js.map +1 -1
- package/dist/core/sandbox.test.js +64 -0
- package/dist/core/sandbox.test.js.map +1 -1
- package/dist/core/verification-gate.d.ts +22 -12
- package/dist/core/verification-gate.d.ts.map +1 -1
- package/dist/core/verification-gate.js +126 -27
- package/dist/core/verification-gate.js.map +1 -1
- package/dist/core/verification-gate.test.js +40 -4
- package/dist/core/verification-gate.test.js.map +1 -1
- package/dist/tools/path-utils.d.ts +28 -1
- package/dist/tools/path-utils.d.ts.map +1 -1
- package/dist/tools/path-utils.js +44 -2
- package/dist/tools/path-utils.js.map +1 -1
- package/dist/tools/path-utils.test.js +57 -1
- package/dist/tools/path-utils.test.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +7 -0
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +284 -20
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +137 -0
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +15 -4
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/app-items.d.ts +3 -0
- package/dist/ui/app-items.d.ts.map +1 -1
- package/dist/ui/app-items.js +3 -0
- package/dist/ui/app-items.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Follow-ups per run
|
|
1
|
+
/** Follow-ups per run. After this the gate is silent for the rest of the run. */
|
|
2
2
|
export const MAX_VERIFICATION_INJECTIONS = 1;
|
|
3
3
|
/** Words that may precede the real command without changing its shape. */
|
|
4
4
|
const SHELL_WRAPPERS = new Set([
|
|
@@ -47,6 +47,10 @@ const RUNNERS = new Set([
|
|
|
47
47
|
"mypy",
|
|
48
48
|
"pylint",
|
|
49
49
|
]);
|
|
50
|
+
/** Shells whose `-c <script>` operand is itself a command to classify. */
|
|
51
|
+
const SHELL_INTERPRETERS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
52
|
+
/** Nested `sh -c` unwraps allowed before the classifier gives up. */
|
|
53
|
+
const MAX_SHELL_DEPTH = 3;
|
|
50
54
|
/** A non-flag word after the runner that makes the command a verification. */
|
|
51
55
|
const VERIFY_KEYWORDS = [
|
|
52
56
|
"test",
|
|
@@ -76,14 +80,105 @@ function isVerifyWord(word) {
|
|
|
76
80
|
// Exact keyword, or a script name built on one (npm run test:unit).
|
|
77
81
|
return VERIFY_KEYWORDS.some((keyword) => word === keyword || word.startsWith(`${keyword}:`));
|
|
78
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Split a command on shell control operators (`&&`, `||`, `;`, `|`, newline),
|
|
85
|
+
* ignoring operators inside quotes, and strip subshell/group punctuation from
|
|
86
|
+
* each piece. `cd pkg && npm test` must classify on its `npm test` half — the
|
|
87
|
+
* whole-string read saw `cd` as the runner and left the gate owed forever.
|
|
88
|
+
*/
|
|
89
|
+
function splitCommandSegments(command) {
|
|
90
|
+
const segments = [];
|
|
91
|
+
let current = "";
|
|
92
|
+
let quote = null;
|
|
93
|
+
for (let i = 0; i < command.length; i++) {
|
|
94
|
+
const char = command[i];
|
|
95
|
+
if (quote) {
|
|
96
|
+
current += char;
|
|
97
|
+
if (char === "\\" && quote === '"')
|
|
98
|
+
current += command[++i] ?? "";
|
|
99
|
+
else if (char === quote)
|
|
100
|
+
quote = null;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (char === "'" || char === '"') {
|
|
104
|
+
quote = char;
|
|
105
|
+
current += char;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (char === "\\") {
|
|
109
|
+
current += char + (command[++i] ?? "");
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Bare `&` is deliberately not an operator: it would split `2>&1`.
|
|
113
|
+
const operator = ["&&", "||", ";", "|", "\n"].find((op) => command.startsWith(op, i));
|
|
114
|
+
if (operator) {
|
|
115
|
+
segments.push(current);
|
|
116
|
+
current = "";
|
|
117
|
+
i += operator.length - 1;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
current += char;
|
|
121
|
+
}
|
|
122
|
+
segments.push(current);
|
|
123
|
+
return segments
|
|
124
|
+
.map((segment) => segment
|
|
125
|
+
.trim()
|
|
126
|
+
.replace(/^[({!\s]+/, "")
|
|
127
|
+
.replace(/[)}\s]+$/, ""))
|
|
128
|
+
.filter((segment) => segment.length > 0);
|
|
129
|
+
}
|
|
130
|
+
/** Split a segment into words, honouring quotes and dropping the quote marks. */
|
|
131
|
+
function tokenize(segment) {
|
|
132
|
+
const words = [];
|
|
133
|
+
let current = "";
|
|
134
|
+
let quote = null;
|
|
135
|
+
let started = false;
|
|
136
|
+
for (let i = 0; i < segment.length; i++) {
|
|
137
|
+
const char = segment[i];
|
|
138
|
+
if (quote) {
|
|
139
|
+
if (char === "\\" && quote === '"')
|
|
140
|
+
current += segment[++i] ?? "";
|
|
141
|
+
else if (char === quote)
|
|
142
|
+
quote = null;
|
|
143
|
+
else
|
|
144
|
+
current += char;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (char === "'" || char === '"') {
|
|
148
|
+
quote = char;
|
|
149
|
+
started = true;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (/\s/.test(char)) {
|
|
153
|
+
if (started || current.length > 0)
|
|
154
|
+
words.push(current);
|
|
155
|
+
current = "";
|
|
156
|
+
started = false;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (char === "\\") {
|
|
160
|
+
current += segment[++i] ?? "";
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
current += char;
|
|
164
|
+
}
|
|
165
|
+
if (started || current.length > 0)
|
|
166
|
+
words.push(current);
|
|
167
|
+
return words;
|
|
168
|
+
}
|
|
79
169
|
/**
|
|
80
170
|
* True when the command looks like a test/typecheck/lint/build invocation:
|
|
81
|
-
* wrappers stripped, a known runner
|
|
82
|
-
* its operands. Deliberately strict —
|
|
83
|
-
* `./run_tests.sh` all read as NOT
|
|
171
|
+
* compound segments considered independently, wrappers stripped, a known runner
|
|
172
|
+
* leading, and a verification keyword among its operands. Deliberately strict —
|
|
173
|
+
* `grep test x`, `git commit -m test` and `./run_tests.sh` all read as NOT
|
|
174
|
+
* verification.
|
|
84
175
|
*/
|
|
85
176
|
export function isVerificationCommand(command) {
|
|
86
|
-
|
|
177
|
+
return splitCommandSegments(command).some((segment) => isVerificationSegment(segment, 0));
|
|
178
|
+
}
|
|
179
|
+
/** Classify one operator-free segment. `depth` bounds `sh -c` unwrapping. */
|
|
180
|
+
function isVerificationSegment(segment, depth) {
|
|
181
|
+
const words = tokenize(segment);
|
|
87
182
|
let i = 0;
|
|
88
183
|
while (i < words.length) {
|
|
89
184
|
const word = words[i];
|
|
@@ -99,6 +194,16 @@ export function isVerificationCommand(command) {
|
|
|
99
194
|
break;
|
|
100
195
|
}
|
|
101
196
|
const runner = words[i] ?? "";
|
|
197
|
+
// `sh -c "cd pkg && npm test"` — classify the script the shell will run.
|
|
198
|
+
if (SHELL_INTERPRETERS.has(runner)) {
|
|
199
|
+
if (depth >= MAX_SHELL_DEPTH)
|
|
200
|
+
return false;
|
|
201
|
+
const flagIndex = words.indexOf("-c", i + 1);
|
|
202
|
+
const script = flagIndex === -1 ? undefined : words[flagIndex + 1];
|
|
203
|
+
if (!script)
|
|
204
|
+
return false;
|
|
205
|
+
return splitCommandSegments(script).some((inner) => isVerificationSegment(inner, depth + 1));
|
|
206
|
+
}
|
|
102
207
|
if (!RUNNERS.has(runner))
|
|
103
208
|
return false;
|
|
104
209
|
if (isVerifyWord(runner))
|
|
@@ -122,17 +227,9 @@ export function buildVerificationFollowUpMessage(files) {
|
|
|
122
227
|
"command has completed since the last edit:\n" +
|
|
123
228
|
files.map((filePath) => `- ${filePath}`).join("\n") +
|
|
124
229
|
"\nRun the project's verification now (its test command, or the closest equivalent) and " +
|
|
125
|
-
"address any failures. Do not describe the change as tested or working without having run it."
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
export function buildVerificationEscalationMessage(files) {
|
|
129
|
-
return {
|
|
130
|
-
role: "user",
|
|
131
|
-
provenance: { source: "runtime", kind: "completion_gate", visibility: "hidden" },
|
|
132
|
-
content: `Verification is still outstanding after ${MAX_VERIFICATION_INJECTIONS} attempt(s); ` +
|
|
133
|
-
"the gate will not prompt again. Give your final response now and state plainly which of " +
|
|
134
|
-
"these changes went unverified and why, so the user can check them:\n" +
|
|
135
|
-
files.map((filePath) => `- ${filePath}`).join("\n"),
|
|
230
|
+
"address any failures. Do not describe the change as tested or working without having run it. " +
|
|
231
|
+
"This is the only time you will be asked: if you cannot run it, say plainly in your final " +
|
|
232
|
+
"response which of these changes went unverified and why, so the user can check them.",
|
|
136
233
|
};
|
|
137
234
|
}
|
|
138
235
|
/**
|
|
@@ -159,23 +256,25 @@ export class VerificationGate {
|
|
|
159
256
|
isOwed() {
|
|
160
257
|
return this.lastMutationSeq > this.lastVerificationSeq;
|
|
161
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Would a stop right now inject? Lets the session arm clients BEFORE the
|
|
261
|
+
* candidate final answer streams, so the draft the injection replaces is held
|
|
262
|
+
* rather than painted and then superseded.
|
|
263
|
+
*/
|
|
264
|
+
willInject() {
|
|
265
|
+
return this.isOwed() && this.injections < MAX_VERIFICATION_INJECTIONS;
|
|
266
|
+
}
|
|
162
267
|
/**
|
|
163
268
|
* The blocking message for the pre-stop hook, or null when nothing is owed
|
|
164
|
-
* or the injection
|
|
165
|
-
*
|
|
269
|
+
* or the single injection is spent. Still-owed on a later stop is deliberately
|
|
270
|
+
* silent: the demand already told the model to disclose what went unverified,
|
|
271
|
+
* and one more injection only costs the user another restated final answer.
|
|
166
272
|
*/
|
|
167
273
|
followUp() {
|
|
168
|
-
if (!this.
|
|
169
|
-
return null;
|
|
170
|
-
if (this.injections >= MAX_VERIFICATION_INJECTIONS + 1)
|
|
274
|
+
if (!this.willInject())
|
|
171
275
|
return null;
|
|
172
276
|
this.injections += 1;
|
|
173
|
-
|
|
174
|
-
return [
|
|
175
|
-
this.injections > MAX_VERIFICATION_INJECTIONS
|
|
176
|
-
? buildVerificationEscalationMessage(files)
|
|
177
|
-
: buildVerificationFollowUpMessage(files),
|
|
178
|
-
];
|
|
277
|
+
return [buildVerificationFollowUpMessage([...this.mutatedFiles].sort())];
|
|
179
278
|
}
|
|
180
279
|
reset() {
|
|
181
280
|
this.seq = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-gate.js","sourceRoot":"","sources":["../../src/core/verification-gate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verification-gate.js","sourceRoot":"","sources":["../../src/core/verification-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,20 @@ describe("isVerificationCommand", () => {
|
|
|
24
24
|
["gradle test", "gradle test"],
|
|
25
25
|
["dotnet test", "dotnet test"],
|
|
26
26
|
["deno task test", "deno task test"],
|
|
27
|
+
// Compound / chained shells: the classifier must look past the first word.
|
|
28
|
+
["cd packages/app && npm test", "cd into a package then test"],
|
|
29
|
+
["cd /tmp/proj && pnpm --filter web test", "cd then filtered workspace test"],
|
|
30
|
+
["npm run typecheck && npm run lint && npm run test", "chained checks"],
|
|
31
|
+
["npm run build; npm test", "semicolon-separated"],
|
|
32
|
+
["npm run test 2>&1 | tee /tmp/out.log", "piped into tee"],
|
|
33
|
+
["npm test 2>&1 | tail -50", "piped into tail"],
|
|
34
|
+
["npm run lint || npm test", "or-chained"],
|
|
35
|
+
["(cd api && cargo test)", "subshell"],
|
|
36
|
+
["git add -A && npm test", "non-verification first, verification second"],
|
|
37
|
+
['sh -c "npm test"', "sh -c wrapper"],
|
|
38
|
+
['bash -c "cd pkg && npm test"', "bash -c wrapping a chain"],
|
|
39
|
+
["sh -c 'pytest tests/'", "sh -c with single quotes"],
|
|
40
|
+
["cd pkg\nnpm test", "newline-separated"],
|
|
27
41
|
];
|
|
28
42
|
const no = [
|
|
29
43
|
["git commit -m fix test", "commit message mentioning test"],
|
|
@@ -36,6 +50,14 @@ describe("isVerificationCommand", () => {
|
|
|
36
50
|
["go run main.go", "go run"],
|
|
37
51
|
["python train.py", "python script"],
|
|
38
52
|
["echo running tests soon", "echo mentioning tests"],
|
|
53
|
+
// Compound negatives: splitting must not invent verification.
|
|
54
|
+
["cd packages/app && npm install", "cd then install"],
|
|
55
|
+
["git add -A && git commit -m 'add test'", "chained git with test in the message"],
|
|
56
|
+
["cd src && ./run_tests.sh", "cd then direct script"],
|
|
57
|
+
['echo "npm test" > notes.txt', "verification text inside a quoted argument"],
|
|
58
|
+
['sh -c "npm run dev"', "sh -c wrapping a dev server"],
|
|
59
|
+
["bash scripts/test.sh", "bash running a script file, not -c"],
|
|
60
|
+
["cat out.log | grep test", "piped grep"],
|
|
39
61
|
];
|
|
40
62
|
it.each(yes)("classifies %s as verification (%s)", (command) => {
|
|
41
63
|
expect(isVerificationCommand(command)).toBe(true);
|
|
@@ -78,17 +100,31 @@ describe("VerificationGate", () => {
|
|
|
78
100
|
expect(gate.isOwed()).toBe(false);
|
|
79
101
|
expect(gate.followUp()).toBeNull();
|
|
80
102
|
});
|
|
81
|
-
it("demands once,
|
|
103
|
+
it("demands once, then goes silent on every later stop while still owed", () => {
|
|
82
104
|
const gate = new VerificationGate();
|
|
83
105
|
gate.recordMutation("a.ts");
|
|
84
106
|
const demand = gate.followUp();
|
|
85
107
|
expect(String(demand[0].content)).toContain("Run the project's verification");
|
|
86
|
-
// Model stopped again without verifying
|
|
87
|
-
|
|
88
|
-
expect(
|
|
108
|
+
// Model stopped again without verifying: still owed, but no second turn is
|
|
109
|
+
// spent on it — each extra injection costs the user another final answer.
|
|
110
|
+
expect(gate.isOwed()).toBe(true);
|
|
111
|
+
expect(gate.followUp()).toBeNull();
|
|
89
112
|
expect(gate.followUp()).toBeNull();
|
|
90
113
|
expect(MAX_VERIFICATION_INJECTIONS).toBe(1);
|
|
91
114
|
});
|
|
115
|
+
it("carries the unverified-disclosure fallback in its single demand", () => {
|
|
116
|
+
const gate = new VerificationGate();
|
|
117
|
+
gate.recordMutation("a.ts");
|
|
118
|
+
// The dropped escalation turn existed only to ask for this; the demand now
|
|
119
|
+
// asks for it up front, so the honesty requirement survives without a turn.
|
|
120
|
+
expect(String(gate.followUp()[0].content)).toContain("unverified");
|
|
121
|
+
});
|
|
122
|
+
it("spends no injection when nothing is owed, so a later mutation still gets its demand", () => {
|
|
123
|
+
const gate = new VerificationGate();
|
|
124
|
+
expect(gate.followUp()).toBeNull();
|
|
125
|
+
gate.recordMutation("a.ts");
|
|
126
|
+
expect(String(gate.followUp()[0].content)).toContain("Run the project's verification");
|
|
127
|
+
});
|
|
92
128
|
it("a later mutation re-arms an already-satisfied gate after a fresh budget reset", () => {
|
|
93
129
|
const gate = new VerificationGate();
|
|
94
130
|
gate.recordMutation("a.ts");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-gate.test.js","sourceRoot":"","sources":["../../src/core/verification-gate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,GAAG,GAAG;QACV,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,gBAAgB,EAAE,+BAA+B,CAAC;QACnD,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,oBAAoB,EAAE,YAAY,CAAC;QACpC,CAAC,YAAY,EAAE,aAAa,CAAC;QAC7B,CAAC,iBAAiB,EAAE,WAAW,CAAC;QAChC,CAAC,cAAc,EAAE,UAAU,CAAC;QAC5B,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,eAAe,EAAE,SAAS,CAAC;QAC5B,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,cAAc,EAAE,cAAc,CAAC;QAChC,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;QAC3C,CAAC,eAAe,EAAE,aAAa,CAAC;QAChC,CAAC,eAAe,EAAE,eAAe,CAAC;QAClC,CAAC,sBAAsB,EAAE,+BAA+B,CAAC;QACzD,CAAC,eAAe,EAAE,iBAAiB,CAAC;QACpC,CAAC,gBAAgB,EAAE,YAAY,CAAC;QAChC,CAAC,eAAe,EAAE,aAAa,CAAC;QAChC,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"verification-gate.test.js","sourceRoot":"","sources":["../../src/core/verification-gate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,GAAG,GAAG;QACV,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,gBAAgB,EAAE,+BAA+B,CAAC;QACnD,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,CAAC,oBAAoB,EAAE,YAAY,CAAC;QACpC,CAAC,YAAY,EAAE,aAAa,CAAC;QAC7B,CAAC,iBAAiB,EAAE,WAAW,CAAC;QAChC,CAAC,cAAc,EAAE,UAAU,CAAC;QAC5B,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,eAAe,EAAE,SAAS,CAAC;QAC5B,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,cAAc,EAAE,cAAc,CAAC;QAChC,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;QAC3C,CAAC,eAAe,EAAE,aAAa,CAAC;QAChC,CAAC,eAAe,EAAE,eAAe,CAAC;QAClC,CAAC,sBAAsB,EAAE,+BAA+B,CAAC;QACzD,CAAC,eAAe,EAAE,iBAAiB,CAAC;QACpC,CAAC,gBAAgB,EAAE,YAAY,CAAC;QAChC,CAAC,eAAe,EAAE,aAAa,CAAC;QAChC,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;QACpC,2EAA2E;QAC3E,CAAC,6BAA6B,EAAE,6BAA6B,CAAC;QAC9D,CAAC,wCAAwC,EAAE,iCAAiC,CAAC;QAC7E,CAAC,mDAAmD,EAAE,gBAAgB,CAAC;QACvE,CAAC,yBAAyB,EAAE,qBAAqB,CAAC;QAClD,CAAC,sCAAsC,EAAE,gBAAgB,CAAC;QAC1D,CAAC,0BAA0B,EAAE,iBAAiB,CAAC;QAC/C,CAAC,0BAA0B,EAAE,YAAY,CAAC;QAC1C,CAAC,wBAAwB,EAAE,UAAU,CAAC;QACtC,CAAC,wBAAwB,EAAE,6CAA6C,CAAC;QACzE,CAAC,kBAAkB,EAAE,eAAe,CAAC;QACrC,CAAC,8BAA8B,EAAE,0BAA0B,CAAC;QAC5D,CAAC,uBAAuB,EAAE,0BAA0B,CAAC;QACrD,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;KAC1C,CAAC;IACF,MAAM,EAAE,GAAG;QACT,CAAC,wBAAwB,EAAE,gCAAgC,CAAC;QAC5D,CAAC,mBAAmB,EAAE,wBAAwB,CAAC;QAC/C,CAAC,qBAAqB,EAAE,WAAW,CAAC;QACpC,CAAC,gBAAgB,EAAE,eAAe,CAAC;QACnC,CAAC,sBAAsB,EAAE,qBAAqB,CAAC;QAC/C,CAAC,aAAa,EAAE,iBAAiB,CAAC;QAClC,CAAC,aAAa,EAAE,YAAY,CAAC;QAC7B,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QAC5B,CAAC,iBAAiB,EAAE,eAAe,CAAC;QACpC,CAAC,yBAAyB,EAAE,uBAAuB,CAAC;QACpD,8DAA8D;QAC9D,CAAC,gCAAgC,EAAE,iBAAiB,CAAC;QACrD,CAAC,wCAAwC,EAAE,sCAAsC,CAAC;QAClF,CAAC,0BAA0B,EAAE,uBAAuB,CAAC;QACrD,CAAC,6BAA6B,EAAE,4CAA4C,CAAC;QAC7E,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;QACtD,CAAC,sBAAsB,EAAE,oCAAoC,CAAC;QAC9D,CAAC,yBAAyB,EAAE,YAAY,CAAC;KAC1C,CAAC;IAEF,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oCAAoC,EAAE,CAAC,OAAO,EAAE,EAAE;QAC7D,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,wCAAwC,EAAE,CAAC,OAAO,EAAE,EAAE;QAChE,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAG,CAAC;QAClC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE5B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAG,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QAE/E,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAG,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAG,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,MAAM,IAAI,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface ResolvePathOpts {
|
|
2
|
+
/** Injected for testability; defaults to process.platform. */
|
|
3
|
+
platform?: NodeJS.Platform;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* MSYS drive path → native Windows path, e.g. `/c/Users/x` → `C:\Users\x`.
|
|
7
|
+
*
|
|
8
|
+
* On Windows our bash tool runs Git Bash (see core/shell.ts), an MSYS2
|
|
9
|
+
* environment, so command output is full of `/c/...`, `//c/...` and
|
|
10
|
+
* `/cygdrive/c/...` paths. The model reads those out of bash output and hands
|
|
11
|
+
* them straight back to the file tools; `path.resolve` then turns `/c/Users/x`
|
|
12
|
+
* into `C:\c\Users\x`, which never exists, so every such call fails and the
|
|
13
|
+
* agent burns turns guessing.
|
|
14
|
+
*
|
|
15
|
+
* Deliberate non-goals:
|
|
16
|
+
* - Non-Windows platforms are left completely alone: `/c/foo` is a perfectly
|
|
17
|
+
* legitimate POSIX path on macOS/Linux and rewriting it would be a
|
|
18
|
+
* data-corrupting regression. Hence the strict platform gate.
|
|
19
|
+
* - MSYS virtual mounts (`/tmp`, `/usr`, `/home`, `/bin`) are NOT translated.
|
|
20
|
+
* They live under the Git-Bash install root, which we cannot determine
|
|
21
|
+
* cheaply or deterministically here, and a wrong guess silently reads or
|
|
22
|
+
* writes the wrong file — far worse than a clear ENOENT.
|
|
23
|
+
* - We do NOT shell out to `cygpath`: this sits on the hot path of every
|
|
24
|
+
* single file tool call, so it would cost a process spawn per call, and
|
|
25
|
+
* `cygpath` is not always on PATH anyway. Pure string manipulation only.
|
|
26
|
+
*/
|
|
27
|
+
export declare function msysToWindowsPath(filePath: string, opts?: ResolvePathOpts): string;
|
|
28
|
+
export declare function resolvePath(cwd: string, filePath: string, opts?: ResolvePathOpts): string;
|
|
2
29
|
/**
|
|
3
30
|
* Check if a path is a symlink. Used by file tools to prevent symlink-based
|
|
4
31
|
* attacks that could read/write sensitive files outside the working directory.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/tools/path-utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/tools/path-utils.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,MAAM,CAiBtF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,MAAM,CAK7F;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
package/dist/tools/path-utils.js
CHANGED
|
@@ -1,11 +1,53 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import os from "node:os";
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* MSYS drive path → native Windows path, e.g. `/c/Users/x` → `C:\Users\x`.
|
|
6
|
+
*
|
|
7
|
+
* On Windows our bash tool runs Git Bash (see core/shell.ts), an MSYS2
|
|
8
|
+
* environment, so command output is full of `/c/...`, `//c/...` and
|
|
9
|
+
* `/cygdrive/c/...` paths. The model reads those out of bash output and hands
|
|
10
|
+
* them straight back to the file tools; `path.resolve` then turns `/c/Users/x`
|
|
11
|
+
* into `C:\c\Users\x`, which never exists, so every such call fails and the
|
|
12
|
+
* agent burns turns guessing.
|
|
13
|
+
*
|
|
14
|
+
* Deliberate non-goals:
|
|
15
|
+
* - Non-Windows platforms are left completely alone: `/c/foo` is a perfectly
|
|
16
|
+
* legitimate POSIX path on macOS/Linux and rewriting it would be a
|
|
17
|
+
* data-corrupting regression. Hence the strict platform gate.
|
|
18
|
+
* - MSYS virtual mounts (`/tmp`, `/usr`, `/home`, `/bin`) are NOT translated.
|
|
19
|
+
* They live under the Git-Bash install root, which we cannot determine
|
|
20
|
+
* cheaply or deterministically here, and a wrong guess silently reads or
|
|
21
|
+
* writes the wrong file — far worse than a clear ENOENT.
|
|
22
|
+
* - We do NOT shell out to `cygpath`: this sits on the hot path of every
|
|
23
|
+
* single file tool call, so it would cost a process spawn per call, and
|
|
24
|
+
* `cygpath` is not always on PATH anyway. Pure string manipulation only.
|
|
25
|
+
*/
|
|
26
|
+
export function msysToWindowsPath(filePath, opts = {}) {
|
|
27
|
+
const platform = opts.platform ?? process.platform;
|
|
28
|
+
if (platform !== "win32")
|
|
29
|
+
return filePath;
|
|
30
|
+
// `//c/x` (MSYS's own drive spelling) and `/cygdrive/c/x` mean exactly the
|
|
31
|
+
// same as `/c/x`. The drive must be a single letter and must be followed by a
|
|
32
|
+
// separator or end-of-string, so `/config` and `/cygdrive` stay untouched.
|
|
33
|
+
//
|
|
34
|
+
// `//c/x` is formally ambiguous with a UNC path whose HOST is one character.
|
|
35
|
+
// Single-letter hostnames don't exist in practice and Git Bash really does
|
|
36
|
+
// emit this form for drives, so translating is the right bet.
|
|
37
|
+
const match = /^(?:\/\/|\/cygdrive\/|\/)([A-Za-z])(?:\/(.*))?$/.exec(filePath);
|
|
38
|
+
if (!match)
|
|
39
|
+
return filePath;
|
|
40
|
+
const drive = match[1].toUpperCase();
|
|
41
|
+
const rest = match[2] ?? "";
|
|
42
|
+
// Always keep the trailing separator: bare `C:` is drive-RELATIVE on Windows
|
|
43
|
+
// (the cwd of that drive), which is not what `/c` means.
|
|
44
|
+
return `${drive}:\\${rest.replaceAll("/", "\\")}`;
|
|
45
|
+
}
|
|
46
|
+
export function resolvePath(cwd, filePath, opts = {}) {
|
|
5
47
|
if (filePath.startsWith("~")) {
|
|
6
48
|
filePath = path.join(os.homedir(), filePath.slice(1));
|
|
7
49
|
}
|
|
8
|
-
return path.resolve(cwd, filePath);
|
|
50
|
+
return path.resolve(cwd, msysToWindowsPath(filePath, opts));
|
|
9
51
|
}
|
|
10
52
|
/**
|
|
11
53
|
* Check if a path is a symlink. Used by file tools to prevent symlink-based
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/tools/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/tools/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,OAAwB,EAAE;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC1C,2EAA2E;IAC3E,8EAA8E;IAC9E,2EAA2E;IAC3E,EAAE;IACF,6EAA6E;IAC7E,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,KAAK,GAAG,iDAAiD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/E,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,6EAA6E;IAC7E,yDAAyD;IACzD,OAAO,GAAG,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAAgB,EAAE,OAAwB,EAAE;IACnF,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uFAAuF;QACvF,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,oBAAoB,CAAC;YAAE,MAAM,GAAG,CAAC;IACtF,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC9C,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import os from "node:os";
|
|
5
|
-
import { resolvePath, rejectSymlink } from "./path-utils.js";
|
|
5
|
+
import { resolvePath, rejectSymlink, msysToWindowsPath } from "./path-utils.js";
|
|
6
6
|
describe("resolvePath", () => {
|
|
7
7
|
it("resolves relative path from cwd", () => {
|
|
8
8
|
const result = resolvePath("/home/user/project", "src/index.ts");
|
|
@@ -26,6 +26,62 @@ describe("resolvePath", () => {
|
|
|
26
26
|
expect(result).toBe(path.join(os.homedir(), "documents/file.txt"));
|
|
27
27
|
});
|
|
28
28
|
});
|
|
29
|
+
describe("msysToWindowsPath", () => {
|
|
30
|
+
const win = { platform: "win32" };
|
|
31
|
+
it("translates /c/... to a native drive path", () => {
|
|
32
|
+
expect(msysToWindowsPath("/c/Users/ken/proj/src/a.ts", win)).toBe("C:\\Users\\ken\\proj\\src\\a.ts");
|
|
33
|
+
expect(msysToWindowsPath("/d/repo", win)).toBe("D:\\repo");
|
|
34
|
+
});
|
|
35
|
+
it("uppercases the drive letter regardless of input case", () => {
|
|
36
|
+
expect(msysToWindowsPath("/C/Users/ken", win)).toBe("C:\\Users\\ken");
|
|
37
|
+
});
|
|
38
|
+
it("translates the //c/ and /cygdrive/c/ spellings identically", () => {
|
|
39
|
+
expect(msysToWindowsPath("//c/Users/x", win)).toBe("C:\\Users\\x");
|
|
40
|
+
expect(msysToWindowsPath("/cygdrive/c/Users/x", win)).toBe("C:\\Users\\x");
|
|
41
|
+
});
|
|
42
|
+
it("maps a drive-only path to the drive ROOT, not the drive-relative cwd", () => {
|
|
43
|
+
expect(msysToWindowsPath("/c", win)).toBe("C:\\");
|
|
44
|
+
expect(msysToWindowsPath("/c/", win)).toBe("C:\\");
|
|
45
|
+
expect(msysToWindowsPath("/cygdrive/d", win)).toBe("D:\\");
|
|
46
|
+
});
|
|
47
|
+
it("leaves MSYS virtual mounts alone rather than guessing", () => {
|
|
48
|
+
expect(msysToWindowsPath("/tmp/x", win)).toBe("/tmp/x");
|
|
49
|
+
expect(msysToWindowsPath("/usr/bin/git", win)).toBe("/usr/bin/git");
|
|
50
|
+
expect(msysToWindowsPath("/home/ken", win)).toBe("/home/ken");
|
|
51
|
+
});
|
|
52
|
+
it("requires a single-letter segment terminated by / or end-of-string", () => {
|
|
53
|
+
expect(msysToWindowsPath("/config/app.json", win)).toBe("/config/app.json");
|
|
54
|
+
expect(msysToWindowsPath("/cygdrive", win)).toBe("/cygdrive");
|
|
55
|
+
});
|
|
56
|
+
it("leaves an already-native Windows path unchanged", () => {
|
|
57
|
+
expect(msysToWindowsPath("C:\\x", win)).toBe("C:\\x");
|
|
58
|
+
expect(msysToWindowsPath("C:/x", win)).toBe("C:/x");
|
|
59
|
+
});
|
|
60
|
+
it("leaves relative paths unchanged", () => {
|
|
61
|
+
expect(msysToWindowsPath("src/index.ts", win)).toBe("src/index.ts");
|
|
62
|
+
expect(msysToWindowsPath("./a.ts", win)).toBe("./a.ts");
|
|
63
|
+
expect(msysToWindowsPath("", win)).toBe("");
|
|
64
|
+
});
|
|
65
|
+
it("never translates on non-Windows platforms (/c/foo is a real POSIX path)", () => {
|
|
66
|
+
for (const platform of ["darwin", "linux"]) {
|
|
67
|
+
expect(msysToWindowsPath("/c/foo", { platform })).toBe("/c/foo");
|
|
68
|
+
expect(msysToWindowsPath("/cygdrive/c/foo", { platform })).toBe("/cygdrive/c/foo");
|
|
69
|
+
expect(msysToWindowsPath("//c/foo", { platform })).toBe("//c/foo");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe("resolvePath with MSYS input", () => {
|
|
74
|
+
it("translates before resolving", () => {
|
|
75
|
+
// path.resolve is host-dependent, so compare against resolving the already
|
|
76
|
+
// translated form: without the MSYS step this would resolve `/c/Users/...`
|
|
77
|
+
// verbatim, which is a different string on every platform.
|
|
78
|
+
const result = resolvePath("D:\\proj", "/c/Users/ken/a.ts", { platform: "win32" });
|
|
79
|
+
expect(result).toBe(path.resolve("D:\\proj", "C:\\Users\\ken\\a.ts"));
|
|
80
|
+
});
|
|
81
|
+
it("leaves /c/foo as a POSIX path when not on Windows", () => {
|
|
82
|
+
expect(resolvePath("/home/user/project", "/c/foo", { platform: "linux" })).toBe(path.resolve("/c/foo"));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
29
85
|
describe("rejectSymlink", () => {
|
|
30
86
|
let tmpDir;
|
|
31
87
|
beforeEach(async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-utils.test.js","sourceRoot":"","sources":["../../src/tools/path-utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"path-utils.test.js","sourceRoot":"","sources":["../../src/tools/path-utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,11 @@ import { type GetNetworkPolicy } from "../core/network-guard.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function isBlockedUrl(urlString: string): boolean;
|
|
9
9
|
export declare function htmlToCleanText(html: string): string;
|
|
10
|
+
/** A hyperlink shown in an outline render as `anchor text [number]`. */
|
|
11
|
+
export interface OutlineLink {
|
|
12
|
+
number: number;
|
|
13
|
+
url: string;
|
|
14
|
+
}
|
|
10
15
|
type LlmsCandidateKind = "llms" | "llms-full" | "llms-ctx" | "page-md";
|
|
11
16
|
interface LlmsCandidate {
|
|
12
17
|
url: string;
|
|
@@ -20,11 +25,13 @@ export declare function createWebFetchTool(getNetworkPolicy?: GetNetworkPolicy):
|
|
|
20
25
|
declare const parameters: z.ZodObject<{
|
|
21
26
|
url: z.ZodOptional<z.ZodString>;
|
|
22
27
|
urls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
|
+
follow: z.ZodOptional<z.ZodNumber>;
|
|
23
29
|
max_length: z.ZodOptional<z.ZodNumber>;
|
|
24
30
|
format: z.ZodOptional<z.ZodEnum<{
|
|
25
31
|
text: "text";
|
|
26
32
|
html: "html";
|
|
27
33
|
markdown: "markdown";
|
|
34
|
+
outline: "outline";
|
|
28
35
|
}>>;
|
|
29
36
|
prefer_llms_txt: z.ZodOptional<z.ZodBoolean>;
|
|
30
37
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAC;AAIlE,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA0CvD;AAmGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYpD;
|
|
1
|
+
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAC;AAIlE,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA0CvD;AAmGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYpD;AAcD,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AA6MD,KAAK,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAEvE,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkID,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,SAAqB,GAC5B,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAwLD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAuCnF;AA2HD,wBAAgB,kBAAkB,CAChC,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,SAAS,CAAC,OAAO,UAAU,CAAC,CA8E9B;AA0BD,QAAA,MAAM,UAAU;;;;;;;;;;;;iBAyCb,CAAC"}
|