agentbox-sdk 0.1.303 → 0.1.304

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Agent
3
- } from "../chunk-GBM7LKZF.js";
4
- import "../chunk-NWAXQ7UD.js";
3
+ } from "../chunk-T7C77LCW.js";
4
+ import "../chunk-EK6GC6YA.js";
5
5
  import {
6
6
  AGENT_RESERVED_PORTS,
7
7
  collectAllAgentReservedPorts
@@ -426,7 +426,9 @@ var ClaudeCodeLogAssembler = class {
426
426
  }
427
427
  const final = extractClaudeAssistantContent(message);
428
428
  this.textByMessageId.set(id, final.text);
429
- this.thinkingByMessageId.set(id, final.thinking);
429
+ if (final.thinking) {
430
+ this.thinkingByMessageId.set(id, final.thinking);
431
+ }
430
432
  const snapshot = this.upsertMessage(id, final.extraBlocks);
431
433
  this.currentMessageId = null;
432
434
  return [snapshot];
@@ -2,7 +2,7 @@ import {
2
2
  createNormalizedEvent,
3
3
  normalizeRawAgentEvent,
4
4
  toAISDKStream
5
- } from "./chunk-NWAXQ7UD.js";
5
+ } from "./chunk-EK6GC6YA.js";
6
6
  import {
7
7
  AgentBoxError,
8
8
  AsyncQueue,
@@ -2504,6 +2504,31 @@ async function* streamSse(url, init) {
2504
2504
  })();
2505
2505
  yield* queue;
2506
2506
  }
2507
+ async function* streamSseResilient(url, init) {
2508
+ let lastEventId;
2509
+ let attempt = 0;
2510
+ const signal = init?.signal;
2511
+ while (true) {
2512
+ try {
2513
+ const headers = {
2514
+ ...init?.headers ?? {},
2515
+ ...lastEventId ? { "Last-Event-ID": lastEventId } : {}
2516
+ };
2517
+ for await (const ev of streamSse(url, { ...init, headers })) {
2518
+ attempt = 0;
2519
+ if (ev.id) lastEventId = ev.id;
2520
+ yield ev;
2521
+ }
2522
+ return;
2523
+ } catch (err) {
2524
+ if (signal?.aborted) throw err;
2525
+ const delay = Math.min(500 * Math.pow(2, attempt), 5e3);
2526
+ attempt++;
2527
+ await new Promise((resolve) => setTimeout(resolve, delay));
2528
+ if (signal?.aborted) throw err;
2529
+ }
2530
+ }
2531
+ }
2507
2532
  async function connectJsonRpcWebSocket(url, options) {
2508
2533
  const notifications = new AsyncQueue();
2509
2534
  const socket = new WebSocket(url, { headers: options?.headers });
@@ -3540,7 +3565,7 @@ var CodexAgentAdapter = class {
3540
3565
  Date.now() - executeStartedAt,
3541
3566
  text?.length ?? 0
3542
3567
  );
3543
- sink.complete({ text, costData: extractCodexCostData(rawPayloads) });
3568
+ sink.complete({ costData: extractCodexCostData(rawPayloads) });
3544
3569
  }
3545
3570
  }
3546
3571
  } finally {
@@ -3638,73 +3663,6 @@ function toRawEvent3(runId, payload, type) {
3638
3663
  payload
3639
3664
  };
3640
3665
  }
3641
- function extractText(value) {
3642
- if (!value) {
3643
- return "";
3644
- }
3645
- if (typeof value === "string") {
3646
- return value;
3647
- }
3648
- if (Array.isArray(value)) {
3649
- return value.map(extractText).filter(Boolean).join("");
3650
- }
3651
- if (typeof value === "object") {
3652
- const record = value;
3653
- if (record.type === "text" && typeof record.text === "string") {
3654
- return record.text;
3655
- }
3656
- if (record.type === "reasoning") {
3657
- return "";
3658
- }
3659
- if (record.message) {
3660
- return extractText(record.message);
3661
- }
3662
- if (record.content) {
3663
- return extractText(record.content);
3664
- }
3665
- if (record.parts) {
3666
- return extractText(record.parts);
3667
- }
3668
- if (record.text) {
3669
- return extractText(record.text);
3670
- }
3671
- }
3672
- return "";
3673
- }
3674
- function extractAssistantMessageId(response) {
3675
- if (!response || typeof response !== "object") {
3676
- return void 0;
3677
- }
3678
- const record = response;
3679
- const info = record.info && typeof record.info === "object" ? record.info : record.message && typeof record.message === "object" ? record.message : void 0;
3680
- const id = info?.id ?? record.id;
3681
- return typeof id === "string" ? id : void 0;
3682
- }
3683
- function extractReasoning(value) {
3684
- if (!value) {
3685
- return "";
3686
- }
3687
- if (Array.isArray(value)) {
3688
- return value.map(extractReasoning).filter(Boolean).join("");
3689
- }
3690
- if (typeof value === "object") {
3691
- const record = value;
3692
- if (record.type === "reasoning") {
3693
- if (typeof record.text === "string") {
3694
- return record.text;
3695
- }
3696
- if (typeof record.reasoning === "string") {
3697
- return record.reasoning;
3698
- }
3699
- }
3700
- return [
3701
- extractReasoning(record.message),
3702
- extractReasoning(record.content),
3703
- extractReasoning(record.parts)
3704
- ].filter(Boolean).join("");
3705
- }
3706
- return "";
3707
- }
3708
3666
  function toOpenCodeModel(model) {
3709
3667
  if (!model) {
3710
3668
  return void 0;
@@ -3771,6 +3729,14 @@ function buildOpenCodeConfig(options, interactiveApproval) {
3771
3729
  const commandsConfig = buildOpenCodeCommandsConfig(options.commands);
3772
3730
  const baseAgent = {
3773
3731
  mode: "primary",
3732
+ // Suppress opencode's default provider system prompt (e.g.
3733
+ // PROMPT_ANTHROPIC's "You are OpenCode...") so request.run.systemPrompt
3734
+ // is the dominant identity statement the model sees. opencode's
3735
+ // session/llm.ts uses agent.prompt instead of SystemPrompt.provider(model)
3736
+ // when this field is truthy — codex already takes that branch via a
3737
+ // separate options.instructions channel, so this brings anthropic et al.
3738
+ // in line. Constant value, so setupId stays stable.
3739
+ prompt: "You are an AI coding assistant. Follow the user's instructions.",
3774
3740
  permission: buildOpenCodePermissionConfig(interactiveApproval),
3775
3741
  tools: {
3776
3742
  write: true,
@@ -4029,25 +3995,14 @@ var OpenCodeAgentAdapter = class {
4029
3995
  "validateProviderUserInput",
4030
3996
  () => validateProviderUserInput(request.provider, request.run.input)
4031
3997
  );
4032
- let pendingMessages = 0;
4033
- let finalText = "";
4034
3998
  let streamedTextFromSse = "";
4035
- const settledMessageIds = /* @__PURE__ */ new Set();
3999
+ const assistantTextByMessageId = /* @__PURE__ */ new Map();
4000
+ const announcedAssistantCompletions = /* @__PURE__ */ new Set();
4036
4001
  let dispatchError;
4037
4002
  let firstSseEventLogged = false;
4038
- let resolveAllDone;
4039
- const allDone = new Promise((resolve) => {
4040
- resolveAllDone = resolve;
4041
- });
4042
- const checkDone = () => {
4043
- if (pendingMessages === 0) {
4044
- resolveAllDone();
4045
- }
4046
- };
4047
4003
  let sendToSession;
4048
4004
  const queuedParts = [];
4049
4005
  sink.onMessage(async (content) => {
4050
- pendingMessages++;
4051
4006
  try {
4052
4007
  const parts = await validateProviderUserInput(
4053
4008
  request.provider,
@@ -4060,11 +4015,10 @@ var OpenCodeAgentAdapter = class {
4060
4015
  queuedParts.push(mapped);
4061
4016
  }
4062
4017
  } catch (error) {
4063
- pendingMessages--;
4064
4018
  if (!dispatchError) {
4065
4019
  dispatchError = error;
4066
4020
  }
4067
- checkDone();
4021
+ resolveSessionTerminal();
4068
4022
  throw error;
4069
4023
  }
4070
4024
  });
@@ -4083,10 +4037,15 @@ var OpenCodeAgentAdapter = class {
4083
4037
  const rawPayloads = [];
4084
4038
  const sseAbort = new AbortController();
4085
4039
  let sseTask;
4086
- const dispatchAbort = new AbortController();
4087
4040
  let capturedSessionId;
4088
4041
  let sessionErrorFromSse;
4089
4042
  let sessionAbortedFromSse = false;
4043
+ let sessionIdleFromSse = false;
4044
+ let resolveSessionTerminal;
4045
+ const sessionTerminal = new Promise((resolve) => {
4046
+ resolveSessionTerminal = resolve;
4047
+ });
4048
+ let lastSseActivityAt = Date.now();
4090
4049
  let userAbortRequested = false;
4091
4050
  sink.setAbort(async () => {
4092
4051
  userAbortRequested = true;
@@ -4114,7 +4073,7 @@ var OpenCodeAgentAdapter = class {
4114
4073
  } catch {
4115
4074
  }
4116
4075
  }
4117
- dispatchAbort.abort();
4076
+ resolveSessionTerminal();
4118
4077
  });
4119
4078
  try {
4120
4079
  const interactiveApproval = isInteractiveApproval(request.options);
@@ -4155,10 +4114,14 @@ var OpenCodeAgentAdapter = class {
4155
4114
  const foreignMessageIds = /* @__PURE__ */ new Set();
4156
4115
  sseTask = (async () => {
4157
4116
  try {
4158
- for await (const event of streamSse(`${runtime.baseUrl}/event`, {
4159
- headers: runtime.previewHeaders,
4160
- signal: sseAbort.signal
4161
- })) {
4117
+ for await (const event of streamSseResilient(
4118
+ `${runtime.baseUrl}/event`,
4119
+ {
4120
+ headers: runtime.previewHeaders,
4121
+ signal: sseAbort.signal
4122
+ }
4123
+ )) {
4124
+ lastSseActivityAt = Date.now();
4162
4125
  if (!firstSseEventLogged) {
4163
4126
  firstSseEventLogged = true;
4164
4127
  debugOpencode(
@@ -4201,6 +4164,22 @@ var OpenCodeAgentAdapter = class {
4201
4164
  { messageId: info.id }
4202
4165
  )
4203
4166
  );
4167
+ } else if (info.role === "assistant" && !announcedAssistantCompletions.has(info.id)) {
4168
+ const time2 = info.time;
4169
+ if (typeof time2?.completed === "number") {
4170
+ announcedAssistantCompletions.add(info.id);
4171
+ sink.emitEvent(
4172
+ createNormalizedEvent(
4173
+ "message.completed",
4174
+ {
4175
+ provider: request.provider,
4176
+ runId: request.runId,
4177
+ raw
4178
+ },
4179
+ { text: assistantTextByMessageId.get(info.id) ?? "" }
4180
+ )
4181
+ );
4182
+ }
4204
4183
  }
4205
4184
  }
4206
4185
  }
@@ -4233,7 +4212,7 @@ var OpenCodeAgentAdapter = class {
4233
4212
  continue;
4234
4213
  }
4235
4214
  const payloadRecord = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null;
4236
- if ((payloadRecord?.type === "session.idle" || payloadRecord?.type === "session.error") && !dispatchAbort.signal.aborted) {
4215
+ if (payloadRecord?.type === "session.idle" || payloadRecord?.type === "session.error") {
4237
4216
  const properties = payloadRecord.properties;
4238
4217
  const eventSessionId = typeof properties?.sessionID === "string" ? properties.sessionID : void 0;
4239
4218
  if (!eventSessionId || eventSessionId === sessionId) {
@@ -4245,13 +4224,28 @@ var OpenCodeAgentAdapter = class {
4245
4224
  const errMsg = typeof errData?.data?.message === "string" ? errData.data.message : typeof errData?.message === "string" ? errData.message : "OpenCode session error";
4246
4225
  sessionErrorFromSse = new Error(errMsg);
4247
4226
  }
4227
+ } else {
4228
+ sessionIdleFromSse = true;
4248
4229
  }
4249
4230
  debugOpencode(
4250
- "\u2605 %s for session=%s \u2014 aborting in-flight dispatch",
4231
+ "\u2605 %s for session=%s",
4251
4232
  payloadRecord.type,
4252
4233
  sessionId
4253
4234
  );
4254
- dispatchAbort.abort();
4235
+ resolveSessionTerminal();
4236
+ }
4237
+ }
4238
+ if (payloadRecord?.type === "session.status") {
4239
+ const properties = payloadRecord.properties;
4240
+ const status = properties?.status;
4241
+ const eventSessionId = typeof properties?.sessionID === "string" ? properties.sessionID : void 0;
4242
+ if ((!eventSessionId || eventSessionId === sessionId) && status?.type === "idle") {
4243
+ sessionIdleFromSse = true;
4244
+ debugOpencode(
4245
+ "\u2605 session.status{idle} for session=%s",
4246
+ sessionId
4247
+ );
4248
+ resolveSessionTerminal();
4255
4249
  }
4256
4250
  }
4257
4251
  if (payloadRecord?.type === "message.part.delta") {
@@ -4262,12 +4256,15 @@ var OpenCodeAgentAdapter = class {
4262
4256
  if (isForeignSession) {
4263
4257
  continue;
4264
4258
  }
4265
- if (eventMessageId !== void 0 && settledMessageIds.has(eventMessageId)) {
4266
- continue;
4267
- }
4268
4259
  const delta = typeof properties?.delta === "string" ? properties.delta : "";
4269
4260
  if (delta && properties?.field === "text") {
4270
4261
  streamedTextFromSse += delta;
4262
+ if (eventMessageId) {
4263
+ assistantTextByMessageId.set(
4264
+ eventMessageId,
4265
+ (assistantTextByMessageId.get(eventMessageId) ?? "") + delta
4266
+ );
4267
+ }
4271
4268
  sink.emitEvent(
4272
4269
  createNormalizedEvent(
4273
4270
  "text.delta",
@@ -4320,131 +4317,131 @@ var OpenCodeAgentAdapter = class {
4320
4317
  })
4321
4318
  );
4322
4319
  const agentSlug = openCodeAgentSlug(request.run.reasoning);
4323
- const dispatchMessage = async (parts) => {
4324
- const sseTextLengthBeforeDispatch = streamedTextFromSse.length;
4325
- try {
4326
- const response = await fetchJson(
4327
- `${runtime.baseUrl}/session/${sessionId}/message`,
4328
- {
4329
- method: "POST",
4330
- signal: dispatchAbort.signal,
4331
- headers: {
4332
- "content-type": "application/json",
4333
- ...runtime.previewHeaders
4334
- },
4335
- body: JSON.stringify({
4336
- ...request.run.model ? { model: toOpenCodeModel(request.run.model) } : {},
4337
- // Per-message system prompt — keeps systemPrompt out of
4338
- // the on-disk agent config so changing it doesn't
4339
- // invalidate setupId. Sent on every dispatch (the field
4340
- // is per-message, not session-sticky).
4341
- ...request.run.systemPrompt ? { system: request.run.systemPrompt } : {},
4342
- agent: agentSlug,
4343
- parts
4344
- })
4320
+ const dispatchPrompt = async (parts) => {
4321
+ const body = JSON.stringify({
4322
+ ...request.run.model ? { model: toOpenCodeModel(request.run.model) } : {},
4323
+ // Per-message system prompt — keeps systemPrompt out of
4324
+ // the on-disk agent config so changing it doesn't
4325
+ // invalidate setupId. Sent on every dispatch (the field
4326
+ // is per-message, not session-sticky).
4327
+ ...request.run.systemPrompt ? { system: request.run.systemPrompt } : {},
4328
+ agent: agentSlug,
4329
+ parts
4330
+ });
4331
+ const url = `${runtime.baseUrl}/session/${sessionId}/prompt_async`;
4332
+ const attempt = async () => {
4333
+ return fetch(url, {
4334
+ method: "POST",
4335
+ headers: {
4336
+ "content-type": "application/json",
4337
+ ...runtime.previewHeaders
4338
+ },
4339
+ body
4340
+ });
4341
+ };
4342
+ let lastError;
4343
+ for (let i = 0; i < 2; i++) {
4344
+ try {
4345
+ const response = await attempt();
4346
+ if (response.ok || response.status === 204) {
4347
+ return;
4345
4348
  }
4346
- );
4347
- const rawResponse = toRawEvent3(
4348
- request.runId,
4349
- response,
4350
- "message.response"
4351
- );
4352
- if (response && typeof response === "object" && !Array.isArray(response)) {
4353
- rawPayloads.push(response);
4354
- }
4355
- sink.emitRaw(rawResponse);
4356
- for (const event of normalizeRawAgentEvent(rawResponse)) {
4357
- sink.emitEvent(event);
4358
- }
4359
- const reasoning = extractReasoning(response);
4360
- if (reasoning) {
4361
- sink.emitEvent(
4362
- createNormalizedEvent(
4363
- "reasoning.delta",
4364
- {
4365
- provider: request.provider,
4366
- runId: request.runId,
4367
- raw: rawResponse
4368
- },
4369
- { delta: reasoning }
4370
- )
4349
+ lastError = new Error(
4350
+ `POST ${url} returned ${response.status}`
4371
4351
  );
4352
+ } catch (error) {
4353
+ lastError = error;
4372
4354
  }
4373
- const text = extractText(response);
4374
- if (text) {
4375
- finalText = text;
4376
- const sseTextForThisDispatch = streamedTextFromSse.slice(
4377
- sseTextLengthBeforeDispatch
4355
+ if (i === 0) {
4356
+ debugOpencode(
4357
+ "prompt_async dispatch attempt %d failed (%s); retrying once",
4358
+ i + 1,
4359
+ lastError?.message ?? String(lastError)
4378
4360
  );
4379
- let missing;
4380
- if (text.startsWith(sseTextForThisDispatch)) {
4381
- missing = text.slice(sseTextForThisDispatch.length);
4382
- } else if (sseTextForThisDispatch.length === 0) {
4383
- missing = text;
4384
- } else {
4385
- missing = "";
4386
- }
4387
- if (missing.length > 0) {
4388
- streamedTextFromSse += missing;
4389
- sink.emitEvent(
4390
- createNormalizedEvent(
4391
- "text.delta",
4392
- {
4393
- provider: request.provider,
4394
- runId: request.runId
4395
- },
4396
- { delta: missing }
4397
- )
4398
- );
4399
- }
4400
- const assistantMessageId = extractAssistantMessageId(response);
4401
- if (assistantMessageId) {
4402
- settledMessageIds.add(assistantMessageId);
4403
- }
4361
+ await sleep(500);
4404
4362
  }
4405
- } catch (error) {
4406
- if (!dispatchError) {
4407
- dispatchError = error;
4408
- }
4409
- } finally {
4410
- pendingMessages--;
4411
- checkDone();
4412
4363
  }
4364
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
4413
4365
  };
4414
4366
  sendToSession = (parts) => {
4415
- void dispatchMessage(parts);
4367
+ void (async () => {
4368
+ try {
4369
+ await dispatchPrompt(parts);
4370
+ } catch (error) {
4371
+ if (!dispatchError) {
4372
+ dispatchError = error;
4373
+ }
4374
+ resolveSessionTerminal();
4375
+ }
4376
+ })();
4416
4377
  };
4417
4378
  for (const queued of queuedParts.splice(0)) {
4418
4379
  sendToSession(queued);
4419
4380
  }
4420
- pendingMessages++;
4421
- void dispatchMessage(mapToOpenCodeParts(inputParts));
4422
- await allDone;
4381
+ try {
4382
+ await dispatchPrompt(mapToOpenCodeParts(inputParts));
4383
+ } catch (error) {
4384
+ if (!dispatchError) {
4385
+ dispatchError = error;
4386
+ }
4387
+ resolveSessionTerminal();
4388
+ }
4389
+ const SSE_SILENCE_THRESHOLD_MS = 18e4;
4390
+ const SSE_POLL_INTERVAL_MS = 5e3;
4391
+ lastSseActivityAt = Date.now();
4392
+ let sseSilent = false;
4393
+ while (!sessionIdleFromSse && !sessionErrorFromSse && !sessionAbortedFromSse && !userAbortRequested && !dispatchError) {
4394
+ const silence = Date.now() - lastSseActivityAt;
4395
+ if (silence > SSE_SILENCE_THRESHOLD_MS) {
4396
+ sseSilent = true;
4397
+ debugOpencode("SSE went silent (%dms) \u2014 giving up", silence);
4398
+ break;
4399
+ }
4400
+ await Promise.race([
4401
+ sessionTerminal,
4402
+ new Promise(
4403
+ (resolve) => setTimeout(resolve, SSE_POLL_INTERVAL_MS)
4404
+ )
4405
+ ]);
4406
+ }
4407
+ sseAbort.abort();
4408
+ await sseTask;
4423
4409
  if (userAbortRequested || sessionAbortedFromSse) {
4424
4410
  debugOpencode(
4425
4411
  "\u2605 run.cancelled (%dms since execute start)",
4426
4412
  Date.now() - executeStartedAt
4427
4413
  );
4428
- sseAbort.abort();
4429
- await sseTask;
4430
4414
  sink.cancel({
4431
4415
  text: streamedTextFromSse || void 0,
4432
4416
  costData: extractOpenCodeCostData(rawPayloads)
4433
4417
  });
4434
4418
  } else if (sessionErrorFromSse) {
4435
- sseAbort.abort();
4436
- await sseTask;
4437
4419
  sink.fail(sessionErrorFromSse);
4438
- } else if (dispatchError && !(dispatchAbort.signal.aborted && dispatchError?.name === "AbortError")) {
4439
- sseAbort.abort();
4440
- await sseTask;
4420
+ } else if (dispatchError) {
4441
4421
  sink.fail(dispatchError);
4442
- } else {
4422
+ } else if (sessionIdleFromSse) {
4443
4423
  debugOpencode(
4444
4424
  "\u2605 run.completed (%dms since execute start) chars=%d",
4445
4425
  Date.now() - executeStartedAt,
4446
- finalText.length
4426
+ streamedTextFromSse.length
4447
4427
  );
4428
+ let lastAssistantText = "";
4429
+ for (const [messageId, text] of assistantTextByMessageId) {
4430
+ lastAssistantText = text;
4431
+ if (!announcedAssistantCompletions.has(messageId)) {
4432
+ announcedAssistantCompletions.add(messageId);
4433
+ sink.emitEvent(
4434
+ createNormalizedEvent(
4435
+ "message.completed",
4436
+ {
4437
+ provider: request.provider,
4438
+ runId: request.runId
4439
+ },
4440
+ { text }
4441
+ )
4442
+ );
4443
+ }
4444
+ }
4448
4445
  sink.emitEvent(
4449
4446
  createNormalizedEvent(
4450
4447
  "run.completed",
@@ -4452,15 +4449,23 @@ var OpenCodeAgentAdapter = class {
4452
4449
  provider: request.provider,
4453
4450
  runId: request.runId
4454
4451
  },
4455
- { text: finalText }
4452
+ { text: lastAssistantText }
4456
4453
  )
4457
4454
  );
4458
- sseAbort.abort();
4459
- await sseTask;
4460
4455
  sink.complete({
4461
- text: finalText,
4456
+ text: lastAssistantText,
4462
4457
  costData: extractOpenCodeCostData(rawPayloads)
4463
4458
  });
4459
+ } else if (sseSilent) {
4460
+ sink.fail(
4461
+ new Error(
4462
+ "opencode SSE went silent before the session reached idle"
4463
+ )
4464
+ );
4465
+ } else {
4466
+ sink.fail(
4467
+ new Error("opencode run ended without a terminal signal")
4468
+ );
4464
4469
  }
4465
4470
  } finally {
4466
4471
  sseAbort.abort();
@@ -4506,10 +4511,10 @@ var OpenCodeAgentAdapter = class {
4506
4511
  }
4507
4512
  }
4508
4513
  /**
4509
- * Stateless message injection. POST a fresh user message to
4510
- * `/session/:id/message` with `agent` defaulting to the build agent
4511
- * opencode appends it to the running session and the originating
4512
- * instance picks up the new turn through its existing SSE stream.
4514
+ * Stateless message injection. Fire-and-forget POST to
4515
+ * `/session/:id/prompt_async` (returns 204) opencode appends the
4516
+ * message to the running session and the originating instance picks
4517
+ * up the new turn through its existing SSE stream.
4513
4518
  */
4514
4519
  async attachSendMessage(request, content) {
4515
4520
  if (!request.sessionId) {
@@ -4523,20 +4528,21 @@ var OpenCodeAgentAdapter = class {
4523
4528
  content
4524
4529
  );
4525
4530
  const parts = mapToOpenCodeParts(inputParts);
4526
- await fetchJson(
4527
- `${baseUrl}/session/${request.sessionId}/message`,
4528
- {
4529
- method: "POST",
4530
- headers: {
4531
- "content-type": "application/json",
4532
- ...request.sandbox.previewHeaders
4533
- },
4534
- body: JSON.stringify({
4535
- agent: openCodeAgentSlug(void 0),
4536
- parts
4537
- })
4538
- }
4539
- );
4531
+ const url = `${baseUrl}/session/${request.sessionId}/prompt_async`;
4532
+ const response = await fetch(url, {
4533
+ method: "POST",
4534
+ headers: {
4535
+ "content-type": "application/json",
4536
+ ...request.sandbox.previewHeaders
4537
+ },
4538
+ body: JSON.stringify({
4539
+ agent: openCodeAgentSlug(void 0),
4540
+ parts
4541
+ })
4542
+ });
4543
+ if (!response.ok && response.status !== 204) {
4544
+ throw new Error(`POST ${url} returned ${response.status}`);
4545
+ }
4540
4546
  }
4541
4547
  };
4542
4548
 
@@ -4619,6 +4625,7 @@ var AgentRunController = class {
4619
4625
  pendingPermissions = /* @__PURE__ */ new Map();
4620
4626
  messageHandler;
4621
4627
  text = "";
4628
+ observedMessageCompleted = false;
4622
4629
  costData = null;
4623
4630
  settled = false;
4624
4631
  finished;
@@ -4669,6 +4676,9 @@ var AgentRunController = class {
4669
4676
  this.text += event.delta;
4670
4677
  } else if ((event.type === "message.completed" || event.type === "run.completed") && event.text) {
4671
4678
  this.text = event.text;
4679
+ if (event.type === "message.completed") {
4680
+ this.observedMessageCompleted = true;
4681
+ }
4672
4682
  }
4673
4683
  this.eventQueue.push(event);
4674
4684
  }
@@ -4766,7 +4776,7 @@ var AgentRunController = class {
4766
4776
  "Agent run completed before pending permission requests resolved."
4767
4777
  )
4768
4778
  );
4769
- if (result?.text) {
4779
+ if (result?.text && !this.observedMessageCompleted) {
4770
4780
  this.text = result.text;
4771
4781
  }
4772
4782
  if (result && "costData" in result) {
@@ -4811,7 +4821,7 @@ var AgentRunController = class {
4811
4821
  "Agent run was cancelled before pending permission requests resolved."
4812
4822
  )
4813
4823
  );
4814
- if (result?.text) {
4824
+ if (result?.text && !this.observedMessageCompleted) {
4815
4825
  this.text = result.text;
4816
4826
  }
4817
4827
  if (result && "costData" in result) {
@@ -4,7 +4,7 @@ import {
4
4
  normalizeRawAgentEvent,
5
5
  toAISDKEvent,
6
6
  toAISDKStream
7
- } from "../chunk-NWAXQ7UD.js";
7
+ } from "../chunk-EK6GC6YA.js";
8
8
  import "../chunk-GOFJNFAD.js";
9
9
  export {
10
10
  ProviderLogAssembler,
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  Agent
3
- } from "./chunk-GBM7LKZF.js";
3
+ } from "./chunk-T7C77LCW.js";
4
4
  import {
5
5
  ProviderLogAssembler,
6
6
  createNormalizedEvent,
7
7
  normalizeRawAgentEvent,
8
8
  toAISDKEvent,
9
9
  toAISDKStream
10
- } from "./chunk-NWAXQ7UD.js";
10
+ } from "./chunk-EK6GC6YA.js";
11
11
  import {
12
12
  Sandbox,
13
13
  SandboxAdapter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbox-sdk",
3
- "version": "0.1.303",
3
+ "version": "0.1.304",
4
4
  "description": "Swappable coding agents and sandbox providers for Bun and TypeScript.",
5
5
  "license": "MIT",
6
6
  "repository": {