@ai-sdk/harness-codex 1.0.42 → 1.0.44

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # @ai-sdk/harness-codex
2
2
 
3
+ ## 1.0.44
4
+
5
+ ### Patch Changes
6
+
7
+ - @ai-sdk/harness@1.0.42
8
+
9
+ ## 1.0.43
10
+
11
+ ### Patch Changes
12
+
13
+ - 07c977a: chore(harness): refactor bridge code to break out stream event emission from launcher to make it testable
14
+ - 560db3a: fix(harness-codex): fix obsolete default Codex model ID
15
+ - Updated dependencies [a94425b]
16
+ - Updated dependencies [2de0611]
17
+ - @ai-sdk/harness@1.0.41
18
+
3
19
  ## 1.0.42
4
20
 
5
21
  ### Patch Changes
@@ -485,7 +485,6 @@ function serialiseError(err) {
485
485
  }
486
486
 
487
487
  // src/bridge/index.ts
488
- import { randomUUID } from "crypto";
489
488
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
490
489
 
491
490
  // src/bridge/cli-relay.ts
@@ -731,6 +730,198 @@ function defaultUsage() {
731
730
  };
732
731
  }
733
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
+
734
925
  // src/bridge/tool-relay.ts
735
926
  import { createServer } from "http";
736
927
 
@@ -948,13 +1139,6 @@ function closeServer(server) {
948
1139
  // src/bridge/index.ts
949
1140
  import { argv, env as procEnv2, stdout as stdout2 } from "process";
950
1141
  import * as codexSdkModule from "@openai/codex-sdk";
951
- var NATIVE_TO_COMMON = {
952
- shell: "bash",
953
- web_search: "webSearch"
954
- };
955
- function toCommonName(nativeName) {
956
- return NATIVE_TO_COMMON[nativeName] ?? nativeName;
957
- }
958
1142
  var args = parseArgs(argv.slice(2));
959
1143
  var workdir = requireArg({ value: args.workdir, name: "--workdir" });
960
1144
  var bridgeStateDir = requireArg({
@@ -1047,19 +1231,21 @@ async function runTurn(start, turn) {
1047
1231
  emit({ type: "stream-start" });
1048
1232
  const userMessage = start.prompt;
1049
1233
  let turnUsage;
1050
- const textByItem = /* @__PURE__ */ new Map();
1051
- const reasoningByItem = /* @__PURE__ */ new Map();
1052
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
+ });
1053
1243
  try {
1054
1244
  const { events } = await thread.runStreamed(userMessage, {
1055
1245
  signal: turn.abortSignal
1056
1246
  });
1057
1247
  for await (const event of events) {
1058
1248
  if (turn.abortSignal.aborted) break;
1059
- if (event.type === "thread.started" && typeof event.thread_id === "string") {
1060
- threadState.id = event.thread_id;
1061
- emit({ type: "bridge-thread", threadId: event.thread_id });
1062
- }
1063
1249
  if (cliShimPath && event.item?.type === "command_execution") {
1064
1250
  const relayCalls = typeof event.item.command === "string" ? parseToolRelayCommands({
1065
1251
  command: event.item.command,
@@ -1075,15 +1261,7 @@ async function runTurn(start, turn) {
1075
1261
  continue;
1076
1262
  }
1077
1263
  }
1078
- translateAndEmit(event, {
1079
- send: emit,
1080
- textByItem,
1081
- reasoningByItem,
1082
- stepTracker,
1083
- setTurnUsage: (u) => turnUsage = u,
1084
- emitWarning: turn.emitWarning,
1085
- emitError: turn.emitError
1086
- });
1264
+ emitStreamEvent(event);
1087
1265
  }
1088
1266
  } catch (err) {
1089
1267
  turn.emitError({ error: err, message: "codex turn failed" });
@@ -1098,175 +1276,6 @@ async function runTurn(start, turn) {
1098
1276
  });
1099
1277
  void turn.pendingUserMessages;
1100
1278
  }
1101
- function extractMcpToolCallResult(item) {
1102
- if (item.result === void 0 || item.result === null || typeof item.result !== "object") {
1103
- return item.error?.message ? { error: item.error.message } : null;
1104
- }
1105
- const result = item.result;
1106
- if (result.structured_content !== void 0 && result.structured_content !== null) {
1107
- return result.structured_content;
1108
- }
1109
- return result.content ?? null;
1110
- }
1111
- function translateAndEmit(event, ctx) {
1112
- if (event.type === "turn.completed") {
1113
- if (event.usage) ctx.setTurnUsage(mapUsage(event.usage));
1114
- ctx.stepTracker.finishStep();
1115
- return;
1116
- }
1117
- if (event.type === "turn.failed") {
1118
- ctx.emitError({
1119
- error: event.error?.message ?? "codex turn failed",
1120
- message: "codex turn failed"
1121
- });
1122
- return;
1123
- }
1124
- if (event.type === "error") {
1125
- ctx.emitError({
1126
- error: event.message ?? "codex error",
1127
- message: "codex stream error"
1128
- });
1129
- return;
1130
- }
1131
- if (!event.item) return;
1132
- const item = event.item;
1133
- const id = item.id ?? randomUUID();
1134
- const observeStep = () => {
1135
- ctx.stepTracker.observeEvent({ event, itemId: id });
1136
- };
1137
- if (item.type === "agent_message" && typeof item.text === "string") {
1138
- if (!ctx.textByItem.has(id)) {
1139
- ctx.send({ type: "text-start", id });
1140
- ctx.textByItem.set(id, "");
1141
- }
1142
- const last = ctx.textByItem.get(id) ?? "";
1143
- const next = item.text;
1144
- if (next.length > last.length) {
1145
- ctx.send({ type: "text-delta", id, delta: next.slice(last.length) });
1146
- ctx.textByItem.set(id, next);
1147
- }
1148
- if (event.type === "item.completed") ctx.send({ type: "text-end", id });
1149
- observeStep();
1150
- return;
1151
- }
1152
- if (item.type === "reasoning" && typeof item.text === "string") {
1153
- if (!ctx.reasoningByItem.has(id)) {
1154
- ctx.send({ type: "reasoning-start", id });
1155
- ctx.reasoningByItem.set(id, "");
1156
- }
1157
- const last = ctx.reasoningByItem.get(id) ?? "";
1158
- const next = item.text;
1159
- if (next.length > last.length) {
1160
- ctx.send({ type: "reasoning-delta", id, delta: next.slice(last.length) });
1161
- ctx.reasoningByItem.set(id, next);
1162
- }
1163
- if (event.type === "item.completed")
1164
- ctx.send({ type: "reasoning-end", id });
1165
- observeStep();
1166
- return;
1167
- }
1168
- if (item.type === "command_execution") {
1169
- const nativeName = "shell";
1170
- if (event.type === "item.started") {
1171
- ctx.send({
1172
- type: "tool-call",
1173
- toolCallId: id,
1174
- toolName: toCommonName(nativeName),
1175
- nativeName,
1176
- input: JSON.stringify({ command: item.command ?? "" }),
1177
- providerExecuted: true
1178
- });
1179
- } else if (event.type === "item.completed") {
1180
- ctx.send({
1181
- type: "tool-result",
1182
- toolCallId: id,
1183
- toolName: toCommonName(nativeName),
1184
- result: {
1185
- exitCode: item.exit_code ?? null,
1186
- output: item.aggregated_output ?? "",
1187
- status: item.status ?? "completed"
1188
- }
1189
- });
1190
- }
1191
- observeStep();
1192
- return;
1193
- }
1194
- if (item.type === "mcp_tool_call") {
1195
- if (event.type === "item.started") {
1196
- ctx.send({
1197
- type: "tool-call",
1198
- toolCallId: id,
1199
- toolName: item.tool ?? "unknown",
1200
- nativeName: item.tool ?? "unknown",
1201
- input: JSON.stringify(item.arguments ?? {}),
1202
- providerExecuted: true
1203
- });
1204
- } else if (event.type === "item.completed") {
1205
- ctx.send({
1206
- type: "tool-result",
1207
- toolCallId: id,
1208
- toolName: item.tool ?? "unknown",
1209
- result: extractMcpToolCallResult(item)
1210
- });
1211
- }
1212
- observeStep();
1213
- return;
1214
- }
1215
- if (item.type === "web_search") {
1216
- const nativeName = "web_search";
1217
- if (event.type === "item.started") {
1218
- ctx.send({
1219
- type: "tool-call",
1220
- toolCallId: id,
1221
- toolName: toCommonName(nativeName),
1222
- nativeName,
1223
- input: JSON.stringify({ query: item.query ?? "" }),
1224
- providerExecuted: true
1225
- });
1226
- } else if (event.type === "item.completed") {
1227
- ctx.send({
1228
- type: "tool-result",
1229
- toolCallId: id,
1230
- toolName: toCommonName(nativeName),
1231
- result: item.result ?? null
1232
- });
1233
- }
1234
- observeStep();
1235
- return;
1236
- }
1237
- if (item.type === "file_change" && event.type === "item.completed") {
1238
- for (const change of item.changes ?? []) {
1239
- ctx.send({
1240
- type: "file-change",
1241
- event: change.kind === "add" ? "create" : change.kind === "delete" ? "delete" : "modify",
1242
- path: change.path
1243
- });
1244
- }
1245
- observeStep();
1246
- return;
1247
- }
1248
- if (item.type === "error" && event.type === "item.completed") {
1249
- const message = typeof item.message === "string" && item.message.trim() ? item.message : "codex reported a non-fatal error item";
1250
- ctx.emitWarning({ message });
1251
- return;
1252
- }
1253
- }
1254
- function mapUsage(usage) {
1255
- const input = usage.input_tokens ?? 0;
1256
- const cacheRead = usage.cached_input_tokens ?? 0;
1257
- return {
1258
- inputTokens: {
1259
- total: input,
1260
- noCache: Math.max(0, input - cacheRead),
1261
- cacheRead,
1262
- cacheWrite: 0
1263
- },
1264
- outputTokens: {
1265
- total: usage.output_tokens ?? 0,
1266
- text: usage.output_tokens ?? 0
1267
- }
1268
- };
1269
- }
1270
1279
  async function startToolRelay({
1271
1280
  tools,
1272
1281
  emit,