@ai-sdk/harness-codex 1.0.27 → 1.0.29
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/CHANGELOG.md +12 -0
- package/dist/bridge/index.mjs +202 -164
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/bridge/cli-relay.ts +76 -6
- package/src/bridge/index.ts +9 -122
- package/src/bridge/tool-relay-auth.ts +56 -95
- package/src/bridge/tool-relay.ts +119 -0
package/CHANGELOG.md
CHANGED
package/dist/bridge/index.mjs
CHANGED
|
@@ -480,7 +480,6 @@ function serialiseError(err) {
|
|
|
480
480
|
// src/bridge/index.ts
|
|
481
481
|
import { randomUUID } from "crypto";
|
|
482
482
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
483
|
-
import { createServer } from "http";
|
|
484
483
|
|
|
485
484
|
// src/bridge/cli-relay.ts
|
|
486
485
|
var CLI_SHIM_FILENAME = "harness-tool.mjs";
|
|
@@ -520,24 +519,39 @@ if (!response.ok || payload.error) {
|
|
|
520
519
|
console.log(JSON.stringify(payload.result ?? payload, null, 2));
|
|
521
520
|
`;
|
|
522
521
|
}
|
|
523
|
-
function
|
|
522
|
+
function parseToolRelayCommands({
|
|
524
523
|
command,
|
|
525
524
|
cliShimPath
|
|
526
525
|
}) {
|
|
527
|
-
return
|
|
526
|
+
return parseToolRelayCommandsInternal({ command, cliShimPath, depth: 0 });
|
|
528
527
|
}
|
|
529
|
-
function
|
|
528
|
+
function parseToolRelayCommandsInternal({
|
|
530
529
|
command,
|
|
531
530
|
cliShimPath,
|
|
532
531
|
depth
|
|
533
532
|
}) {
|
|
533
|
+
const commands = splitShellAndCommands(command);
|
|
534
|
+
if (!commands) return void 0;
|
|
535
|
+
if (commands.length > 1) {
|
|
536
|
+
const relayCalls = [];
|
|
537
|
+
for (const nestedCommand of commands) {
|
|
538
|
+
const nestedCalls = parseToolRelayCommandsInternal({
|
|
539
|
+
command: nestedCommand,
|
|
540
|
+
cliShimPath,
|
|
541
|
+
depth
|
|
542
|
+
});
|
|
543
|
+
if (!nestedCalls) return void 0;
|
|
544
|
+
relayCalls.push(...nestedCalls);
|
|
545
|
+
}
|
|
546
|
+
return relayCalls;
|
|
547
|
+
}
|
|
534
548
|
const argv2 = parseShellWords(command);
|
|
535
549
|
if (!argv2) return void 0;
|
|
536
550
|
const relayCall = parseDirectToolRelayArgv({ argv: argv2, cliShimPath });
|
|
537
|
-
if (relayCall) return relayCall;
|
|
551
|
+
if (relayCall) return [relayCall];
|
|
538
552
|
const innerCommand = extractShellEvalCommand(argv2);
|
|
539
553
|
if (!innerCommand || depth >= 2) return void 0;
|
|
540
|
-
return
|
|
554
|
+
return parseToolRelayCommandsInternal({
|
|
541
555
|
command: innerCommand,
|
|
542
556
|
cliShimPath,
|
|
543
557
|
depth: depth + 1
|
|
@@ -566,6 +580,46 @@ function extractShellEvalCommand(argv2) {
|
|
|
566
580
|
if (argv2[1] !== "-c" && argv2[1] !== "-lc") return void 0;
|
|
567
581
|
return argv2[2];
|
|
568
582
|
}
|
|
583
|
+
function splitShellAndCommands(command) {
|
|
584
|
+
const commands = [];
|
|
585
|
+
let start = 0;
|
|
586
|
+
let quote;
|
|
587
|
+
for (let i = 0; i < command.length; i++) {
|
|
588
|
+
const char = command[i];
|
|
589
|
+
if (quote === "'") {
|
|
590
|
+
if (char === "'") quote = void 0;
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
if (quote === '"') {
|
|
594
|
+
if (char === '"') {
|
|
595
|
+
quote = void 0;
|
|
596
|
+
} else if (char === "\\") {
|
|
597
|
+
i++;
|
|
598
|
+
}
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (char === '"' || char === "'") {
|
|
602
|
+
quote = char;
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (char === "\\") {
|
|
606
|
+
i++;
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
if (char === "&" && command[i + 1] === "&") {
|
|
610
|
+
const nestedCommand2 = command.slice(start, i).trim();
|
|
611
|
+
if (!nestedCommand2) return void 0;
|
|
612
|
+
commands.push(nestedCommand2);
|
|
613
|
+
start = i + 2;
|
|
614
|
+
i++;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (quote) return void 0;
|
|
618
|
+
const nestedCommand = command.slice(start).trim();
|
|
619
|
+
if (!nestedCommand) return void 0;
|
|
620
|
+
commands.push(nestedCommand);
|
|
621
|
+
return commands;
|
|
622
|
+
}
|
|
569
623
|
function parseShellWords(command) {
|
|
570
624
|
const words = [];
|
|
571
625
|
let current = "";
|
|
@@ -670,40 +724,71 @@ function defaultUsage() {
|
|
|
670
724
|
};
|
|
671
725
|
}
|
|
672
726
|
|
|
727
|
+
// src/bridge/tool-relay.ts
|
|
728
|
+
import { createServer } from "http";
|
|
729
|
+
|
|
673
730
|
// src/bridge/tool-relay-auth.ts
|
|
674
|
-
import { readdir, readFile, readlink } from "fs/promises";
|
|
675
731
|
var ToolRelayAuthorizer = class {
|
|
676
732
|
constructor({
|
|
677
733
|
ttlMs = 1e4,
|
|
678
734
|
now = Date.now
|
|
679
735
|
} = {}) {
|
|
680
736
|
this.authorizations = [];
|
|
737
|
+
this.pendingRequests = [];
|
|
681
738
|
this.ttlMs = ttlMs;
|
|
682
739
|
this.now = now;
|
|
683
740
|
}
|
|
684
741
|
authorizeToolCall(call) {
|
|
685
742
|
this.pruneExpired();
|
|
743
|
+
const key = toolRelayCallKey(call);
|
|
744
|
+
const pendingRequestIndex = this.pendingRequests.findIndex(
|
|
745
|
+
(request) => request.key === key
|
|
746
|
+
);
|
|
747
|
+
if (pendingRequestIndex !== -1) {
|
|
748
|
+
const [pendingRequest] = this.pendingRequests.splice(
|
|
749
|
+
pendingRequestIndex,
|
|
750
|
+
1
|
|
751
|
+
);
|
|
752
|
+
clearTimeout(pendingRequest.timeout);
|
|
753
|
+
pendingRequest.resolve(true);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
686
756
|
this.authorizations.push({
|
|
687
|
-
key
|
|
757
|
+
key,
|
|
688
758
|
expiresAt: this.now() + this.ttlMs
|
|
689
759
|
});
|
|
690
760
|
}
|
|
691
|
-
|
|
761
|
+
waitForToolCallAuthorization(call) {
|
|
692
762
|
this.pruneExpired();
|
|
693
|
-
|
|
694
|
-
|
|
763
|
+
const key = toolRelayCallKey(call);
|
|
764
|
+
const authorizationIndex = this.authorizations.findIndex(
|
|
765
|
+
(authorization) => authorization.key === key
|
|
766
|
+
);
|
|
767
|
+
if (authorizationIndex !== -1) {
|
|
768
|
+
this.authorizations.splice(authorizationIndex, 1);
|
|
769
|
+
return Promise.resolve(true);
|
|
770
|
+
}
|
|
771
|
+
const expiresAt = this.now() + this.ttlMs;
|
|
772
|
+
return new Promise((resolve) => {
|
|
773
|
+
const pendingRequest = {
|
|
774
|
+
key,
|
|
775
|
+
expiresAt,
|
|
776
|
+
timeout: setTimeout(() => {
|
|
777
|
+
const index = this.pendingRequests.indexOf(pendingRequest);
|
|
778
|
+
if (index !== -1) this.pendingRequests.splice(index, 1);
|
|
779
|
+
resolve(false);
|
|
780
|
+
}, this.ttlMs),
|
|
781
|
+
resolve
|
|
782
|
+
};
|
|
783
|
+
this.pendingRequests.push(pendingRequest);
|
|
695
784
|
});
|
|
696
785
|
}
|
|
697
|
-
|
|
698
|
-
this.
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
index = this.authorizations.findIndex((auth) => auth.key === void 0);
|
|
786
|
+
close() {
|
|
787
|
+
this.authorizations.length = 0;
|
|
788
|
+
for (const pendingRequest of this.pendingRequests.splice(0)) {
|
|
789
|
+
clearTimeout(pendingRequest.timeout);
|
|
790
|
+
pendingRequest.resolve(false);
|
|
703
791
|
}
|
|
704
|
-
if (index === -1) return false;
|
|
705
|
-
this.authorizations.splice(index, 1);
|
|
706
|
-
return true;
|
|
707
792
|
}
|
|
708
793
|
pruneExpired() {
|
|
709
794
|
const now = this.now();
|
|
@@ -712,6 +797,14 @@ var ToolRelayAuthorizer = class {
|
|
|
712
797
|
this.authorizations.splice(i, 1);
|
|
713
798
|
}
|
|
714
799
|
}
|
|
800
|
+
for (let i = this.pendingRequests.length - 1; i >= 0; i--) {
|
|
801
|
+
const pendingRequest = this.pendingRequests[i];
|
|
802
|
+
if (pendingRequest.expiresAt <= now) {
|
|
803
|
+
this.pendingRequests.splice(i, 1);
|
|
804
|
+
clearTimeout(pendingRequest.timeout);
|
|
805
|
+
pendingRequest.resolve(false);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
715
808
|
}
|
|
716
809
|
};
|
|
717
810
|
var ToolRelayPendingCalls = class {
|
|
@@ -753,62 +846,96 @@ function normalizeJsonValue(value) {
|
|
|
753
846
|
}
|
|
754
847
|
return value;
|
|
755
848
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
clientPort: socket.remotePort,
|
|
764
|
-
serverPort: socket.localPort
|
|
765
|
-
});
|
|
766
|
-
if (!inode) return false;
|
|
767
|
-
const cmdline = await findProcessCmdlineForSocketInode({ inode });
|
|
768
|
-
return cmdline?.some((arg) => allowedScriptPaths.has(arg)) ?? false;
|
|
769
|
-
}
|
|
770
|
-
async function findTcpSocketInode({
|
|
771
|
-
clientPort,
|
|
772
|
-
serverPort
|
|
849
|
+
|
|
850
|
+
// src/bridge/tool-relay.ts
|
|
851
|
+
async function startAuthorizedToolRelay({
|
|
852
|
+
tools,
|
|
853
|
+
emit,
|
|
854
|
+
requestToolResult,
|
|
855
|
+
authorizer = new ToolRelayAuthorizer()
|
|
773
856
|
}) {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
if (local?.port === clientPort && remote?.port === serverPort && columns[9] !== "0") {
|
|
783
|
-
return columns[9];
|
|
857
|
+
const toolNames = new Set(tools.map((tool) => tool.name));
|
|
858
|
+
const pendingCalls = new ToolRelayPendingCalls();
|
|
859
|
+
const server = createServer(async (req, res) => {
|
|
860
|
+
try {
|
|
861
|
+
if (req.method !== "POST" || req.url !== "/") {
|
|
862
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
863
|
+
res.end(JSON.stringify({ error: "unauthorized tool relay request" }));
|
|
864
|
+
return;
|
|
784
865
|
}
|
|
866
|
+
const chunks = [];
|
|
867
|
+
for await (const chunk of req) {
|
|
868
|
+
chunks.push(chunk);
|
|
869
|
+
}
|
|
870
|
+
const body = Buffer.concat(chunks).toString("utf8");
|
|
871
|
+
const { requestId, toolName, input } = JSON.parse(body);
|
|
872
|
+
if (!toolNames.has(toolName)) {
|
|
873
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
874
|
+
res.end(
|
|
875
|
+
JSON.stringify({ error: `Tool "${toolName}" is not available` })
|
|
876
|
+
);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
const relayCall = { toolName, input };
|
|
880
|
+
if (!await authorizer.waitForToolCallAuthorization(relayCall)) {
|
|
881
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
882
|
+
res.end(JSON.stringify({ error: "unauthorized tool relay request" }));
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
const { result } = pendingCalls.begin({
|
|
886
|
+
call: relayCall,
|
|
887
|
+
run: async () => {
|
|
888
|
+
emit({
|
|
889
|
+
type: "tool-call",
|
|
890
|
+
toolCallId: requestId,
|
|
891
|
+
toolName,
|
|
892
|
+
input: JSON.stringify(input ?? {}),
|
|
893
|
+
providerExecuted: false
|
|
894
|
+
});
|
|
895
|
+
const toolResult = await requestToolResult(requestId);
|
|
896
|
+
emit({
|
|
897
|
+
type: "tool-result",
|
|
898
|
+
toolCallId: requestId,
|
|
899
|
+
toolName,
|
|
900
|
+
result: toolResult.output ?? null,
|
|
901
|
+
isError: !!toolResult.isError
|
|
902
|
+
});
|
|
903
|
+
return toolResult;
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
const { output } = await result;
|
|
907
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
908
|
+
res.end(JSON.stringify({ result: output }));
|
|
909
|
+
} catch (error) {
|
|
910
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
911
|
+
res.end(
|
|
912
|
+
JSON.stringify({
|
|
913
|
+
error: error instanceof Error ? error.message : String(error)
|
|
914
|
+
})
|
|
915
|
+
);
|
|
785
916
|
}
|
|
917
|
+
});
|
|
918
|
+
await new Promise(
|
|
919
|
+
(resolve) => server.listen(0, "127.0.0.1", () => resolve())
|
|
920
|
+
);
|
|
921
|
+
const address = server.address();
|
|
922
|
+
if (!address || typeof address === "string") {
|
|
923
|
+
throw new Error("tool relay did not expose a numeric port");
|
|
786
924
|
}
|
|
787
|
-
return
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
925
|
+
return {
|
|
926
|
+
port: address.port,
|
|
927
|
+
close: () => {
|
|
928
|
+
authorizer.close();
|
|
929
|
+
closeServer(server);
|
|
930
|
+
},
|
|
931
|
+
authorizeToolCall: (call) => authorizer.authorizeToolCall(call)
|
|
932
|
+
};
|
|
793
933
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
() => []
|
|
799
|
-
);
|
|
800
|
-
for (const entry of procEntries) {
|
|
801
|
-
if (!entry.isDirectory() || !/^\d+$/.test(entry.name)) continue;
|
|
802
|
-
const fdDir = `/proc/${entry.name}/fd`;
|
|
803
|
-
const fds = await readdir(fdDir).catch(() => []);
|
|
804
|
-
for (const fd of fds) {
|
|
805
|
-
const target = await readlink(`${fdDir}/${fd}`).catch(() => void 0);
|
|
806
|
-
if (target !== `socket:[${inode}]`) continue;
|
|
807
|
-
const cmdline = await readFile(`/proc/${entry.name}/cmdline`, "utf8").then((value) => value.split("\0").filter(Boolean)).catch(() => void 0);
|
|
808
|
-
if (cmdline) return cmdline;
|
|
809
|
-
}
|
|
934
|
+
function closeServer(server) {
|
|
935
|
+
try {
|
|
936
|
+
server.close();
|
|
937
|
+
} catch {
|
|
810
938
|
}
|
|
811
|
-
return void 0;
|
|
812
939
|
}
|
|
813
940
|
|
|
814
941
|
// src/bridge/index.ts
|
|
@@ -852,7 +979,6 @@ async function runTurn(start, turn) {
|
|
|
852
979
|
if (start.tools && start.tools.length > 0) {
|
|
853
980
|
cliShimPath = `${cliShimDir}/${CLI_SHIM_FILENAME}`;
|
|
854
981
|
relay = await startToolRelay({
|
|
855
|
-
allowedScriptPaths: [cliShimPath, `${bootstrapDir}/host-tool-mcp.mjs`],
|
|
856
982
|
tools: start.tools,
|
|
857
983
|
emit,
|
|
858
984
|
requestToolResult: turn.requestToolResult
|
|
@@ -946,18 +1072,16 @@ async function runTurn(start, turn) {
|
|
|
946
1072
|
emit({ type: "bridge-thread", threadId: event.thread_id });
|
|
947
1073
|
}
|
|
948
1074
|
if (cliShimPath && event.item?.type === "command_execution") {
|
|
949
|
-
const
|
|
1075
|
+
const relayCalls = typeof event.item.command === "string" ? parseToolRelayCommands({
|
|
950
1076
|
command: event.item.command,
|
|
951
1077
|
cliShimPath
|
|
952
1078
|
}) : void 0;
|
|
953
|
-
if (event.type === "item.started" && relay) {
|
|
954
|
-
|
|
1079
|
+
if (event.type === "item.started" && relay && relayCalls) {
|
|
1080
|
+
for (const relayCall of relayCalls) {
|
|
955
1081
|
relay.authorizeToolCall(relayCall);
|
|
956
|
-
} else if (typeof event.item.command !== "string") {
|
|
957
|
-
relay.authorizeAnyToolCall();
|
|
958
1082
|
}
|
|
959
1083
|
}
|
|
960
|
-
if (
|
|
1084
|
+
if (relayCalls) {
|
|
961
1085
|
stepTracker.observeEvent({ event, itemId: event.item.id });
|
|
962
1086
|
continue;
|
|
963
1087
|
}
|
|
@@ -1174,97 +1298,11 @@ function mapUsage(usage) {
|
|
|
1174
1298
|
};
|
|
1175
1299
|
}
|
|
1176
1300
|
async function startToolRelay({
|
|
1177
|
-
allowedScriptPaths,
|
|
1178
1301
|
tools,
|
|
1179
1302
|
emit,
|
|
1180
1303
|
requestToolResult
|
|
1181
1304
|
}) {
|
|
1182
|
-
|
|
1183
|
-
const allowedScriptPathSet = new Set(allowedScriptPaths);
|
|
1184
|
-
const authorizer = new ToolRelayAuthorizer();
|
|
1185
|
-
const pendingCalls = new ToolRelayPendingCalls();
|
|
1186
|
-
const server = createServer(async (req, res) => {
|
|
1187
|
-
try {
|
|
1188
|
-
if (req.method !== "POST" || req.url !== "/") {
|
|
1189
|
-
res.writeHead(401, { "Content-Type": "application/json" });
|
|
1190
|
-
res.end(JSON.stringify({ error: "unauthorized tool relay request" }));
|
|
1191
|
-
return;
|
|
1192
|
-
}
|
|
1193
|
-
const chunks = [];
|
|
1194
|
-
for await (const chunk of req) {
|
|
1195
|
-
chunks.push(chunk);
|
|
1196
|
-
}
|
|
1197
|
-
const body = Buffer.concat(chunks).toString("utf8");
|
|
1198
|
-
const { requestId, toolName, input } = JSON.parse(body);
|
|
1199
|
-
if (!toolNames.has(toolName)) {
|
|
1200
|
-
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1201
|
-
res.end(
|
|
1202
|
-
JSON.stringify({ error: `Tool "${toolName}" is not available` })
|
|
1203
|
-
);
|
|
1204
|
-
return;
|
|
1205
|
-
}
|
|
1206
|
-
const relayCall = { toolName, input };
|
|
1207
|
-
const authorized = authorizer.consumeToolCall(relayCall) || await isToolRelayRequestFromAllowedProcess({
|
|
1208
|
-
socket: req.socket,
|
|
1209
|
-
allowedScriptPaths: allowedScriptPathSet
|
|
1210
|
-
});
|
|
1211
|
-
if (!authorized) {
|
|
1212
|
-
res.writeHead(401, { "Content-Type": "application/json" });
|
|
1213
|
-
res.end(JSON.stringify({ error: "unauthorized tool relay request" }));
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1216
|
-
const { result } = pendingCalls.begin({
|
|
1217
|
-
call: relayCall,
|
|
1218
|
-
run: async () => {
|
|
1219
|
-
emit({
|
|
1220
|
-
type: "tool-call",
|
|
1221
|
-
toolCallId: requestId,
|
|
1222
|
-
toolName,
|
|
1223
|
-
input: JSON.stringify(input ?? {}),
|
|
1224
|
-
providerExecuted: false
|
|
1225
|
-
});
|
|
1226
|
-
const toolResult = await requestToolResult(requestId);
|
|
1227
|
-
emit({
|
|
1228
|
-
type: "tool-result",
|
|
1229
|
-
toolCallId: requestId,
|
|
1230
|
-
toolName,
|
|
1231
|
-
result: toolResult.output ?? null,
|
|
1232
|
-
isError: !!toolResult.isError
|
|
1233
|
-
});
|
|
1234
|
-
return toolResult;
|
|
1235
|
-
}
|
|
1236
|
-
});
|
|
1237
|
-
const { output } = await result;
|
|
1238
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1239
|
-
res.end(JSON.stringify({ result: output }));
|
|
1240
|
-
} catch (error) {
|
|
1241
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1242
|
-
res.end(
|
|
1243
|
-
JSON.stringify({
|
|
1244
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1245
|
-
})
|
|
1246
|
-
);
|
|
1247
|
-
}
|
|
1248
|
-
});
|
|
1249
|
-
await new Promise(
|
|
1250
|
-
(resolve) => server.listen(0, "127.0.0.1", () => resolve())
|
|
1251
|
-
);
|
|
1252
|
-
const address = server.address();
|
|
1253
|
-
if (!address || typeof address === "string") {
|
|
1254
|
-
throw new Error("tool relay did not expose a numeric port");
|
|
1255
|
-
}
|
|
1256
|
-
return {
|
|
1257
|
-
port: address.port,
|
|
1258
|
-
close: () => closeServer(server),
|
|
1259
|
-
authorizeToolCall: (call) => authorizer.authorizeToolCall(call),
|
|
1260
|
-
authorizeAnyToolCall: () => authorizer.authorizeAnyToolCall()
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1263
|
-
function closeServer(server) {
|
|
1264
|
-
try {
|
|
1265
|
-
server.close();
|
|
1266
|
-
} catch {
|
|
1267
|
-
}
|
|
1305
|
+
return startAuthorizedToolRelay({ tools, emit, requestToolResult });
|
|
1268
1306
|
}
|
|
1269
1307
|
function parseArgs(args2) {
|
|
1270
1308
|
const out = {};
|