agentbox-sdk 0.1.602 → 0.1.603

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.
@@ -15,7 +15,7 @@ import {
15
15
  parseHarnessCommandInvocation,
16
16
  resolveHarnessCommand,
17
17
  skillDirective
18
- } from "../chunk-UE4LQEL5.js";
18
+ } from "../chunk-JO6LTAAD.js";
19
19
  import "../chunk-AE2FQ6YU.js";
20
20
  import {
21
21
  AGENT_RESERVED_PORTS,
@@ -4991,6 +4991,18 @@ function codexConfigDir(options) {
4991
4991
  var REMOTE_CODEX_APP_SERVER_PORT = 43181;
4992
4992
  var REMOTE_CODEX_APP_SERVER_ID = "shared-app-server";
4993
4993
  var CODEX_APP_SERVER_TOKEN_FILENAME = "codex-app-server-token";
4994
+ var MAX_CODEX_RECONNECTS = 3;
4995
+ var CODEX_RECONNECT_TIMEOUT_MS = 3e4;
4996
+ function missedCodexNotifications(thread, threadId, turnId, seenItemIds) {
4997
+ const active = thread.status?.type === "active";
4998
+ const turn = turnId ? thread.turns?.find((candidate) => candidate.id === turnId) : void 0;
4999
+ if (!turn) return active ? [] : void 0;
5000
+ const ended = turn.status === "completed" || turn.status === "failed";
5001
+ if (!ended && (turn.status !== "inProgress" || !active)) return void 0;
5002
+ const missed = (turn.items ?? []).filter((item) => typeof item.id === "string" && !seenItemIds.has(item.id) && item.status !== "inProgress").map((item) => ({ method: "item/completed", params: { threadId, turnId, item } }));
5003
+ if (ended) missed.push({ method: "turn/completed", params: { threadId, turn: { ...turn, items: [] } } });
5004
+ return missed;
5005
+ }
4994
5006
  function defaultRemoteCodexTokenPath() {
4995
5007
  return path10.posix.join(
4996
5008
  agentboxRoot(AgentProvider.Codex, true),
@@ -5821,25 +5833,28 @@ async function createRuntime(request, inputParts) {
5821
5833
  () => sandbox.getPreviewLink(REMOTE_CODEX_APP_SERVER_PORT)
5822
5834
  );
5823
5835
  const token = await getCodexAppServerToken(sandbox);
5824
- const transport = await connectRemoteCodexAppServer(
5825
- toRemoteCodexWebSocketUrl(previewUrl),
5826
- withCodexAppServerAuthHeaders(sandbox.previewHeaders, token)
5827
- );
5828
- debugCodex("\u2605 codex transport established");
5829
- return {
5830
- source: transport.source,
5831
- writeLine: transport.send,
5832
- cleanup: async () => {
5833
- await transport?.close().catch(() => void 0);
5834
- },
5835
- raw: {
5836
- transport: transport.raw,
5837
- previewUrl,
5838
- port: REMOTE_CODEX_APP_SERVER_PORT,
5839
- codexDir
5840
- },
5841
- inputItems
5836
+ const connect = async () => {
5837
+ const transport = await connectRemoteCodexAppServer(
5838
+ toRemoteCodexWebSocketUrl(previewUrl),
5839
+ withCodexAppServerAuthHeaders(sandbox.previewHeaders, token)
5840
+ );
5841
+ return {
5842
+ source: transport.source,
5843
+ writeLine: transport.send,
5844
+ cleanup: async () => {
5845
+ await transport.close().catch(() => void 0);
5846
+ },
5847
+ raw: {
5848
+ transport: transport.raw,
5849
+ previewUrl,
5850
+ port: REMOTE_CODEX_APP_SERVER_PORT,
5851
+ codexDir
5852
+ }
5853
+ };
5842
5854
  };
5855
+ const connection = await connect();
5856
+ debugCodex("\u2605 codex transport established");
5857
+ return { ...connection, reconnect: connect, inputItems };
5843
5858
  }
5844
5859
  const binary = options.provider?.binary ?? "codex";
5845
5860
  if (options.sandbox) {
@@ -6006,7 +6021,7 @@ var CodexAgentAdapter = class {
6006
6021
  runId: request.runId
6007
6022
  })
6008
6023
  );
6009
- const client = runtime.client ?? new JsonRpcLineClient(
6024
+ let client = runtime.client ?? new JsonRpcLineClient(
6010
6025
  runtime.source,
6011
6026
  runtime.writeLine
6012
6027
  );
@@ -6064,6 +6079,8 @@ var CodexAgentAdapter = class {
6064
6079
  const pendingFileChanges = /* @__PURE__ */ new Map();
6065
6080
  const fileItemKey = (params, itemId) => typeof params?.threadId === "string" && typeof params.turnId === "string" && typeof itemId === "string" ? `${params.threadId}:${params.turnId}:${itemId}` : void 0;
6066
6081
  let streamedText = "";
6082
+ const completedItemIds = /* @__PURE__ */ new Set();
6083
+ const replayedItemIds = /* @__PURE__ */ new Set();
6067
6084
  const timeoutMs = resolveBackgroundTaskTimeoutMs(request.options.backgroundTaskTimeoutMs);
6068
6085
  const isRootThread = (params) => !params?.threadId || params.threadId === rootThreadId;
6069
6086
  let goalStatus = request.run.goal ? "active" : void 0;
@@ -6100,29 +6117,82 @@ var CodexAgentAdapter = class {
6100
6117
  };
6101
6118
  void (async () => {
6102
6119
  let firstClientMessageLogged = false;
6103
- const iterator = client.messages()[Symbol.asyncIterator]();
6104
- for (let next = iterator.next(); ; next = iterator.next()) {
6105
- let step;
6120
+ let iterator = client.messages()[Symbol.asyncIterator]();
6121
+ let next;
6122
+ const replay = [];
6123
+ let reconnects = 0;
6124
+ const reconnect = async (cause) => {
6125
+ if (!runtime.reconnect || abortInvoked || !rootThreadId || reconnects >= MAX_CODEX_RECONNECTS) return false;
6126
+ reconnects++;
6127
+ debugCodex("\u2605 transport lost (%o); reconnecting (attempt %d)", cause, reconnects);
6128
+ let connection;
6106
6129
  try {
6107
- step = pendingWait ? await Promise.race([
6108
- next.then((result) => ({ result })),
6109
- pendingWait.expired.then((reason) => ({ reason }))
6110
- ]) : { result: await next };
6130
+ connection = await runtime.reconnect();
6131
+ const nextClient = new JsonRpcLineClient(connection.source, connection.writeLine);
6132
+ const resumed = await withTimeout((async () => {
6133
+ await initializeCodexClient(nextClient);
6134
+ return nextClient.request("thread/resume", { threadId: rootThreadId });
6135
+ })(), CODEX_RECONNECT_TIMEOUT_MS);
6136
+ const missed = resumed?.thread && missedCodexNotifications(resumed.thread, rootThreadId, turnId, completedItemIds);
6137
+ if (!missed || abortInvoked) throw new Error("Codex thread could not be rejoined.");
6138
+ const previous = runtime;
6139
+ runtime = { ...runtime, ...connection };
6140
+ await previous.cleanup().catch(() => void 0);
6141
+ client = nextClient;
6142
+ iterator = client.messages()[Symbol.asyncIterator]();
6143
+ sink.setRaw(runtime.raw);
6144
+ replay.push(...missed);
6145
+ debugCodex("\u2605 rejoined thread %s; replaying %d notification(s)", rootThreadId, missed.length);
6146
+ return true;
6111
6147
  } catch (error) {
6112
- if (settleOnFailure(error)) return;
6113
- throw error;
6148
+ debugCodex("\u2605 reconnect failed: %o", error);
6149
+ await connection?.cleanup().catch(() => void 0);
6150
+ return false;
6114
6151
  }
6115
- if ("reason" in step) {
6116
- if (!abortInvoked) {
6117
- debugCodex("\u2605 native goal wait over (%s)", step.reason);
6118
- settle();
6119
- return;
6152
+ };
6153
+ for (; ; ) {
6154
+ let step;
6155
+ const replayed = replay.shift();
6156
+ if (replayed) {
6157
+ step = { result: { done: false, value: replayed } };
6158
+ } else {
6159
+ const read = next ??= iterator.next();
6160
+ try {
6161
+ step = pendingWait ? await Promise.race([
6162
+ read.then((result) => ({ result })),
6163
+ pendingWait.expired.then((reason) => ({ reason }))
6164
+ ]) : { result: await read };
6165
+ } catch (error) {
6166
+ next = void 0;
6167
+ if (settleOnFailure(error)) return;
6168
+ if (await reconnect(error)) continue;
6169
+ throw error;
6120
6170
  }
6121
- endWait();
6122
- step = { result: await next };
6171
+ if ("reason" in step) {
6172
+ if (!abortInvoked) {
6173
+ debugCodex("\u2605 native goal wait over (%s)", step.reason);
6174
+ settle();
6175
+ return;
6176
+ }
6177
+ endWait();
6178
+ step = { result: await read };
6179
+ }
6180
+ next = void 0;
6181
+ }
6182
+ if (step.result.done) {
6183
+ if (pendingWait && lastTurn) break;
6184
+ if (await reconnect(new Error("Codex transport closed."))) continue;
6185
+ break;
6123
6186
  }
6124
- if (step.result.done) break;
6125
6187
  const message = step.result.value;
6188
+ if (message.method === "item/completed") {
6189
+ const id = message.params?.item?.id;
6190
+ if (typeof id === "string") {
6191
+ if (replayed) replayedItemIds.add(id);
6192
+ else if (replayedItemIds.has(id)) continue;
6193
+ completedItemIds.add(id);
6194
+ }
6195
+ }
6126
6196
  if (!firstClientMessageLogged) {
6127
6197
  firstClientMessageLogged = true;
6128
6198
  debugCodex(
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  parseHarnessCommandInvocation,
16
16
  resolveHarnessCommand,
17
17
  skillDirective
18
- } from "./chunk-UE4LQEL5.js";
18
+ } from "./chunk-JO6LTAAD.js";
19
19
  import {
20
20
  ProviderLogAssembler,
21
21
  createNormalizedEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbox-sdk",
3
- "version": "0.1.602",
3
+ "version": "0.1.603",
4
4
  "description": "Swappable coding agents and sandbox providers for Bun and TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {