@ai-sdk/harness-codex 1.0.41 → 1.0.43
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 +18 -0
- package/dist/bridge/index.mjs +209 -193
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/bridge/create-emit-stream-event.ts +287 -0
- package/src/bridge/index.ts +13 -292
- package/src/codex-harness.ts +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @ai-sdk/harness-codex
|
|
2
2
|
|
|
3
|
+
## 1.0.43
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 07c977a: chore(harness): refactor bridge code to break out stream event emission from launcher to make it testable
|
|
8
|
+
- 560db3a: fix(harness-codex): fix obsolete default Codex model ID
|
|
9
|
+
- Updated dependencies [a94425b]
|
|
10
|
+
- Updated dependencies [2de0611]
|
|
11
|
+
- @ai-sdk/harness@1.0.41
|
|
12
|
+
|
|
13
|
+
## 1.0.42
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [59a2306]
|
|
18
|
+
- Updated dependencies [5f65e61]
|
|
19
|
+
- @ai-sdk/harness@1.0.40
|
|
20
|
+
|
|
3
21
|
## 1.0.41
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/bridge/index.mjs
CHANGED
|
@@ -53,6 +53,7 @@ async function runBridge(options) {
|
|
|
53
53
|
let currentBoundPort = 0;
|
|
54
54
|
let currentTurnState = "init";
|
|
55
55
|
let activeSocket;
|
|
56
|
+
let activeSocketReadyForLiveEvents = false;
|
|
56
57
|
let isFirstTurn = true;
|
|
57
58
|
let turnAbort;
|
|
58
59
|
let currentUserMessages;
|
|
@@ -152,7 +153,7 @@ async function runBridge(options) {
|
|
|
152
153
|
diskBuffer += `${line}
|
|
153
154
|
`;
|
|
154
155
|
scheduleEventFlush();
|
|
155
|
-
if (activeSocket?.readyState === WS_OPEN) {
|
|
156
|
+
if (activeSocketReadyForLiveEvents && activeSocket?.readyState === WS_OPEN) {
|
|
156
157
|
try {
|
|
157
158
|
activeSocket.send(line);
|
|
158
159
|
} catch {
|
|
@@ -255,6 +256,8 @@ async function runBridge(options) {
|
|
|
255
256
|
const handleInbound = async (msg, ws) => {
|
|
256
257
|
switch (msg.type) {
|
|
257
258
|
case "start": {
|
|
259
|
+
if (activeSocket !== ws) return;
|
|
260
|
+
activeSocketReadyForLiveEvents = true;
|
|
258
261
|
const firstTurn = isFirstTurn;
|
|
259
262
|
isFirstTurn = false;
|
|
260
263
|
eventLog = [];
|
|
@@ -357,7 +360,9 @@ async function runBridge(options) {
|
|
|
357
360
|
}
|
|
358
361
|
return;
|
|
359
362
|
case "resume":
|
|
363
|
+
if (activeSocket !== ws) return;
|
|
360
364
|
replay(ws, msg.lastSeenEventId);
|
|
365
|
+
activeSocketReadyForLiveEvents = true;
|
|
361
366
|
return;
|
|
362
367
|
case "shutdown":
|
|
363
368
|
currentTurnState = "done";
|
|
@@ -422,6 +427,7 @@ async function runBridge(options) {
|
|
|
422
427
|
return;
|
|
423
428
|
}
|
|
424
429
|
activeSocket = ws;
|
|
430
|
+
activeSocketReadyForLiveEvents = false;
|
|
425
431
|
sendControl({
|
|
426
432
|
type: "bridge-hello",
|
|
427
433
|
state: currentTurnState,
|
|
@@ -444,6 +450,7 @@ async function runBridge(options) {
|
|
|
444
450
|
ws.on("close", () => {
|
|
445
451
|
if (activeSocket === ws) {
|
|
446
452
|
activeSocket = void 0;
|
|
453
|
+
activeSocketReadyForLiveEvents = false;
|
|
447
454
|
}
|
|
448
455
|
});
|
|
449
456
|
ws.on("error", () => {
|
|
@@ -478,7 +485,6 @@ function serialiseError(err) {
|
|
|
478
485
|
}
|
|
479
486
|
|
|
480
487
|
// src/bridge/index.ts
|
|
481
|
-
import { randomUUID } from "crypto";
|
|
482
488
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
483
489
|
|
|
484
490
|
// src/bridge/cli-relay.ts
|
|
@@ -724,6 +730,198 @@ function defaultUsage() {
|
|
|
724
730
|
};
|
|
725
731
|
}
|
|
726
732
|
|
|
733
|
+
// src/bridge/create-emit-stream-event.ts
|
|
734
|
+
import { randomUUID } from "crypto";
|
|
735
|
+
var NATIVE_TO_COMMON = {
|
|
736
|
+
shell: "bash",
|
|
737
|
+
web_search: "webSearch"
|
|
738
|
+
};
|
|
739
|
+
function toCommonName(nativeName) {
|
|
740
|
+
return NATIVE_TO_COMMON[nativeName] ?? nativeName;
|
|
741
|
+
}
|
|
742
|
+
function createEmitStreamEvent({
|
|
743
|
+
send,
|
|
744
|
+
stepTracker,
|
|
745
|
+
setTurnUsage,
|
|
746
|
+
setThreadId,
|
|
747
|
+
emitWarning,
|
|
748
|
+
emitError
|
|
749
|
+
}) {
|
|
750
|
+
const textByItem = /* @__PURE__ */ new Map();
|
|
751
|
+
const reasoningByItem = /* @__PURE__ */ new Map();
|
|
752
|
+
return (event) => {
|
|
753
|
+
if (event.type === "thread.started" && typeof event.thread_id === "string") {
|
|
754
|
+
setThreadId(event.thread_id);
|
|
755
|
+
send({ type: "bridge-thread", threadId: event.thread_id });
|
|
756
|
+
}
|
|
757
|
+
if (event.type === "turn.completed") {
|
|
758
|
+
if (event.usage) setTurnUsage(mapUsage(event.usage));
|
|
759
|
+
stepTracker.finishStep();
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (event.type === "turn.failed") {
|
|
763
|
+
emitError({
|
|
764
|
+
error: event.error?.message ?? "codex turn failed",
|
|
765
|
+
message: "codex turn failed"
|
|
766
|
+
});
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (event.type === "error") {
|
|
770
|
+
emitError({
|
|
771
|
+
error: event.message ?? "codex error",
|
|
772
|
+
message: "codex stream error"
|
|
773
|
+
});
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if (!event.item) return;
|
|
777
|
+
const item = event.item;
|
|
778
|
+
const id = item.id ?? randomUUID();
|
|
779
|
+
const observeStep = () => {
|
|
780
|
+
stepTracker.observeEvent({ event, itemId: id });
|
|
781
|
+
};
|
|
782
|
+
if (item.type === "agent_message" && typeof item.text === "string") {
|
|
783
|
+
if (!textByItem.has(id)) {
|
|
784
|
+
send({ type: "text-start", id });
|
|
785
|
+
textByItem.set(id, "");
|
|
786
|
+
}
|
|
787
|
+
const last = textByItem.get(id) ?? "";
|
|
788
|
+
const next = item.text;
|
|
789
|
+
if (next.length > last.length) {
|
|
790
|
+
send({ type: "text-delta", id, delta: next.slice(last.length) });
|
|
791
|
+
textByItem.set(id, next);
|
|
792
|
+
}
|
|
793
|
+
if (event.type === "item.completed") send({ type: "text-end", id });
|
|
794
|
+
observeStep();
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (item.type === "reasoning" && typeof item.text === "string") {
|
|
798
|
+
if (!reasoningByItem.has(id)) {
|
|
799
|
+
send({ type: "reasoning-start", id });
|
|
800
|
+
reasoningByItem.set(id, "");
|
|
801
|
+
}
|
|
802
|
+
const last = reasoningByItem.get(id) ?? "";
|
|
803
|
+
const next = item.text;
|
|
804
|
+
if (next.length > last.length) {
|
|
805
|
+
send({ type: "reasoning-delta", id, delta: next.slice(last.length) });
|
|
806
|
+
reasoningByItem.set(id, next);
|
|
807
|
+
}
|
|
808
|
+
if (event.type === "item.completed") send({ type: "reasoning-end", id });
|
|
809
|
+
observeStep();
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
if (item.type === "command_execution") {
|
|
813
|
+
const nativeName = "shell";
|
|
814
|
+
if (event.type === "item.started") {
|
|
815
|
+
send({
|
|
816
|
+
type: "tool-call",
|
|
817
|
+
toolCallId: id,
|
|
818
|
+
toolName: toCommonName(nativeName),
|
|
819
|
+
nativeName,
|
|
820
|
+
input: JSON.stringify({ command: item.command ?? "" }),
|
|
821
|
+
providerExecuted: true
|
|
822
|
+
});
|
|
823
|
+
} else if (event.type === "item.completed") {
|
|
824
|
+
send({
|
|
825
|
+
type: "tool-result",
|
|
826
|
+
toolCallId: id,
|
|
827
|
+
toolName: toCommonName(nativeName),
|
|
828
|
+
result: {
|
|
829
|
+
exitCode: item.exit_code ?? null,
|
|
830
|
+
output: item.aggregated_output ?? "",
|
|
831
|
+
status: item.status ?? "completed"
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
observeStep();
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
if (item.type === "mcp_tool_call") {
|
|
839
|
+
if (event.type === "item.started") {
|
|
840
|
+
send({
|
|
841
|
+
type: "tool-call",
|
|
842
|
+
toolCallId: id,
|
|
843
|
+
toolName: item.tool ?? "unknown",
|
|
844
|
+
nativeName: item.tool ?? "unknown",
|
|
845
|
+
input: JSON.stringify(item.arguments ?? {}),
|
|
846
|
+
providerExecuted: true
|
|
847
|
+
});
|
|
848
|
+
} else if (event.type === "item.completed") {
|
|
849
|
+
send({
|
|
850
|
+
type: "tool-result",
|
|
851
|
+
toolCallId: id,
|
|
852
|
+
toolName: item.tool ?? "unknown",
|
|
853
|
+
result: extractMcpToolCallResult(item)
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
observeStep();
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
if (item.type === "web_search") {
|
|
860
|
+
const nativeName = "web_search";
|
|
861
|
+
if (event.type === "item.started") {
|
|
862
|
+
send({
|
|
863
|
+
type: "tool-call",
|
|
864
|
+
toolCallId: id,
|
|
865
|
+
toolName: toCommonName(nativeName),
|
|
866
|
+
nativeName,
|
|
867
|
+
input: JSON.stringify({ query: item.query ?? "" }),
|
|
868
|
+
providerExecuted: true
|
|
869
|
+
});
|
|
870
|
+
} else if (event.type === "item.completed") {
|
|
871
|
+
send({
|
|
872
|
+
type: "tool-result",
|
|
873
|
+
toolCallId: id,
|
|
874
|
+
toolName: toCommonName(nativeName),
|
|
875
|
+
result: item.result ?? null
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
observeStep();
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (item.type === "file_change" && event.type === "item.completed") {
|
|
882
|
+
for (const change of item.changes ?? []) {
|
|
883
|
+
send({
|
|
884
|
+
type: "file-change",
|
|
885
|
+
event: change.kind === "add" ? "create" : change.kind === "delete" ? "delete" : "modify",
|
|
886
|
+
path: change.path
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
observeStep();
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
if (item.type === "error" && event.type === "item.completed") {
|
|
893
|
+
const message = typeof item.message === "string" && item.message.trim() ? item.message : "codex reported a non-fatal error item";
|
|
894
|
+
emitWarning({ message });
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function extractMcpToolCallResult(item) {
|
|
899
|
+
if (item.result === void 0 || item.result === null || typeof item.result !== "object") {
|
|
900
|
+
return item.error?.message ? { error: item.error.message } : null;
|
|
901
|
+
}
|
|
902
|
+
const result = item.result;
|
|
903
|
+
if (result.structured_content !== void 0 && result.structured_content !== null) {
|
|
904
|
+
return result.structured_content;
|
|
905
|
+
}
|
|
906
|
+
return result.content ?? null;
|
|
907
|
+
}
|
|
908
|
+
function mapUsage(usage) {
|
|
909
|
+
const input = usage.input_tokens ?? 0;
|
|
910
|
+
const cacheRead = usage.cached_input_tokens ?? 0;
|
|
911
|
+
return {
|
|
912
|
+
inputTokens: {
|
|
913
|
+
total: input,
|
|
914
|
+
noCache: Math.max(0, input - cacheRead),
|
|
915
|
+
cacheRead,
|
|
916
|
+
cacheWrite: 0
|
|
917
|
+
},
|
|
918
|
+
outputTokens: {
|
|
919
|
+
total: usage.output_tokens ?? 0,
|
|
920
|
+
text: usage.output_tokens ?? 0
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
|
|
727
925
|
// src/bridge/tool-relay.ts
|
|
728
926
|
import { createServer } from "http";
|
|
729
927
|
|
|
@@ -941,13 +1139,6 @@ function closeServer(server) {
|
|
|
941
1139
|
// src/bridge/index.ts
|
|
942
1140
|
import { argv, env as procEnv2, stdout as stdout2 } from "process";
|
|
943
1141
|
import * as codexSdkModule from "@openai/codex-sdk";
|
|
944
|
-
var NATIVE_TO_COMMON = {
|
|
945
|
-
shell: "bash",
|
|
946
|
-
web_search: "webSearch"
|
|
947
|
-
};
|
|
948
|
-
function toCommonName(nativeName) {
|
|
949
|
-
return NATIVE_TO_COMMON[nativeName] ?? nativeName;
|
|
950
|
-
}
|
|
951
1142
|
var args = parseArgs(argv.slice(2));
|
|
952
1143
|
var workdir = requireArg({ value: args.workdir, name: "--workdir" });
|
|
953
1144
|
var bridgeStateDir = requireArg({
|
|
@@ -1040,19 +1231,21 @@ async function runTurn(start, turn) {
|
|
|
1040
1231
|
emit({ type: "stream-start" });
|
|
1041
1232
|
const userMessage = start.prompt;
|
|
1042
1233
|
let turnUsage;
|
|
1043
|
-
const textByItem = /* @__PURE__ */ new Map();
|
|
1044
|
-
const reasoningByItem = /* @__PURE__ */ new Map();
|
|
1045
1234
|
const stepTracker = createCodexStepTracker({ send: emit });
|
|
1235
|
+
const emitStreamEvent = createEmitStreamEvent({
|
|
1236
|
+
send: emit,
|
|
1237
|
+
stepTracker,
|
|
1238
|
+
setTurnUsage: (usage) => turnUsage = usage,
|
|
1239
|
+
setThreadId: (threadId) => threadState.id = threadId,
|
|
1240
|
+
emitWarning: turn.emitWarning,
|
|
1241
|
+
emitError: turn.emitError
|
|
1242
|
+
});
|
|
1046
1243
|
try {
|
|
1047
1244
|
const { events } = await thread.runStreamed(userMessage, {
|
|
1048
1245
|
signal: turn.abortSignal
|
|
1049
1246
|
});
|
|
1050
1247
|
for await (const event of events) {
|
|
1051
1248
|
if (turn.abortSignal.aborted) break;
|
|
1052
|
-
if (event.type === "thread.started" && typeof event.thread_id === "string") {
|
|
1053
|
-
threadState.id = event.thread_id;
|
|
1054
|
-
emit({ type: "bridge-thread", threadId: event.thread_id });
|
|
1055
|
-
}
|
|
1056
1249
|
if (cliShimPath && event.item?.type === "command_execution") {
|
|
1057
1250
|
const relayCalls = typeof event.item.command === "string" ? parseToolRelayCommands({
|
|
1058
1251
|
command: event.item.command,
|
|
@@ -1068,15 +1261,7 @@ async function runTurn(start, turn) {
|
|
|
1068
1261
|
continue;
|
|
1069
1262
|
}
|
|
1070
1263
|
}
|
|
1071
|
-
|
|
1072
|
-
send: emit,
|
|
1073
|
-
textByItem,
|
|
1074
|
-
reasoningByItem,
|
|
1075
|
-
stepTracker,
|
|
1076
|
-
setTurnUsage: (u) => turnUsage = u,
|
|
1077
|
-
emitWarning: turn.emitWarning,
|
|
1078
|
-
emitError: turn.emitError
|
|
1079
|
-
});
|
|
1264
|
+
emitStreamEvent(event);
|
|
1080
1265
|
}
|
|
1081
1266
|
} catch (err) {
|
|
1082
1267
|
turn.emitError({ error: err, message: "codex turn failed" });
|
|
@@ -1091,175 +1276,6 @@ async function runTurn(start, turn) {
|
|
|
1091
1276
|
});
|
|
1092
1277
|
void turn.pendingUserMessages;
|
|
1093
1278
|
}
|
|
1094
|
-
function extractMcpToolCallResult(item) {
|
|
1095
|
-
if (item.result === void 0 || item.result === null || typeof item.result !== "object") {
|
|
1096
|
-
return item.error?.message ? { error: item.error.message } : null;
|
|
1097
|
-
}
|
|
1098
|
-
const result = item.result;
|
|
1099
|
-
if (result.structured_content !== void 0 && result.structured_content !== null) {
|
|
1100
|
-
return result.structured_content;
|
|
1101
|
-
}
|
|
1102
|
-
return result.content ?? null;
|
|
1103
|
-
}
|
|
1104
|
-
function translateAndEmit(event, ctx) {
|
|
1105
|
-
if (event.type === "turn.completed") {
|
|
1106
|
-
if (event.usage) ctx.setTurnUsage(mapUsage(event.usage));
|
|
1107
|
-
ctx.stepTracker.finishStep();
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
if (event.type === "turn.failed") {
|
|
1111
|
-
ctx.emitError({
|
|
1112
|
-
error: event.error?.message ?? "codex turn failed",
|
|
1113
|
-
message: "codex turn failed"
|
|
1114
|
-
});
|
|
1115
|
-
return;
|
|
1116
|
-
}
|
|
1117
|
-
if (event.type === "error") {
|
|
1118
|
-
ctx.emitError({
|
|
1119
|
-
error: event.message ?? "codex error",
|
|
1120
|
-
message: "codex stream error"
|
|
1121
|
-
});
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
if (!event.item) return;
|
|
1125
|
-
const item = event.item;
|
|
1126
|
-
const id = item.id ?? randomUUID();
|
|
1127
|
-
const observeStep = () => {
|
|
1128
|
-
ctx.stepTracker.observeEvent({ event, itemId: id });
|
|
1129
|
-
};
|
|
1130
|
-
if (item.type === "agent_message" && typeof item.text === "string") {
|
|
1131
|
-
if (!ctx.textByItem.has(id)) {
|
|
1132
|
-
ctx.send({ type: "text-start", id });
|
|
1133
|
-
ctx.textByItem.set(id, "");
|
|
1134
|
-
}
|
|
1135
|
-
const last = ctx.textByItem.get(id) ?? "";
|
|
1136
|
-
const next = item.text;
|
|
1137
|
-
if (next.length > last.length) {
|
|
1138
|
-
ctx.send({ type: "text-delta", id, delta: next.slice(last.length) });
|
|
1139
|
-
ctx.textByItem.set(id, next);
|
|
1140
|
-
}
|
|
1141
|
-
if (event.type === "item.completed") ctx.send({ type: "text-end", id });
|
|
1142
|
-
observeStep();
|
|
1143
|
-
return;
|
|
1144
|
-
}
|
|
1145
|
-
if (item.type === "reasoning" && typeof item.text === "string") {
|
|
1146
|
-
if (!ctx.reasoningByItem.has(id)) {
|
|
1147
|
-
ctx.send({ type: "reasoning-start", id });
|
|
1148
|
-
ctx.reasoningByItem.set(id, "");
|
|
1149
|
-
}
|
|
1150
|
-
const last = ctx.reasoningByItem.get(id) ?? "";
|
|
1151
|
-
const next = item.text;
|
|
1152
|
-
if (next.length > last.length) {
|
|
1153
|
-
ctx.send({ type: "reasoning-delta", id, delta: next.slice(last.length) });
|
|
1154
|
-
ctx.reasoningByItem.set(id, next);
|
|
1155
|
-
}
|
|
1156
|
-
if (event.type === "item.completed")
|
|
1157
|
-
ctx.send({ type: "reasoning-end", id });
|
|
1158
|
-
observeStep();
|
|
1159
|
-
return;
|
|
1160
|
-
}
|
|
1161
|
-
if (item.type === "command_execution") {
|
|
1162
|
-
const nativeName = "shell";
|
|
1163
|
-
if (event.type === "item.started") {
|
|
1164
|
-
ctx.send({
|
|
1165
|
-
type: "tool-call",
|
|
1166
|
-
toolCallId: id,
|
|
1167
|
-
toolName: toCommonName(nativeName),
|
|
1168
|
-
nativeName,
|
|
1169
|
-
input: JSON.stringify({ command: item.command ?? "" }),
|
|
1170
|
-
providerExecuted: true
|
|
1171
|
-
});
|
|
1172
|
-
} else if (event.type === "item.completed") {
|
|
1173
|
-
ctx.send({
|
|
1174
|
-
type: "tool-result",
|
|
1175
|
-
toolCallId: id,
|
|
1176
|
-
toolName: toCommonName(nativeName),
|
|
1177
|
-
result: {
|
|
1178
|
-
exitCode: item.exit_code ?? null,
|
|
1179
|
-
output: item.aggregated_output ?? "",
|
|
1180
|
-
status: item.status ?? "completed"
|
|
1181
|
-
}
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
observeStep();
|
|
1185
|
-
return;
|
|
1186
|
-
}
|
|
1187
|
-
if (item.type === "mcp_tool_call") {
|
|
1188
|
-
if (event.type === "item.started") {
|
|
1189
|
-
ctx.send({
|
|
1190
|
-
type: "tool-call",
|
|
1191
|
-
toolCallId: id,
|
|
1192
|
-
toolName: item.tool ?? "unknown",
|
|
1193
|
-
nativeName: item.tool ?? "unknown",
|
|
1194
|
-
input: JSON.stringify(item.arguments ?? {}),
|
|
1195
|
-
providerExecuted: true
|
|
1196
|
-
});
|
|
1197
|
-
} else if (event.type === "item.completed") {
|
|
1198
|
-
ctx.send({
|
|
1199
|
-
type: "tool-result",
|
|
1200
|
-
toolCallId: id,
|
|
1201
|
-
toolName: item.tool ?? "unknown",
|
|
1202
|
-
result: extractMcpToolCallResult(item)
|
|
1203
|
-
});
|
|
1204
|
-
}
|
|
1205
|
-
observeStep();
|
|
1206
|
-
return;
|
|
1207
|
-
}
|
|
1208
|
-
if (item.type === "web_search") {
|
|
1209
|
-
const nativeName = "web_search";
|
|
1210
|
-
if (event.type === "item.started") {
|
|
1211
|
-
ctx.send({
|
|
1212
|
-
type: "tool-call",
|
|
1213
|
-
toolCallId: id,
|
|
1214
|
-
toolName: toCommonName(nativeName),
|
|
1215
|
-
nativeName,
|
|
1216
|
-
input: JSON.stringify({ query: item.query ?? "" }),
|
|
1217
|
-
providerExecuted: true
|
|
1218
|
-
});
|
|
1219
|
-
} else if (event.type === "item.completed") {
|
|
1220
|
-
ctx.send({
|
|
1221
|
-
type: "tool-result",
|
|
1222
|
-
toolCallId: id,
|
|
1223
|
-
toolName: toCommonName(nativeName),
|
|
1224
|
-
result: item.result ?? null
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
observeStep();
|
|
1228
|
-
return;
|
|
1229
|
-
}
|
|
1230
|
-
if (item.type === "file_change" && event.type === "item.completed") {
|
|
1231
|
-
for (const change of item.changes ?? []) {
|
|
1232
|
-
ctx.send({
|
|
1233
|
-
type: "file-change",
|
|
1234
|
-
event: change.kind === "add" ? "create" : change.kind === "delete" ? "delete" : "modify",
|
|
1235
|
-
path: change.path
|
|
1236
|
-
});
|
|
1237
|
-
}
|
|
1238
|
-
observeStep();
|
|
1239
|
-
return;
|
|
1240
|
-
}
|
|
1241
|
-
if (item.type === "error" && event.type === "item.completed") {
|
|
1242
|
-
const message = typeof item.message === "string" && item.message.trim() ? item.message : "codex reported a non-fatal error item";
|
|
1243
|
-
ctx.emitWarning({ message });
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
function mapUsage(usage) {
|
|
1248
|
-
const input = usage.input_tokens ?? 0;
|
|
1249
|
-
const cacheRead = usage.cached_input_tokens ?? 0;
|
|
1250
|
-
return {
|
|
1251
|
-
inputTokens: {
|
|
1252
|
-
total: input,
|
|
1253
|
-
noCache: Math.max(0, input - cacheRead),
|
|
1254
|
-
cacheRead,
|
|
1255
|
-
cacheWrite: 0
|
|
1256
|
-
},
|
|
1257
|
-
outputTokens: {
|
|
1258
|
-
total: usage.output_tokens ?? 0,
|
|
1259
|
-
text: usage.output_tokens ?? 0
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1263
1279
|
async function startToolRelay({
|
|
1264
1280
|
tools,
|
|
1265
1281
|
emit,
|