@linghun/tools 0.1.3 → 0.1.5
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/{chunk-J7O24FJB.js → chunk-PNXZO2UE.js} +11 -11
- package/dist/{chunk-F7UOI3YR.js → chunk-XGK6YYZO.js} +11 -11
- package/dist/index.d.ts +18 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +139 -234
- package/dist/tools/Todo/TodoTool.js +2 -2
- package/dist/tools/prompts.js +15 -15
- package/dist/tools/ui.js +15 -15
- package/package.json +1 -1
- package/dist/chunk-236QJATI.js +0 -678
- package/dist/chunk-SPAD4DZS.js +0 -319
- package/dist/chunk-XG6HNLY6.js +0 -166
- package/dist/tools/Bash/artifact-checker.d.ts +0 -33
- package/dist/tools/Bash/artifact-checker.d.ts.map +0 -1
- package/dist/tools/Bash/artifact-checker.js +0 -6
- package/dist/tools/Bash/binary-helper.d.ts +0 -7
- package/dist/tools/Bash/binary-helper.d.ts.map +0 -1
- package/dist/tools/Bash/binary-helper.js +0 -6
- package/dist/tools/Bash/service-kernel.d.ts +0 -75
- package/dist/tools/Bash/service-kernel.d.ts.map +0 -1
- package/dist/tools/Bash/service-kernel.js +0 -8
- package/dist/{chunk-4567YAXM.js → chunk-MFHY7PBM.js} +3 -3
package/dist/index.js
CHANGED
|
@@ -1,71 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatFetchOutput,
|
|
3
|
-
webFetch
|
|
4
|
-
} from "./chunk-4UHQWBFA.js";
|
|
5
1
|
import {
|
|
6
2
|
applyDomainFilter,
|
|
7
3
|
bingSearch,
|
|
8
4
|
formatSearchOutput
|
|
9
5
|
} from "./chunk-EPIB4FSE.js";
|
|
10
6
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./chunk-
|
|
7
|
+
formatFetchOutput,
|
|
8
|
+
webFetch
|
|
9
|
+
} from "./chunk-4UHQWBFA.js";
|
|
14
10
|
import {
|
|
15
11
|
createTool
|
|
16
12
|
} from "./chunk-MMJX44V6.js";
|
|
17
13
|
import {
|
|
18
14
|
toolPrompts
|
|
19
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-XGK6YYZO.js";
|
|
20
16
|
import {
|
|
21
17
|
toolUserFacingNames
|
|
22
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-PNXZO2UE.js";
|
|
23
19
|
import "./chunk-4EZHIDZ6.js";
|
|
20
|
+
import "./chunk-YR4HWOR2.js";
|
|
21
|
+
import "./chunk-VAFW24RN.js";
|
|
22
|
+
import "./chunk-LGZOG7IQ.js";
|
|
23
|
+
import "./chunk-MFHY7PBM.js";
|
|
24
|
+
import "./chunk-SZFZPQGL.js";
|
|
25
|
+
import "./chunk-XZWSO5CM.js";
|
|
24
26
|
import "./chunk-I3Z4OKMS.js";
|
|
25
27
|
import "./chunk-PS2ZOFZ6.js";
|
|
26
28
|
import "./chunk-NPKLGVDQ.js";
|
|
27
|
-
import "./chunk-VJDLOFCF.js";
|
|
28
|
-
import "./chunk-3RP665TH.js";
|
|
29
|
-
import "./chunk-IOC3BSPT.js";
|
|
30
|
-
import "./chunk-LGZOG7IQ.js";
|
|
31
|
-
import "./chunk-ZYAEUABC.js";
|
|
32
|
-
import "./chunk-SWK6XRZQ.js";
|
|
33
|
-
import "./chunk-YR4HWOR2.js";
|
|
34
|
-
import "./chunk-VAFW24RN.js";
|
|
35
29
|
import "./chunk-TZ6QK52L.js";
|
|
36
30
|
import "./chunk-K3YDFDLP.js";
|
|
37
31
|
import "./chunk-GI5XI4HN.js";
|
|
38
32
|
import "./chunk-WEWXKRKL.js";
|
|
39
33
|
import "./chunk-A6FUAM64.js";
|
|
40
34
|
import "./chunk-YCO6C7KF.js";
|
|
41
|
-
import "./chunk-
|
|
42
|
-
import "./chunk-
|
|
43
|
-
import "./chunk-SZFZPQGL.js";
|
|
44
|
-
import "./chunk-WLQ7DGMG.js";
|
|
45
|
-
import "./chunk-SQP6SJRP.js";
|
|
46
|
-
import "./chunk-BRG64AEC.js";
|
|
35
|
+
import "./chunk-ZYAEUABC.js";
|
|
36
|
+
import "./chunk-SWK6XRZQ.js";
|
|
47
37
|
import "./chunk-AZCQL24J.js";
|
|
48
38
|
import "./chunk-HUIZOB4A.js";
|
|
49
39
|
import "./chunk-MK3YP2VR.js";
|
|
40
|
+
import "./chunk-VJDLOFCF.js";
|
|
41
|
+
import "./chunk-3RP665TH.js";
|
|
42
|
+
import "./chunk-IOC3BSPT.js";
|
|
50
43
|
import "./chunk-HNIVNZIS.js";
|
|
44
|
+
import "./chunk-WLQ7DGMG.js";
|
|
45
|
+
import "./chunk-SQP6SJRP.js";
|
|
46
|
+
import "./chunk-BRG64AEC.js";
|
|
51
47
|
import "./chunk-7ZOADACP.js";
|
|
52
48
|
import "./chunk-H5OOD2OS.js";
|
|
53
49
|
import "./chunk-IQP3XE32.js";
|
|
54
50
|
import "./chunk-Z3H6SZBS.js";
|
|
55
51
|
import "./chunk-ITBZHMZQ.js";
|
|
56
52
|
import "./chunk-2U4BZXAI.js";
|
|
57
|
-
import {
|
|
58
|
-
checkArtifact
|
|
59
|
-
} from "./chunk-SPAD4DZS.js";
|
|
60
53
|
import "./chunk-2DIXRINW.js";
|
|
61
|
-
import "./chunk-PKMIDA5A.js";
|
|
62
|
-
import "./chunk-GAWMEMXB.js";
|
|
63
|
-
import {
|
|
64
|
-
inspectBinaryFile
|
|
65
|
-
} from "./chunk-XG6HNLY6.js";
|
|
66
54
|
import {
|
|
67
55
|
interpretCommandResult
|
|
68
56
|
} from "./chunk-FI4YPDFE.js";
|
|
57
|
+
import "./chunk-PKMIDA5A.js";
|
|
58
|
+
import "./chunk-GAWMEMXB.js";
|
|
69
59
|
|
|
70
60
|
// src/index.ts
|
|
71
61
|
import { spawn } from "child_process";
|
|
@@ -99,8 +89,7 @@ function createToolContext(workspaceRoot = process.cwd(), options = {}) {
|
|
|
99
89
|
readSnapshots: {},
|
|
100
90
|
sourcePackCandidates: options.sourcePackCandidates,
|
|
101
91
|
patchSummaries: {},
|
|
102
|
-
recentDiagnostics: []
|
|
103
|
-
services: []
|
|
92
|
+
recentDiagnostics: []
|
|
104
93
|
};
|
|
105
94
|
}
|
|
106
95
|
async function runTool(name, input, context) {
|
|
@@ -308,7 +297,7 @@ var toolDefinitions = {
|
|
|
308
297
|
call: bashTool,
|
|
309
298
|
prompt: () => toolPrompts.Bash,
|
|
310
299
|
userFacingName: () => toolUserFacingNames.Bash,
|
|
311
|
-
getToolUseSummary: (input) =>
|
|
300
|
+
getToolUseSummary: (input) => `Bash ${input.command}`,
|
|
312
301
|
getActivityDescription: () => "Running command"
|
|
313
302
|
}),
|
|
314
303
|
Todo: defineTool({
|
|
@@ -588,120 +577,17 @@ function validateGlobInput(input) {
|
|
|
588
577
|
function validateBashInput(input) {
|
|
589
578
|
const record = validateRecord(input, "Bash");
|
|
590
579
|
const command = readOptionalString(record, "command", "Bash");
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const service = validateOptionalBashServiceInput(record.service);
|
|
594
|
-
const serviceAction = isBashServiceLifecycleAction(service);
|
|
595
|
-
if (command === void 0 && binary === void 0 && artifact === void 0 && !serviceAction) {
|
|
596
|
-
throw new Error("Bash.command\u3001Bash.binary\u3001Bash.artifact \u6216 Bash.service action \u5FC5\u987B\u63D0\u4F9B\u4E00\u4E2A\u3002");
|
|
597
|
-
}
|
|
598
|
-
const modeCount = [
|
|
599
|
-
command !== void 0,
|
|
600
|
-
binary !== void 0,
|
|
601
|
-
artifact !== void 0,
|
|
602
|
-
serviceAction
|
|
603
|
-
].filter(Boolean).length;
|
|
604
|
-
if (modeCount > 1 || (binary !== void 0 || artifact !== void 0) && service !== void 0) {
|
|
605
|
-
throw new Error("Bash.command\u3001Bash.binary\u3001Bash.artifact \u548C Bash.service \u4E0D\u80FD\u6DF7\u7528\u3002");
|
|
606
|
-
}
|
|
607
|
-
if (service !== void 0 && !serviceAction && command === void 0) {
|
|
608
|
-
throw new Error("Bash.service readiness \u5FC5\u987B\u548C Bash.command \u4E00\u8D77\u4F7F\u7528\u3002");
|
|
580
|
+
if (command === void 0) {
|
|
581
|
+
throw new Error("Bash.command \u5FC5\u987B\u63D0\u4F9B\u3002");
|
|
609
582
|
}
|
|
610
583
|
const runInBackground = record.runInBackground === true || record.run_in_background === true;
|
|
611
584
|
return {
|
|
612
585
|
command,
|
|
586
|
+
description: readOptionalString(record, "description", "Bash"),
|
|
613
587
|
timeoutMs: readOptionalPositiveInteger(record, "timeoutMs", "Bash"),
|
|
614
|
-
service,
|
|
615
|
-
binary,
|
|
616
|
-
artifact,
|
|
617
588
|
...runInBackground ? { runInBackground: true } : {}
|
|
618
589
|
};
|
|
619
590
|
}
|
|
620
|
-
function validateOptionalBashBinaryInspect(input) {
|
|
621
|
-
if (input === void 0) return void 0;
|
|
622
|
-
if (isEmptyOptionalObject(input)) return void 0;
|
|
623
|
-
const record = validateRecord(input, "Bash");
|
|
624
|
-
return {
|
|
625
|
-
path: readString(record, "path", "Bash"),
|
|
626
|
-
previewBytes: readOptionalPositiveInteger(record, "previewBytes", "Bash")
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
function validateOptionalBashArtifactCheck(input) {
|
|
630
|
-
if (input === void 0) return void 0;
|
|
631
|
-
if (isEmptyOptionalObject(input)) return void 0;
|
|
632
|
-
const record = validateRecord(input, "Bash");
|
|
633
|
-
return {
|
|
634
|
-
path: readString(record, "path", "Bash"),
|
|
635
|
-
expectHeader: readOptionalString(record, "expectHeader", "Bash"),
|
|
636
|
-
expectMagic: readOptionalString(record, "expectMagic", "Bash"),
|
|
637
|
-
json: readOptionalBoolean(record, "json", "Bash"),
|
|
638
|
-
executable: readOptionalBoolean(record, "executable", "Bash"),
|
|
639
|
-
protectPaths: readOptionalStringArray(record, "protectPaths", "Bash"),
|
|
640
|
-
text: validateOptionalBashArtifactTextCheck(record.text),
|
|
641
|
-
preserve: validateOptionalBashArtifactPreserveCheck(record.preserve)
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
function validateOptionalBashServiceInput(input) {
|
|
645
|
-
if (input === void 0) return void 0;
|
|
646
|
-
if (isEmptyOptionalObject(input)) return void 0;
|
|
647
|
-
const record = validateRecord(input, "Bash");
|
|
648
|
-
const action = readOptionalString(record, "action", "Bash");
|
|
649
|
-
if (action !== void 0) {
|
|
650
|
-
if (action === "fetch") {
|
|
651
|
-
const url = readString(record, "url", "Bash");
|
|
652
|
-
validateHttpUrl(url);
|
|
653
|
-
return {
|
|
654
|
-
action,
|
|
655
|
-
url,
|
|
656
|
-
expectStatus: readOptionalPositiveInteger(record, "expectStatus", "Bash"),
|
|
657
|
-
bodyContains: readOptionalStringOrStringArray(record, "bodyContains", "Bash"),
|
|
658
|
-
timeoutMs: readOptionalPositiveInteger(record, "timeoutMs", "Bash"),
|
|
659
|
-
retry: readOptionalPositiveInteger(record, "retry", "Bash"),
|
|
660
|
-
intervalMs: readOptionalPositiveInteger(record, "intervalMs", "Bash")
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
if (action === "status" || action === "probe" || action === "logs" || action === "stop") {
|
|
664
|
-
return {
|
|
665
|
-
action,
|
|
666
|
-
serviceId: readString(record, "serviceId", "Bash"),
|
|
667
|
-
...action === "logs" ? { tailBytes: readOptionalPositiveInteger(record, "tailBytes", "Bash") } : {}
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
throw new Error("Bash.service.action \u5FC5\u987B\u662F status/probe/logs/stop/fetch\u3002");
|
|
671
|
-
}
|
|
672
|
-
const type = readString(record, "type", "Bash");
|
|
673
|
-
const timeoutMs = readOptionalPositiveInteger(record, "timeoutMs", "Bash");
|
|
674
|
-
const intervalMs = readOptionalPositiveInteger(record, "intervalMs", "Bash");
|
|
675
|
-
if (type === "tcp") {
|
|
676
|
-
const rawPort = record.port;
|
|
677
|
-
if (!Number.isInteger(rawPort) || rawPort <= 0) {
|
|
678
|
-
throw new Error("Bash.service.port \u5FC5\u987B\u662F\u6B63\u6574\u6570\u3002");
|
|
679
|
-
}
|
|
680
|
-
const port = rawPort;
|
|
681
|
-
if (port > 65535) {
|
|
682
|
-
throw new Error("Bash.service.port \u5FC5\u987B\u5728 1-65535 \u8303\u56F4\u5185\u3002");
|
|
683
|
-
}
|
|
684
|
-
return {
|
|
685
|
-
type,
|
|
686
|
-
port,
|
|
687
|
-
host: readOptionalString(record, "host", "Bash"),
|
|
688
|
-
timeoutMs,
|
|
689
|
-
intervalMs
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
if (type === "http") {
|
|
693
|
-
const url = readString(record, "url", "Bash");
|
|
694
|
-
validateHttpUrl(url);
|
|
695
|
-
return { type, url, timeoutMs, intervalMs };
|
|
696
|
-
}
|
|
697
|
-
throw new Error("Bash.service.type \u5FC5\u987B\u662F tcp \u6216 http\u3002");
|
|
698
|
-
}
|
|
699
|
-
function isEmptyOptionalObject(input) {
|
|
700
|
-
return input === null || typeof input === "object" && !Array.isArray(input) && Object.keys(input).length === 0;
|
|
701
|
-
}
|
|
702
|
-
function isBashServiceLifecycleAction(input) {
|
|
703
|
-
return Boolean(input && "action" in input);
|
|
704
|
-
}
|
|
705
591
|
function validateTodoInput(input) {
|
|
706
592
|
const record = validateRecord(input, "Todo");
|
|
707
593
|
const action = readString(record, "action", "Todo");
|
|
@@ -759,53 +645,6 @@ function readOptionalStringArray(record, key, toolName) {
|
|
|
759
645
|
}
|
|
760
646
|
return value;
|
|
761
647
|
}
|
|
762
|
-
function readOptionalBoolean(record, key, toolName) {
|
|
763
|
-
const value = record[key];
|
|
764
|
-
if (value === void 0) return void 0;
|
|
765
|
-
if (typeof value !== "boolean") {
|
|
766
|
-
throw new Error(`${toolName}.${key} \u5FC5\u987B\u662F boolean \u6216 undefined\u3002`);
|
|
767
|
-
}
|
|
768
|
-
return value;
|
|
769
|
-
}
|
|
770
|
-
function readOptionalStringOrStringArray(record, key, toolName) {
|
|
771
|
-
const value = record[key];
|
|
772
|
-
if (value === void 0) return void 0;
|
|
773
|
-
if (typeof value === "string") return value;
|
|
774
|
-
if (Array.isArray(value) && value.every((item) => typeof item === "string")) return value;
|
|
775
|
-
throw new Error(`${toolName}.${key} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3001\u5B57\u7B26\u4E32\u6570\u7EC4\u6216 undefined\u3002`);
|
|
776
|
-
}
|
|
777
|
-
function validateOptionalBashArtifactTextCheck(input) {
|
|
778
|
-
if (input === void 0) return void 0;
|
|
779
|
-
const record = validateRecord(input, "Bash");
|
|
780
|
-
return {
|
|
781
|
-
exact: readOptionalString(record, "exact", "Bash"),
|
|
782
|
-
contains: readOptionalStringOrStringArray(record, "contains", "Bash"),
|
|
783
|
-
lineSet: readOptionalStringArray(record, "lineSet", "Bash")
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
function validateOptionalBashArtifactPreserveCheck(input) {
|
|
787
|
-
if (input === void 0) return void 0;
|
|
788
|
-
const record = validateRecord(input, "Bash");
|
|
789
|
-
const mode = readString(record, "mode", "Bash");
|
|
790
|
-
if (mode !== "rawPreserve" && mode !== "compareNormalizedHtml") {
|
|
791
|
-
throw new Error("Bash.artifact.preserve.mode \u5FC5\u987B\u662F rawPreserve \u6216 compareNormalizedHtml\u3002");
|
|
792
|
-
}
|
|
793
|
-
return {
|
|
794
|
-
mode,
|
|
795
|
-
expectedPath: readOptionalString(record, "expectedPath", "Bash"),
|
|
796
|
-
expectedText: readOptionalString(record, "expectedText", "Bash")
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
function validateHttpUrl(url) {
|
|
800
|
-
try {
|
|
801
|
-
const parsed = new URL(url);
|
|
802
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
803
|
-
throw new Error("protocol");
|
|
804
|
-
}
|
|
805
|
-
} catch {
|
|
806
|
-
throw new Error("Bash.service.url \u5FC5\u987B\u662F http/https URL\u3002");
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
648
|
async function readTool(input, context) {
|
|
810
649
|
const filePath = resolveWorkspacePath(context.workspaceRoot, input.path);
|
|
811
650
|
const content = await readFile(filePath, "utf8");
|
|
@@ -1182,43 +1021,14 @@ function sanitizeSecrets(text) {
|
|
|
1182
1021
|
return sanitized;
|
|
1183
1022
|
}
|
|
1184
1023
|
async function bashTool(input, context) {
|
|
1185
|
-
if (input.artifact) {
|
|
1186
|
-
return checkArtifact({
|
|
1187
|
-
input: input.artifact,
|
|
1188
|
-
target: resolveArtifactPath(context, input.artifact.path),
|
|
1189
|
-
protectPaths: (input.artifact.protectPaths ?? []).map((path) => resolveArtifactPath(context, path)),
|
|
1190
|
-
context
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
if (input.binary) {
|
|
1194
|
-
return inspectBinaryFile(input.binary, resolveWorkspacePath(context.workspaceRoot, input.binary.path));
|
|
1195
|
-
}
|
|
1196
1024
|
if (!input.command) {
|
|
1197
|
-
|
|
1198
|
-
return runBashServiceLifecycleAction(input.service, context);
|
|
1199
|
-
}
|
|
1200
|
-
throw new Error("Bash.command\u3001Bash.binary \u6216 Bash.service action \u5FC5\u987B\u63D0\u4F9B\u4E00\u4E2A\u3002");
|
|
1025
|
+
throw new Error("Bash.command \u5FC5\u987B\u63D0\u4F9B\u3002");
|
|
1201
1026
|
}
|
|
1202
1027
|
const logRoot = context.logRoot ?? join(context.workspaceRoot, ".linghun", "logs", "tools");
|
|
1203
1028
|
await mkdir(logRoot, { recursive: true });
|
|
1204
1029
|
const fullOutputPath = join(logRoot, `bash-${Date.now()}-${randomUUID()}.log`);
|
|
1205
1030
|
const timeoutMs = input.timeoutMs ?? BASH_TIMEOUT_MS;
|
|
1206
1031
|
const adapted = adaptShellCommand(input.command);
|
|
1207
|
-
if (input.service && !isBashServiceLifecycleAction(input.service)) {
|
|
1208
|
-
const readiness = withDefaultServiceReadiness(input.service, context);
|
|
1209
|
-
return startBashService({
|
|
1210
|
-
command: adapted.command,
|
|
1211
|
-
logCommand: adapted.logCommand ?? adapted.command,
|
|
1212
|
-
cwd: context.workspaceRoot,
|
|
1213
|
-
fullOutputPath,
|
|
1214
|
-
readiness,
|
|
1215
|
-
context,
|
|
1216
|
-
abortSignal: context.abortSignal,
|
|
1217
|
-
onProgress: (stream, text) => void context.onProgress?.({ toolName: "Bash", stream, text }),
|
|
1218
|
-
trackChildProcess: context.trackChildProcess,
|
|
1219
|
-
sanitizeText: sanitizeSecrets
|
|
1220
|
-
});
|
|
1221
|
-
}
|
|
1222
1032
|
if (input.runInBackground === true) {
|
|
1223
1033
|
const taskId = randomUUID();
|
|
1224
1034
|
void runBackgroundBash({
|
|
@@ -1787,14 +1597,6 @@ function isHeadlessBenchContext(context) {
|
|
|
1787
1597
|
const record = context;
|
|
1788
1598
|
return record.headlessBench?.enabled === true || record.isHeadlessBench === true;
|
|
1789
1599
|
}
|
|
1790
|
-
function withDefaultServiceReadiness(readiness, context) {
|
|
1791
|
-
if (readiness.timeoutMs !== void 0) return readiness;
|
|
1792
|
-
const hasReadinessRisk = (context.recentDiagnostics ?? []).some(
|
|
1793
|
-
(diagnostic) => diagnostic.type === "service_readiness" || diagnostic.type === "timeout"
|
|
1794
|
-
);
|
|
1795
|
-
const timeoutMs = hasReadinessRisk ? 15e3 : isHeadlessBenchContext(context) ? 1e4 : 5e3;
|
|
1796
|
-
return { ...readiness, timeoutMs };
|
|
1797
|
-
}
|
|
1798
1600
|
function createBashOutcomeDiagnostics(outcome) {
|
|
1799
1601
|
if (outcome === "timeout") {
|
|
1800
1602
|
return [
|
|
@@ -1817,13 +1619,20 @@ function adaptShellCommand(command) {
|
|
|
1817
1619
|
}
|
|
1818
1620
|
function adaptShellCommandForPlatform(command, platform) {
|
|
1819
1621
|
if (platform !== "win32") return { command, adapter: "native" };
|
|
1622
|
+
if (isExplicitPowerShellCommand(command)) return { command, adapter: "native" };
|
|
1623
|
+
const fileWriteBlock = blockWindowsShellFileWriteCommand(command);
|
|
1624
|
+
if (fileWriteBlock) return fileWriteBlock;
|
|
1820
1625
|
const heredoc = convertNodeHereDocForPowerShell(command);
|
|
1821
1626
|
if (heredoc) return heredoc;
|
|
1627
|
+
const nativePowerShell = convertNativePowerShellCommand(command);
|
|
1628
|
+
if (nativePowerShell) return nativePowerShell;
|
|
1822
1629
|
if (looksLikeUnsupportedUnixMultiline(command)) {
|
|
1823
1630
|
return createBlockedPowerShellAdapter(
|
|
1824
1631
|
"Unsupported multi-line Unix shell syntax on Windows PowerShell; use PowerShell-safe commands or Node one-liners."
|
|
1825
1632
|
);
|
|
1826
1633
|
}
|
|
1634
|
+
const unsupportedPosix = blockUnsupportedPosixShellSyntax(command);
|
|
1635
|
+
if (unsupportedPosix) return unsupportedPosix;
|
|
1827
1636
|
const converted = convertUnixPipelineForPowerShell(command);
|
|
1828
1637
|
if (converted) return { command: converted, adapter: "powershell-adapted" };
|
|
1829
1638
|
const readOnlyCommand = convertUnixReadOnlyCommandForPowerShell(command);
|
|
@@ -1836,6 +1645,73 @@ function adaptShellCommandForPlatform(command, platform) {
|
|
|
1836
1645
|
if (unsupportedReadOnlyCommand) return unsupportedReadOnlyCommand;
|
|
1837
1646
|
return { command, adapter: "native" };
|
|
1838
1647
|
}
|
|
1648
|
+
function isExplicitPowerShellCommand(command) {
|
|
1649
|
+
return /^(?:powershell(?:\.exe)?|pwsh(?:\.exe)?)\b/iu.test(command.trim());
|
|
1650
|
+
}
|
|
1651
|
+
var WINDOWS_SHELL_WRITE_BLOCK_MESSAGE = "Linghun Bash does not support shell apply_patch or heredoc file writes on Windows; use Edit/MultiEdit/Write structured tools instead.";
|
|
1652
|
+
function blockWindowsShellFileWriteCommand(command) {
|
|
1653
|
+
const normalized = command.replace(/\r\n/gu, "\n").trim();
|
|
1654
|
+
if (!normalized) return void 0;
|
|
1655
|
+
if (/\bapply_patch\b/iu.test(normalized) && (/(?:^|\n|;)\s*apply_patch\s*<</iu.test(normalized) || /@['"][\s\S]*?['"]@\s*\|\s*apply_patch\b/iu.test(normalized) || /\$[A-Za-z_][\w]*\s*=\s*@['"][\s\S]*?['"]@/u.test(normalized) || /\$[A-Za-z_][\w]*\s*\|\s*apply_patch\b/u.test(normalized))) {
|
|
1656
|
+
return createBlockedPowerShellAdapter(WINDOWS_SHELL_WRITE_BLOCK_MESSAGE);
|
|
1657
|
+
}
|
|
1658
|
+
if (/(?:^|\n|;)\s*cat\b[^\n;]*>\s*\S+/iu.test(normalized) || /(?:^|\n|;)\s*cat\b[^\n;]*<<[^\n]*>\s*\S+/iu.test(normalized) || /(?:^|\n|;)\s*tee\b\s+\S+/iu.test(normalized)) {
|
|
1659
|
+
return createBlockedPowerShellAdapter(WINDOWS_SHELL_WRITE_BLOCK_MESSAGE);
|
|
1660
|
+
}
|
|
1661
|
+
return void 0;
|
|
1662
|
+
}
|
|
1663
|
+
function convertNativePowerShellCommand(command) {
|
|
1664
|
+
const normalized = command.trim();
|
|
1665
|
+
if (!normalized) return void 0;
|
|
1666
|
+
if (isExplicitPowerShellCommand(normalized)) return void 0;
|
|
1667
|
+
if (!looksLikePowerShellScript(normalized)) {
|
|
1668
|
+
return void 0;
|
|
1669
|
+
}
|
|
1670
|
+
return {
|
|
1671
|
+
command: [
|
|
1672
|
+
"powershell.exe -NoProfile -NonInteractive -Command",
|
|
1673
|
+
quoteCmdArg(`$ErrorActionPreference='Stop'; ${normalized}`)
|
|
1674
|
+
].join(" "),
|
|
1675
|
+
adapter: "powershell-adapted",
|
|
1676
|
+
logCommand: `powershell.exe -NoProfile -NonInteractive -Command <powershell script>`
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function looksLikePowerShellScript(command) {
|
|
1680
|
+
const normalized = command.trim();
|
|
1681
|
+
if (/^\$[A-Za-z_][\w]*\s*=/u.test(normalized)) return true;
|
|
1682
|
+
if (/^\$PWD\.Path\b/iu.test(normalized)) return true;
|
|
1683
|
+
if (/@['"][\s\S]*?['"]@/u.test(normalized)) return true;
|
|
1684
|
+
if (/^\$[A-Za-z_][\w]*\s*\|/u.test(normalized) || /;\s*\$[A-Za-z_][\w]*\s*\|/u.test(normalized)) {
|
|
1685
|
+
return true;
|
|
1686
|
+
}
|
|
1687
|
+
const cmdlet = /\b(?:Get|Set|New|Remove|Select|ForEach|Where|Test|Resolve|Join|Split|Copy|Move|Write|Out|Measure|Compare|Sort|Format)-[A-Za-z]+\b/u;
|
|
1688
|
+
if (!cmdlet.test(normalized)) return false;
|
|
1689
|
+
if (/^(?:Get|Set|New|Remove|Select|ForEach|Where|Test|Resolve|Join|Split|Copy|Move|Write|Out|Measure|Compare|Sort|Format)-[A-Za-z]+\b/u.test(normalized)) {
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
return /[;|]/u.test(normalized) || /\$[A-Za-z_][\w]*(?:\.|\s*\|)/u.test(normalized);
|
|
1693
|
+
}
|
|
1694
|
+
function blockUnsupportedPosixShellSyntax(command) {
|
|
1695
|
+
const normalized = command.replace(/\r\n/gu, "\n").trim();
|
|
1696
|
+
if (!normalized) return void 0;
|
|
1697
|
+
const message = "Unsupported POSIX shell syntax on Windows; use PowerShell-safe commands, Node one-liners, or structured tools.";
|
|
1698
|
+
if (/<<\s*['"]?[A-Za-z_][\w.-]*['"]?/u.test(normalized)) {
|
|
1699
|
+
return createBlockedPowerShellAdapter(message);
|
|
1700
|
+
}
|
|
1701
|
+
if (/(?:^|\n|;)\s*export\s+[A-Za-z_][\w]*=/u.test(normalized)) {
|
|
1702
|
+
return createBlockedPowerShellAdapter(message);
|
|
1703
|
+
}
|
|
1704
|
+
if (/^(?:[A-Za-z_][\w]*=[^\s]+\s+)+\S+/u.test(normalized)) {
|
|
1705
|
+
return createBlockedPowerShellAdapter(message);
|
|
1706
|
+
}
|
|
1707
|
+
if (/\$\([^)]*\)/u.test(normalized)) {
|
|
1708
|
+
return createBlockedPowerShellAdapter(message);
|
|
1709
|
+
}
|
|
1710
|
+
if (/\n/u.test(normalized)) {
|
|
1711
|
+
return createBlockedPowerShellAdapter(message);
|
|
1712
|
+
}
|
|
1713
|
+
return void 0;
|
|
1714
|
+
}
|
|
1839
1715
|
function convertNodeHereDocForPowerShell(command) {
|
|
1840
1716
|
const normalized = command.replace(/\r\n/gu, "\n");
|
|
1841
1717
|
const match = normalized.match(
|
|
@@ -2182,14 +2058,6 @@ function resolveWorkspacePath(workspaceRoot, inputPath) {
|
|
|
2182
2058
|
function relativePath(workspaceRoot, filePath) {
|
|
2183
2059
|
return relative(workspaceRoot, filePath).replaceAll("\\", "/") || ".";
|
|
2184
2060
|
}
|
|
2185
|
-
function resolveArtifactPath(context, inputPath) {
|
|
2186
|
-
const absolute = resolveWorkspacePath(context.workspaceRoot, inputPath);
|
|
2187
|
-
return {
|
|
2188
|
-
input: inputPath,
|
|
2189
|
-
absolute,
|
|
2190
|
-
relative: relativePath(context.workspaceRoot, absolute)
|
|
2191
|
-
};
|
|
2192
|
-
}
|
|
2193
2061
|
function ensureUnique(content, oldText) {
|
|
2194
2062
|
if (!oldText) {
|
|
2195
2063
|
throw new Error("oldText \u4E0D\u80FD\u4E3A\u7A7A\u3002\u5EFA\u8BAE\uFF1A\u63D0\u4F9B\u8DB3\u591F\u4E0A\u4E0B\u6587\u7684\u552F\u4E00\u7247\u6BB5\u3002");
|
|
@@ -2256,6 +2124,8 @@ function rememberReadSnapshot(context, filePath, content, info) {
|
|
|
2256
2124
|
function createEditOutput(context, operation, filePath, before, after, readGuard, editCount = 1) {
|
|
2257
2125
|
const rel = relativePath(context.workspaceRoot, filePath);
|
|
2258
2126
|
const summary = createPatchSummary([rel], before, after);
|
|
2127
|
+
const structuredPatch = createStructuredPatch(rel, before, after);
|
|
2128
|
+
const patchHunks = structuredPatch.files.flatMap((file) => file.hunks);
|
|
2259
2129
|
context.patchSummaries = { ...context.patchSummaries ?? {}, [rel]: summary };
|
|
2260
2130
|
const newlineBefore = detectNewlineStyle(before);
|
|
2261
2131
|
const newlineAfter = detectNewlineStyle(after);
|
|
@@ -2281,11 +2151,46 @@ function createEditOutput(context, operation, filePath, before, after, readGuard
|
|
|
2281
2151
|
afterHash: hashText(after),
|
|
2282
2152
|
newlineBefore,
|
|
2283
2153
|
newlineAfter,
|
|
2284
|
-
encoding: "utf8"
|
|
2154
|
+
encoding: "utf8",
|
|
2155
|
+
structuredPatch,
|
|
2156
|
+
patchHunks
|
|
2285
2157
|
},
|
|
2286
2158
|
changedFiles: [rel]
|
|
2287
2159
|
};
|
|
2288
2160
|
}
|
|
2161
|
+
var STRUCTURED_PATCH_LINE_LIMIT = 120;
|
|
2162
|
+
function createStructuredPatch(path, before, after) {
|
|
2163
|
+
const beforeLines = splitPatchLines(before);
|
|
2164
|
+
const afterLines = splitPatchLines(after);
|
|
2165
|
+
const hunk = createPatchHunk(beforeLines, afterLines);
|
|
2166
|
+
return { files: [{ path, hunks: hunk ? [hunk] : [] }] };
|
|
2167
|
+
}
|
|
2168
|
+
function splitPatchLines(content) {
|
|
2169
|
+
if (content.length === 0) return [];
|
|
2170
|
+
return content.replace(/\r\n/gu, "\n").replace(/\n$/u, "").split("\n");
|
|
2171
|
+
}
|
|
2172
|
+
function createPatchHunk(beforeLines, afterLines) {
|
|
2173
|
+
let prefix = 0;
|
|
2174
|
+
while (prefix < beforeLines.length && prefix < afterLines.length && beforeLines[prefix] === afterLines[prefix]) {
|
|
2175
|
+
prefix += 1;
|
|
2176
|
+
}
|
|
2177
|
+
let suffix = 0;
|
|
2178
|
+
while (suffix < beforeLines.length - prefix && suffix < afterLines.length - prefix && beforeLines[beforeLines.length - 1 - suffix] === afterLines[afterLines.length - 1 - suffix]) {
|
|
2179
|
+
suffix += 1;
|
|
2180
|
+
}
|
|
2181
|
+
const oldLines = beforeLines.slice(prefix, beforeLines.length - suffix);
|
|
2182
|
+
const newLines = afterLines.slice(prefix, afterLines.length - suffix);
|
|
2183
|
+
if (oldLines.length === 0 && newLines.length === 0) return void 0;
|
|
2184
|
+
return {
|
|
2185
|
+
oldStart: oldLines.length > 0 ? prefix + 1 : prefix,
|
|
2186
|
+
newStart: newLines.length > 0 ? prefix + 1 : prefix,
|
|
2187
|
+
oldLines: oldLines.slice(0, STRUCTURED_PATCH_LINE_LIMIT),
|
|
2188
|
+
newLines: newLines.slice(0, STRUCTURED_PATCH_LINE_LIMIT),
|
|
2189
|
+
oldLineCount: oldLines.length,
|
|
2190
|
+
newLineCount: newLines.length,
|
|
2191
|
+
truncated: oldLines.length > STRUCTURED_PATCH_LINE_LIMIT || newLines.length > STRUCTURED_PATCH_LINE_LIMIT
|
|
2192
|
+
};
|
|
2193
|
+
}
|
|
2289
2194
|
function createPatchSummary(changedFiles, before, after) {
|
|
2290
2195
|
const beforeLines = before.length > 0 ? before.split(/\r?\n/u) : [];
|
|
2291
2196
|
const afterLines = after.length > 0 ? after.split(/\r?\n/u) : [];
|
package/dist/tools/prompts.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toolPrompts
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-XGK6YYZO.js";
|
|
4
4
|
import "../chunk-4EZHIDZ6.js";
|
|
5
|
+
import "../chunk-YR4HWOR2.js";
|
|
6
|
+
import "../chunk-VAFW24RN.js";
|
|
7
|
+
import "../chunk-LGZOG7IQ.js";
|
|
8
|
+
import "../chunk-MFHY7PBM.js";
|
|
9
|
+
import "../chunk-SZFZPQGL.js";
|
|
10
|
+
import "../chunk-XZWSO5CM.js";
|
|
5
11
|
import "../chunk-I3Z4OKMS.js";
|
|
6
12
|
import "../chunk-PS2ZOFZ6.js";
|
|
7
13
|
import "../chunk-NPKLGVDQ.js";
|
|
8
|
-
import "../chunk-VJDLOFCF.js";
|
|
9
|
-
import "../chunk-3RP665TH.js";
|
|
10
|
-
import "../chunk-IOC3BSPT.js";
|
|
11
|
-
import "../chunk-LGZOG7IQ.js";
|
|
12
|
-
import "../chunk-ZYAEUABC.js";
|
|
13
|
-
import "../chunk-SWK6XRZQ.js";
|
|
14
|
-
import "../chunk-YR4HWOR2.js";
|
|
15
|
-
import "../chunk-VAFW24RN.js";
|
|
16
14
|
import "../chunk-TZ6QK52L.js";
|
|
17
15
|
import "../chunk-K3YDFDLP.js";
|
|
18
16
|
import "../chunk-GI5XI4HN.js";
|
|
19
17
|
import "../chunk-WEWXKRKL.js";
|
|
20
18
|
import "../chunk-A6FUAM64.js";
|
|
21
19
|
import "../chunk-YCO6C7KF.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
24
|
-
import "../chunk-SZFZPQGL.js";
|
|
25
|
-
import "../chunk-WLQ7DGMG.js";
|
|
26
|
-
import "../chunk-SQP6SJRP.js";
|
|
27
|
-
import "../chunk-BRG64AEC.js";
|
|
20
|
+
import "../chunk-ZYAEUABC.js";
|
|
21
|
+
import "../chunk-SWK6XRZQ.js";
|
|
28
22
|
import "../chunk-AZCQL24J.js";
|
|
29
23
|
import "../chunk-HUIZOB4A.js";
|
|
30
24
|
import "../chunk-MK3YP2VR.js";
|
|
25
|
+
import "../chunk-VJDLOFCF.js";
|
|
26
|
+
import "../chunk-3RP665TH.js";
|
|
27
|
+
import "../chunk-IOC3BSPT.js";
|
|
31
28
|
import "../chunk-HNIVNZIS.js";
|
|
29
|
+
import "../chunk-WLQ7DGMG.js";
|
|
30
|
+
import "../chunk-SQP6SJRP.js";
|
|
31
|
+
import "../chunk-BRG64AEC.js";
|
|
32
32
|
import "../chunk-7ZOADACP.js";
|
|
33
33
|
import "../chunk-H5OOD2OS.js";
|
|
34
34
|
import "../chunk-IQP3XE32.js";
|
package/dist/tools/ui.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toolUserFacingNames
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-PNXZO2UE.js";
|
|
4
4
|
import "../chunk-4EZHIDZ6.js";
|
|
5
|
+
import "../chunk-YR4HWOR2.js";
|
|
6
|
+
import "../chunk-VAFW24RN.js";
|
|
7
|
+
import "../chunk-LGZOG7IQ.js";
|
|
8
|
+
import "../chunk-MFHY7PBM.js";
|
|
9
|
+
import "../chunk-SZFZPQGL.js";
|
|
10
|
+
import "../chunk-XZWSO5CM.js";
|
|
5
11
|
import "../chunk-I3Z4OKMS.js";
|
|
6
12
|
import "../chunk-PS2ZOFZ6.js";
|
|
7
13
|
import "../chunk-NPKLGVDQ.js";
|
|
8
|
-
import "../chunk-VJDLOFCF.js";
|
|
9
|
-
import "../chunk-3RP665TH.js";
|
|
10
|
-
import "../chunk-IOC3BSPT.js";
|
|
11
|
-
import "../chunk-LGZOG7IQ.js";
|
|
12
|
-
import "../chunk-ZYAEUABC.js";
|
|
13
|
-
import "../chunk-SWK6XRZQ.js";
|
|
14
|
-
import "../chunk-YR4HWOR2.js";
|
|
15
|
-
import "../chunk-VAFW24RN.js";
|
|
16
14
|
import "../chunk-TZ6QK52L.js";
|
|
17
15
|
import "../chunk-K3YDFDLP.js";
|
|
18
16
|
import "../chunk-GI5XI4HN.js";
|
|
19
17
|
import "../chunk-WEWXKRKL.js";
|
|
20
18
|
import "../chunk-A6FUAM64.js";
|
|
21
19
|
import "../chunk-YCO6C7KF.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
24
|
-
import "../chunk-SZFZPQGL.js";
|
|
25
|
-
import "../chunk-WLQ7DGMG.js";
|
|
26
|
-
import "../chunk-SQP6SJRP.js";
|
|
27
|
-
import "../chunk-BRG64AEC.js";
|
|
20
|
+
import "../chunk-ZYAEUABC.js";
|
|
21
|
+
import "../chunk-SWK6XRZQ.js";
|
|
28
22
|
import "../chunk-AZCQL24J.js";
|
|
29
23
|
import "../chunk-HUIZOB4A.js";
|
|
30
24
|
import "../chunk-MK3YP2VR.js";
|
|
25
|
+
import "../chunk-VJDLOFCF.js";
|
|
26
|
+
import "../chunk-3RP665TH.js";
|
|
27
|
+
import "../chunk-IOC3BSPT.js";
|
|
31
28
|
import "../chunk-HNIVNZIS.js";
|
|
29
|
+
import "../chunk-WLQ7DGMG.js";
|
|
30
|
+
import "../chunk-SQP6SJRP.js";
|
|
31
|
+
import "../chunk-BRG64AEC.js";
|
|
32
32
|
import "../chunk-7ZOADACP.js";
|
|
33
33
|
import "../chunk-H5OOD2OS.js";
|
|
34
34
|
import "../chunk-IQP3XE32.js";
|