@cydm/pie 2.7.5 → 2.7.6

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,9 +1,9 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createAskUserCapability
4
- } from "../../../chunks/chunk-BFHCZVNO.js";
5
- import "../../../chunks/chunk-MLRF72MK.js";
6
- import "../../../chunks/chunk-SUPAWIKP.js";
4
+ } from "../../../chunks/chunk-YWWLRZSG.js";
5
+ import "../../../chunks/chunk-5YWEUFLM.js";
6
+ import "../../../chunks/chunk-ZF5FHTES.js";
7
7
  import "../../../chunks/chunk-XXGYUYXI.js";
8
8
  import "../../../chunks/chunk-LZQXQOPJ.js";
9
9
 
@@ -7,9 +7,9 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-BFHCZVNO.js";
11
- import "../../../chunks/chunk-MLRF72MK.js";
12
- import "../../../chunks/chunk-SUPAWIKP.js";
10
+ } from "../../../chunks/chunk-YWWLRZSG.js";
11
+ import "../../../chunks/chunk-5YWEUFLM.js";
12
+ import "../../../chunks/chunk-ZF5FHTES.js";
13
13
  import {
14
14
  Type
15
15
  } from "../../../chunks/chunk-XXGYUYXI.js";
@@ -4,14 +4,14 @@ import {
4
4
  formatTransportLifecycle,
5
5
  getConfigDir,
6
6
  logTransportLifecycle
7
- } from "../../../chunks/chunk-OOUL3DRE.js";
7
+ } from "../../../chunks/chunk-GAUIKMBA.js";
8
8
  import {
9
9
  SUBAGENT_SESSION_RECORD_VERSION,
10
10
  createSharedFileSystemTools,
11
11
  createSubagentCapability
12
- } from "../../../chunks/chunk-BFHCZVNO.js";
13
- import "../../../chunks/chunk-MLRF72MK.js";
14
- import "../../../chunks/chunk-SUPAWIKP.js";
12
+ } from "../../../chunks/chunk-YWWLRZSG.js";
13
+ import "../../../chunks/chunk-5YWEUFLM.js";
14
+ import "../../../chunks/chunk-ZF5FHTES.js";
15
15
  import "../../../chunks/chunk-XXGYUYXI.js";
16
16
  import "../../../chunks/chunk-LZQXQOPJ.js";
17
17
 
@@ -8,9 +8,9 @@ import {
8
8
  executeManageTodoList,
9
9
  executionStateToTodos,
10
10
  restoreExecutionState
11
- } from "../../../chunks/chunk-BFHCZVNO.js";
12
- import "../../../chunks/chunk-MLRF72MK.js";
13
- import "../../../chunks/chunk-SUPAWIKP.js";
11
+ } from "../../../chunks/chunk-YWWLRZSG.js";
12
+ import "../../../chunks/chunk-5YWEUFLM.js";
13
+ import "../../../chunks/chunk-ZF5FHTES.js";
14
14
  import "../../../chunks/chunk-XXGYUYXI.js";
15
15
  import "../../../chunks/chunk-LZQXQOPJ.js";
16
16
 
@@ -4,7 +4,7 @@ import {
4
4
  disposeModelTransports,
5
5
  streamSimple,
6
6
  validateToolArguments
7
- } from "./chunk-SUPAWIKP.js";
7
+ } from "./chunk-ZF5FHTES.js";
8
8
 
9
9
  // ../../packages/agent-core/src/agent-loop.ts
10
10
  function createLoopErrorMessage(error, config, signal) {
@@ -6,10 +6,10 @@ import {
6
6
  createSharedWebSearchTool,
7
7
  interpretShellExit,
8
8
  requestInteraction
9
- } from "./chunk-BFHCZVNO.js";
9
+ } from "./chunk-YWWLRZSG.js";
10
10
  import {
11
11
  getLogger
12
- } from "./chunk-SUPAWIKP.js";
12
+ } from "./chunk-ZF5FHTES.js";
13
13
  import {
14
14
  Type
15
15
  } from "./chunk-XXGYUYXI.js";
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "node:module"; const require =
2
2
  import {
3
3
  Agent,
4
4
  getToolCallerIdentity
5
- } from "./chunk-MLRF72MK.js";
5
+ } from "./chunk-5YWEUFLM.js";
6
6
  import {
7
7
  AssistantMessageEventStream,
8
8
  FileSystemGateway,
@@ -12,7 +12,7 @@ import {
12
12
  getPlatformConfig,
13
13
  hashText,
14
14
  streamSimple
15
- } from "./chunk-SUPAWIKP.js";
15
+ } from "./chunk-ZF5FHTES.js";
16
16
  import {
17
17
  Type
18
18
  } from "./chunk-XXGYUYXI.js";
@@ -1211,6 +1211,27 @@ function createPlanCapability() {
1211
1211
  });
1212
1212
  }
1213
1213
 
1214
+ // ../../packages/agent-framework/src/session/remote-failure.ts
1215
+ function classifyRemoteFailure(remote, message) {
1216
+ if (!remote || !["transient", "other", "context_overflow"].includes(remote.category)) return void 0;
1217
+ const overflow = remote.category === "context_overflow";
1218
+ const retryAfterMs = remote.retryAfterMs;
1219
+ return {
1220
+ kind: overflow ? "context_overflow" : remote.category === "transient" ? "provider_transient" : "provider_confirmation",
1221
+ retryable: !overflow,
1222
+ compactable: overflow,
1223
+ userAbort: false,
1224
+ terminal: false,
1225
+ message,
1226
+ ...typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs >= 0 ? { retryAfterMs } : {}
1227
+ };
1228
+ }
1229
+ function resolveRetryDelay(backoffMs, maxDelayMs, retryAfterMs = 0) {
1230
+ const maximumWait = Math.min(maxDelayMs ?? 6e4, 2147483647);
1231
+ if (retryAfterMs > maximumWait) return void 0;
1232
+ return Math.max(maxDelayMs === void 0 ? backoffMs : Math.min(backoffMs, maxDelayMs), retryAfterMs);
1233
+ }
1234
+
1214
1235
  // ../../packages/agent-framework/src/session/compaction.ts
1215
1236
  var COMPACT_PROMPT = `You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.
1216
1237
 
@@ -1577,6 +1598,7 @@ async function createCompactionSummary(messages, options = {}) {
1577
1598
  throwIfAborted();
1578
1599
  return appendFileOperationsToSummary(createSimpleSummary(messages), messages);
1579
1600
  }
1601
+ let confirmationRetries = 0;
1580
1602
  for (let attempt = 0; ; attempt++) {
1581
1603
  throwIfAborted();
1582
1604
  let response;
@@ -1602,17 +1624,22 @@ Return a text-only successor handoff. Do not call any tools.` }],
1602
1624
  }
1603
1625
  ).result();
1604
1626
  throwIfAborted();
1605
- if (response.stopReason === "error" && !response.content.some((block) => block.type === "toolCall")) {
1627
+ if (response.stopReason === "error" && (!response.content.some((block) => block.type === "toolCall") || classifyRemoteFailure(response.remoteFailure, response.errorMessage ?? "") !== void 0)) {
1606
1628
  const providerError = new Error(response.errorMessage || "Compaction provider error");
1607
1629
  const explicitRetryable = response.retryable;
1608
1630
  if (typeof explicitRetryable === "boolean") providerError.retryable = explicitRetryable;
1609
1631
  if (response.replayEligible === true) providerError.replayEligible = true;
1632
+ providerError.remoteFailure = response.remoteFailure;
1610
1633
  throw providerError;
1611
1634
  }
1612
1635
  } catch (error) {
1613
1636
  throwIfAborted();
1614
- if (attempt >= 2 || explicitlyNonRetryable(error) || !isTransientCompactionFailure(error)) throw error;
1615
- await waitForCompactionRetry(250 * 2 ** attempt, signal);
1637
+ const remote = classifyRemoteFailure(error?.remoteFailure, error instanceof Error ? error.message : String(error));
1638
+ if (attempt >= 2 || explicitlyNonRetryable(error) || (remote ? !remote.retryable : !isTransientCompactionFailure(error))) throw error;
1639
+ if (remote?.kind === "provider_confirmation" && confirmationRetries++ >= 1) throw error;
1640
+ const delayMs = resolveRetryDelay(250 * 2 ** attempt, 6e4, remote?.retryAfterMs);
1641
+ if (delayMs === void 0) throw new Error(`${remote?.message} (Retry-After exceeds the allowed wait; automatic recovery paused)`);
1642
+ await waitForCompactionRetry(delayMs, signal);
1616
1643
  continue;
1617
1644
  }
1618
1645
  if (response.stopReason !== "stop" || response.content.some((block) => block.type === "toolCall")) {
@@ -4705,7 +4732,7 @@ var AgentSessionAutoCompactScheduler = class {
4705
4732
  this.resolvePending();
4706
4733
  return;
4707
4734
  }
4708
- if (this.options.isStreaming()) {
4735
+ if (this.options.isStreaming() || this.runningAutoCompact !== void 0) {
4709
4736
  this.pendingAutoCompact = pending;
4710
4737
  this.schedule(pending, 100);
4711
4738
  return;
@@ -4717,7 +4744,11 @@ var AgentSessionAutoCompactScheduler = class {
4717
4744
  if (this.runningAutoCompact === running) {
4718
4745
  this.runningAutoCompact = void 0;
4719
4746
  this.runningAbortController = void 0;
4720
- this.resolvePending();
4747
+ try {
4748
+ this.options.onSettled?.();
4749
+ } finally {
4750
+ this.resolvePending();
4751
+ }
4721
4752
  }
4722
4753
  });
4723
4754
  this.runningAutoCompact = running;
@@ -4742,6 +4773,7 @@ var AgentSessionAutoCompactScheduler = class {
4742
4773
  });
4743
4774
  }
4744
4775
  resolvePending() {
4776
+ if (this.hasPendingAutoCompact) return;
4745
4777
  const resolve2 = this.resolvePendingWait;
4746
4778
  this.pendingWait = void 0;
4747
4779
  this.resolvePendingWait = void 0;
@@ -5276,7 +5308,8 @@ function createFailureClassification(context, retry, classifyFailure) {
5276
5308
  if (context.message?.role === "assistant" && context.message.retryable === false) {
5277
5309
  return { kind: "unknown", retryable: false, compactable: false, userAbort: context.message.stopReason === "aborted", terminal: true, message: context.errorMessage };
5278
5310
  }
5279
- const hostClassification = classifyFailure?.(context);
5311
+ const remote = context.message?.role === "assistant" && context.message.stopReason === "error" ? classifyRemoteFailure(context.message.remoteFailure, context.errorMessage) : void 0;
5312
+ const hostClassification = remote ? retry || remote.compactable ? remote : asTerminalFailure(remote) : classifyFailure?.(context);
5280
5313
  if (hostClassification) {
5281
5314
  return hostClassification;
5282
5315
  }
@@ -5433,22 +5466,23 @@ var AgentSessionRetryController = class {
5433
5466
  this.resolvePending();
5434
5467
  return;
5435
5468
  }
5436
- const maxRetries = this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3;
5469
+ const maxRetries = Math.min(this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3, failure.kind === "provider_confirmation" ? 1 : Infinity);
5437
5470
  const kindAttempts = (this.retryAttempts.get(failure.kind) ?? 0) + 1;
5438
5471
  this.retryAttempts.set(failure.kind, kindAttempts);
5439
5472
  this.totalRetryAttempts += 1;
5440
5473
  const totalBudget = this.retry.maxTotalRetries;
5441
5474
  const kindExhausted = kindAttempts > maxRetries;
5442
5475
  const totalExhausted = totalBudget !== void 0 && this.totalRetryAttempts > totalBudget;
5443
- if (kindExhausted || totalExhausted) {
5444
- const terminalFailure = asTerminalFailure(failure);
5476
+ const delayMs = resolveRetryDelay((this.retry.baseDelayMs ?? 2e3) * 2 ** (kindAttempts - 1), this.retry.maxDelayMs, failure.retryAfterMs);
5477
+ if (kindExhausted || totalExhausted || delayMs === void 0) {
5478
+ const terminalFailure = asTerminalFailure(failure, delayMs === void 0 ? `${failure.message} (Retry-After exceeds the allowed wait; automatic recovery paused)` : failure.message);
5445
5479
  if (failure.replayExempt === true) {
5446
5480
  const outcome = this.replayCircuit.recordReplayExhaustion();
5447
5481
  if (outcome.opened) {
5448
5482
  this.emit({ type: "retry_exhausted", errorMessage: `systemic timeout-stall: ${outcome.consecutive} consecutive turns ended by timeout-replay exhaustion`, maxRetries: totalExhausted ? totalBudget : maxRetries });
5449
5483
  }
5450
5484
  }
5451
- this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries: totalExhausted ? totalBudget : maxRetries });
5485
+ this.emit({ type: "retry_exhausted", errorMessage: terminalFailure.message, maxRetries: totalExhausted ? totalBudget : maxRetries });
5452
5486
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
5453
5487
  this.emit({ type: "turn_settled" });
5454
5488
  this.resetAttempts();
@@ -5457,8 +5491,6 @@ var AgentSessionRetryController = class {
5457
5491
  return;
5458
5492
  }
5459
5493
  const attempt = kindAttempts;
5460
- const rawDelayMs = (this.retry.baseDelayMs ?? 2e3) * 2 ** (attempt - 1);
5461
- const delayMs = this.retry.maxDelayMs !== void 0 ? Math.min(rawDelayMs, this.retry.maxDelayMs) : rawDelayMs;
5462
5494
  this.ensurePending();
5463
5495
  const epoch = this.retryEpoch;
5464
5496
  const pending = this.pendingRetry;
@@ -5510,7 +5542,7 @@ var AgentSessionRetryController = class {
5510
5542
  userAbort: false,
5511
5543
  terminal: true
5512
5544
  });
5513
- const maxRetries = (failure !== void 0 ? this.retry?.maxRetriesForFailure?.(failure) : void 0) ?? this.retry?.maxRetries ?? 3;
5545
+ const maxRetries = Math.min((failure !== void 0 ? this.retry?.maxRetriesForFailure?.(failure) : void 0) ?? this.retry?.maxRetries ?? 3, failure?.kind === "provider_confirmation" ? 1 : Infinity);
5514
5546
  this.emit({ type: "retry_exhausted", errorMessage: terminalFailure.message, maxRetries });
5515
5547
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure });
5516
5548
  this.emit({ type: "turn_settled" });
@@ -6211,8 +6243,9 @@ var AgentSessionController = class {
6211
6243
  getRuntimeGuardTriggered: () => this.runtimeGuard.triggered,
6212
6244
  isStreaming: () => this.isStreaming,
6213
6245
  runAutoCompact: async (decision, signal) => {
6214
- await this.runAutoCompact(decision.reason, decision.willRetry, { signal });
6215
- }
6246
+ await this.runAutoCompact(decision.reason, decision.willRetry, { signal }).finally(() => signal.aborted ? void 0 : this.pendingEndOperations.wait());
6247
+ },
6248
+ onSettled: () => this.pendingEndOperations.track(() => this.handleAgentEndHook(this.agent.state.messages.slice()))
6216
6249
  });
6217
6250
  this.autoContinue = new AgentSessionAutoContinueController({
6218
6251
  agent: this.agent,
@@ -5445,6 +5445,68 @@ function buildResponsesCreateEvent(model, context, options) {
5445
5445
  return { type: "response.create", ...params };
5446
5446
  }
5447
5447
 
5448
+ // ../../packages/ai/src/providers/responses/responses-remote-failure.ts
5449
+ var MAX_TEXT = 4096;
5450
+ var transientCodes = /* @__PURE__ */ new Set(["server_error", "rate_limit_exceeded", "slow_down", "rate_limit_error", "server_is_overloaded", "service_unavailable_error"]);
5451
+ function responsesRemoteFailure(value, status, headers) {
5452
+ const root = isRecord2(value) ? value : {};
5453
+ const response = isRecord2(root.response) ? root.response : {};
5454
+ const error = isRecord2(root.error) ? root.error : isRecord2(response.error) ? response.error : root;
5455
+ const code = typeof error.code === "string" ? error.code.slice(0, 128).toLowerCase() : "";
5456
+ const type = typeof error.type === "string" ? error.type.slice(0, 128).toLowerCase() : "";
5457
+ const message = (typeof value === "string" ? value : typeof error.message === "string" ? error.message : "").slice(0, MAX_TEXT).toLowerCase();
5458
+ const httpStatus = status ?? root.status ?? root.statusCode;
5459
+ const fields = `${code} ${type}`;
5460
+ let category = "other";
5461
+ if (/context_length_exceeded|context_window_exceeded|context_overflow/.test(fields) || /context (?:length|window).{0,60}(?:exceed|too (?:long|large))|maximum context length|exceeds.{0,30}context window/.test(message)) category = "context_overflow";
5462
+ else if (/billing|insufficient_quota|insufficient_balance|credit|usage_limit|spend_limit/.test(fields) || /billing|(?:account|monthly) quota|exceeded your current quota|insufficient (?:credit|balance)|credit balance|spend(?:ing)? limit/.test(message)) category = "other";
5463
+ else if (typeof httpStatus === "number" && httpStatus >= 400 && httpStatus < 500 && httpStatus !== 429) category = "other";
5464
+ else if (httpStatus === 429 || typeof httpStatus === "number" && httpStatus >= 500 && httpStatus <= 599 || transientCodes.has(code) || transientCodes.has(type) || /server (?:is )?overloaded|temporarily unavailable|internal server error|rate limit (?:exceeded|reached)/.test(message)) category = "transient";
5465
+ const retryAfterMs = parseRetryAfter(headers ?? root.headers);
5466
+ return { category, ...retryAfterMs !== void 0 ? { retryAfterMs } : {} };
5467
+ }
5468
+ function parseRetryAfter(headers) {
5469
+ if (!headers || typeof headers !== "object") return void 0;
5470
+ let raw;
5471
+ if ("get" in headers && typeof headers.get === "function") raw = headers.get("retry-after");
5472
+ else for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === "retry-after") raw = value;
5473
+ if (typeof raw !== "string" || raw.length > 128) return void 0;
5474
+ const text = raw.trim();
5475
+ if (/^\d+(?:\.\d+)?$/.test(text)) {
5476
+ const delay = Number(text) * 1e3;
5477
+ return Number.isFinite(delay) ? delay : Number.MAX_VALUE;
5478
+ }
5479
+ if (!/^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(text)) return void 0;
5480
+ const date = Date.parse(text);
5481
+ if (!Number.isFinite(date) || new Date(date).toUTCString() !== text) return void 0;
5482
+ return Math.max(0, date - Date.now());
5483
+ }
5484
+ async function readResponsesErrorBody(read, signal) {
5485
+ let timer;
5486
+ let onAbort;
5487
+ try {
5488
+ return await Promise.race([
5489
+ Promise.resolve().then(read).then((text) => text.slice(0, MAX_TEXT)).catch(() => ""),
5490
+ new Promise((resolve) => {
5491
+ onAbort = () => resolve("");
5492
+ if (signal.aborted) resolve("");
5493
+ else signal.addEventListener("abort", onAbort, { once: true });
5494
+ timer = setTimeout(() => resolve(""), 250);
5495
+ })
5496
+ ]);
5497
+ } finally {
5498
+ if (timer !== void 0) clearTimeout(timer);
5499
+ if (onAbort) signal.removeEventListener("abort", onAbort);
5500
+ }
5501
+ }
5502
+ function parseResponsesErrorBody(text) {
5503
+ try {
5504
+ return JSON.parse(text);
5505
+ } catch {
5506
+ return text;
5507
+ }
5508
+ }
5509
+
5448
5510
  // ../../packages/ai/src/providers/responses/responses-usage.ts
5449
5511
  function tokenCount(value) {
5450
5512
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
@@ -5515,6 +5577,19 @@ var ResponsesEventReducer = class {
5515
5577
  }
5516
5578
  /** Feed one raw wire event; returns the AssistantMessageEvents to emit. */
5517
5579
  feed(raw) {
5580
+ if (this.terminal) return [];
5581
+ try {
5582
+ const events = this.feedInbound(raw);
5583
+ if (this.isTerminal && this.output.stopReason === "error") {
5584
+ this.output.remoteFailure = responsesRemoteFailure(raw);
5585
+ }
5586
+ return events;
5587
+ } catch (error) {
5588
+ this.terminal = null;
5589
+ throw error;
5590
+ }
5591
+ }
5592
+ feedInbound(raw) {
5518
5593
  const events = [];
5519
5594
  if (!isResponsesEventLike(raw)) {
5520
5595
  throw new ResponsesProtocolError("Responses stream returned an event without a string type.");
@@ -6033,6 +6108,7 @@ function streamResponsesSSE(model, context, options) {
6033
6108
  let providerErrorMessage;
6034
6109
  let transportLost = false;
6035
6110
  let endedWithoutTerminal = false;
6111
+ let responseId;
6036
6112
  const requestAbort = new AbortController();
6037
6113
  const onUserAbort = () => requestAbort.abort();
6038
6114
  const clearTotalTimer = () => {
@@ -6082,8 +6158,8 @@ function streamResponsesSSE(model, context, options) {
6082
6158
  timeoutKind: "request_total",
6083
6159
  terminalAccepted: false,
6084
6160
  cancelSource: "internal_timeout",
6085
- retryAllowed: !submitted,
6086
- retryDecision: submitted ? "not_retryable_after_submission" : "not_submitted"
6161
+ retryAllowed: !!reducer.message.remoteFailure || !submitted,
6162
+ retryDecision: reducer.message.remoteFailure ? `remote_${reducer.message.remoteFailure.category}` : submitted ? "not_retryable_after_submission" : "not_submitted"
6087
6163
  });
6088
6164
  requestAbort.abort();
6089
6165
  }, resolved.requestTimeoutMs);
@@ -6128,6 +6204,7 @@ function streamResponsesSSE(model, context, options) {
6128
6204
  const status = error && typeof error === "object" ? error.status ?? error.statusCode : void 0;
6129
6205
  if (typeof status === "number" && status >= 400) {
6130
6206
  providerRejected = true;
6207
+ reducer.message.remoteFailure = responsesRemoteFailure(error, status);
6131
6208
  providerErrorMessage = `API error ${status}: ${error instanceof Error ? error.message : "request rejected"}`;
6132
6209
  }
6133
6210
  transportLost = !providerRejected && !(error instanceof ResponsesProtocolError || error instanceof SyntaxError);
@@ -6136,8 +6213,13 @@ function streamResponsesSSE(model, context, options) {
6136
6213
  if (!response.ok) {
6137
6214
  providerRejected = true;
6138
6215
  providerErrorMessage = `API error ${response.status}`;
6139
- const errorBody = await response.text().catch(() => "");
6140
- if (errorBody) providerErrorMessage += `: ${errorBody}`;
6216
+ reducer.message.remoteFailure = responsesRemoteFailure({}, response.status, response.headers);
6217
+ const errorBody = await readResponsesErrorBody(() => response.text(), requestAbort.signal);
6218
+ if (errorBody) {
6219
+ providerErrorMessage += `: ${errorBody}`;
6220
+ reducer.message.remoteFailure = responsesRemoteFailure(parseResponsesErrorBody(errorBody), response.status, response.headers);
6221
+ }
6222
+ requestAbort.abort();
6141
6223
  throw new Error(providerErrorMessage);
6142
6224
  }
6143
6225
  if (!response.readSSELines) {
@@ -6161,21 +6243,39 @@ function streamResponsesSSE(model, context, options) {
6161
6243
  if (data === "[DONE]") {
6162
6244
  continue;
6163
6245
  }
6164
- let event;
6246
+ if (requestAbort.signal.aborted) {
6247
+ throw new Error(internalTimeout ? `Responses request timeout (${internalTimeout})` : "Request was aborted");
6248
+ }
6249
+ let events;
6165
6250
  try {
6166
- event = JSON.parse(data);
6251
+ let event;
6252
+ try {
6253
+ event = JSON.parse(data);
6254
+ } catch (error) {
6255
+ const message = error instanceof Error ? error.message : String(error);
6256
+ throw new ResponsesProtocolError(`Responses SSE stream returned malformed JSON: ${message}`);
6257
+ }
6258
+ if (!isResponsesEventLike(event)) {
6259
+ throw new ResponsesProtocolError("Responses SSE payload is not an event object with a string type.");
6260
+ }
6261
+ if (event.type.startsWith("response.output") || event.type.startsWith("response.content") || event.type.startsWith("response.reasoning")) {
6262
+ sawModelContent = true;
6263
+ }
6264
+ const incomingResponse = event.response;
6265
+ if (event.type === "response.created" && (!isRecord2(incomingResponse) || typeof incomingResponse.id !== "string" || !incomingResponse.id)) {
6266
+ throw new ResponsesProtocolError("response.created requires a response id.");
6267
+ }
6268
+ if (isRecord2(incomingResponse) && typeof incomingResponse.id === "string") {
6269
+ if (responseId && (incomingResponse.id !== responseId || event.type === "response.created")) {
6270
+ throw new ResponsesProtocolError("Response identity changed within a request.");
6271
+ }
6272
+ responseId = incomingResponse.id;
6273
+ }
6274
+ events = reducer.feed(event);
6167
6275
  } catch (error) {
6168
- const message = error instanceof Error ? error.message : String(error);
6169
- throw new ResponsesProtocolError(`Responses SSE stream returned malformed JSON: ${message}`);
6170
- }
6171
- if (!isResponsesEventLike(event)) {
6172
- throw new ResponsesProtocolError("Responses SSE payload is not an event object with a string type.");
6173
- }
6174
- if (typeof event.type === "string" && (event.type.startsWith("response.output") || event.type.startsWith("response.content") || event.type.startsWith("response.reasoning"))) {
6175
- sawModelContent = true;
6276
+ reducer.message.remoteFailure = { category: "other" };
6277
+ throw error;
6176
6278
  }
6177
- const events = reducer.feed(event);
6178
- if (reducer.isTerminal && reducer.message.stopReason === "error") reducer.message.retryable = false;
6179
6279
  for (const assistantEvent of events) {
6180
6280
  stream.push(assistantEvent);
6181
6281
  }
@@ -6183,7 +6283,7 @@ function streamResponsesSSE(model, context, options) {
6183
6283
  terminalAccepted = true;
6184
6284
  phase = "terminal_accepted";
6185
6285
  clearTotalTimer();
6186
- lifecycle({ retryAllowed: reducer.message.retryable !== false, retryDecision: "terminal" });
6286
+ lifecycle({ retryAllowed: reducer.message.retryable !== false, retryDecision: reducer.message.remoteFailure ? `remote_${reducer.message.remoteFailure.category}` : "terminal" });
6187
6287
  break;
6188
6288
  }
6189
6289
  }
@@ -6204,6 +6304,7 @@ function streamResponsesSSE(model, context, options) {
6204
6304
  const message = reducer.message;
6205
6305
  const userAborted = options?.signal?.aborted === true;
6206
6306
  message.stopReason = userAborted ? "aborted" : "error";
6307
+ if (userAborted) delete message.remoteFailure;
6207
6308
  const adapterTimeoutKind = error instanceof Error ? error.timeoutKind : void 0;
6208
6309
  if (!internalTimeout && (adapterTimeoutKind === "first_byte" || adapterTimeoutKind === "stream_idle")) {
6209
6310
  internalTimeout = adapterTimeoutKind === "first_byte" ? "first_response" : "stream_idle";
@@ -6212,19 +6313,19 @@ function streamResponsesSSE(model, context, options) {
6212
6313
  message.errorMessage = providerErrorMessage ?? (internalTimeout && !protocolFailure ? `Responses request timeout (${internalTimeout}) after ${Math.round(monotonicNow() - startedAt)}ms` : error instanceof Error ? error.message : JSON.stringify(error));
6213
6314
  const compat = getResponsesCompat(model);
6214
6315
  const streamLost = (endedWithoutTerminal || transportLost) && !protocolFailure && !internalTimeout && submitted && !localFailure && !providerRejected && message.stopReason === "error";
6215
- if (internalTimeout && !protocolFailure && submitted && !providerRejected && !localFailure && !userAborted && compat.timeoutReplay) {
6316
+ if (internalTimeout && !message.remoteFailure && !protocolFailure && submitted && !providerRejected && !localFailure && !userAborted && compat.timeoutReplay) {
6216
6317
  message.replayEligible = true;
6217
6318
  message.replayClass = internalTimeout;
6218
- } else if (streamLost && compat.timeoutReplay) {
6319
+ } else if (streamLost && !message.remoteFailure && compat.timeoutReplay) {
6219
6320
  message.replayEligible = true;
6220
6321
  message.replayClass = receivedMessageCount === 0 ? "stream_lost" : "stream_lost_partial";
6221
6322
  }
6222
- if ((submitted || localFailure) && !(streamLost && receivedMessageCount === 0)) message.retryable = false;
6323
+ if (!message.remoteFailure && (userAborted || (submitted || localFailure) && !(streamLost && receivedMessageCount === 0))) message.retryable = false;
6223
6324
  phase = "cleanup";
6224
6325
  lifecycle({
6225
6326
  timeoutKind: internalTimeout,
6226
6327
  retryAllowed: !userAborted && !localFailure && message.retryable !== false,
6227
- retryDecision: streamLost ? receivedMessageCount === 0 ? message.replayEligible ? "replay_exempt_stream_lost" : "stream_lost_no_evidence" : message.replayEligible ? "replay_exempt_after_submission" : "not_retryable_after_submission" : submitted ? "not_retryable_after_submission" : localFailure ? "local_configuration_error" : "not_submitted",
6328
+ retryDecision: message.remoteFailure ? `remote_${message.remoteFailure.category}` : streamLost ? receivedMessageCount === 0 ? message.replayEligible ? "replay_exempt_stream_lost" : "stream_lost_no_evidence" : message.replayEligible ? "replay_exempt_after_submission" : "not_retryable_after_submission" : submitted ? "not_retryable_after_submission" : localFailure ? "local_configuration_error" : "not_submitted",
6228
6329
  cancelSource: userAborted ? "user" : internalTimeout ? "internal_timeout" : "none",
6229
6330
  cleanupOutcome: "request_abandoned"
6230
6331
  });
@@ -6431,6 +6532,7 @@ function streamResponsesWS(model, context, options) {
6431
6532
  if (state.busy) {
6432
6533
  reducer.message.stopReason = "error";
6433
6534
  reducer.message.errorMessage = "Responses owner already has an in-flight request.";
6535
+ reducer.message.retryable = false;
6434
6536
  stream.push({ type: "error", reason: "error", error: reducer.message });
6435
6537
  stream.end();
6436
6538
  return stream;
@@ -6687,12 +6789,18 @@ function streamResponsesWS(model, context, options) {
6687
6789
  });
6688
6790
  } catch (error) {
6689
6791
  if (error instanceof WebSocketTransportError && error.kind === "timeout") timedOut = "connect";
6792
+ const status = error && typeof error === "object" ? error.status ?? error.statusCode : void 0;
6793
+ if (typeof status === "number" && status >= 400) {
6794
+ providerRejected = true;
6795
+ reducer.message.remoteFailure = responsesRemoteFailure(error, status);
6796
+ }
6690
6797
  if (error instanceof WebSocketTransportError && error.kind === "handshake" && !options?.signal?.aborted && !state.abort.signal.aborted) {
6691
- const status = error.status ?? 0;
6692
- providerRejected = status > 0;
6693
- const endpointHasNoWebsockets = options?.transport === "auto" && [404, 405, 426, 501].includes(status);
6694
- const wsEdgeRefused = status === 0 || status === 429 || status >= 500 && status <= 599;
6798
+ const status2 = error.status ?? 0;
6799
+ providerRejected = status2 > 0;
6800
+ const endpointHasNoWebsockets = options?.transport === "auto" && [404, 405, 426, 501].includes(status2);
6801
+ const wsEdgeRefused = status2 === 0 || status2 === 429 || status2 >= 500 && status2 <= 599;
6695
6802
  if (endpointHasNoWebsockets || wsEdgeRefused) {
6803
+ delete reducer.message.remoteFailure;
6696
6804
  await runSSEFallback();
6697
6805
  return;
6698
6806
  }
@@ -6774,32 +6882,38 @@ function streamResponsesWS(model, context, options) {
6774
6882
  if (state.abort.signal.aborted || requestAbort.signal.aborted) {
6775
6883
  throw new Error(timedOut ? `Responses request timeout (${timedOut})` : "Request aborted");
6776
6884
  }
6777
- if (message.isBinary) throw new ResponsesProtocolError("Responses requires JSON text messages.");
6778
- const event = JSON.parse(message.data);
6779
- if (!isRecord2(event)) throw new ResponsesProtocolError("Invalid Responses WebSocket event.");
6780
- if (typeof event.type === "string") {
6781
- if (event.type === "response.created") sawResponseCreated = true;
6782
- else if (event.type.startsWith("response.output") || event.type.startsWith("response.content") || event.type.startsWith("response.reasoning")) sawModelContent = true;
6783
- }
6784
- if (!started && attempt === 0 && payload.previous_response_id && event.type === "error" && event.status === 400 && isRecord2(event.error) && event.error.code === "previous_response_not_found" && event.error.param === "previous_response_id") {
6785
- delete payload.previous_response_id;
6786
- payload.input = fullInput;
6787
- continuationReason = "previous_response_not_found";
6788
- rebuild = true;
6789
- break;
6790
- }
6791
- if (!started && typeof event.type === "string" && event.type !== "error" && !event.type.startsWith("response.")) continue;
6792
- if (!started && event.type !== "error") {
6793
- if (event.type !== "response.created" || !isRecord2(event.response) || typeof event.response.id !== "string" || event.response.id === state.lastResponseId) {
6794
- throw new ResponsesProtocolError("Expected a new response.created before output.");
6885
+ let events;
6886
+ try {
6887
+ if (message.isBinary) throw new ResponsesProtocolError("Responses requires JSON text messages.");
6888
+ const event = JSON.parse(message.data);
6889
+ if (!isRecord2(event)) throw new ResponsesProtocolError("Invalid Responses WebSocket event.");
6890
+ if (typeof event.type === "string") {
6891
+ if (event.type === "response.created") sawResponseCreated = true;
6892
+ else if (event.type.startsWith("response.output") || event.type.startsWith("response.content") || event.type.startsWith("response.reasoning")) sawModelContent = true;
6893
+ }
6894
+ if (!started && attempt === 0 && payload.previous_response_id && event.type === "error" && event.status === 400 && isRecord2(event.error) && event.error.code === "previous_response_not_found" && event.error.param === "previous_response_id") {
6895
+ delete payload.previous_response_id;
6896
+ payload.input = fullInput;
6897
+ continuationReason = "previous_response_not_found";
6898
+ rebuild = true;
6899
+ break;
6900
+ }
6901
+ if (!started && typeof event.type === "string" && event.type !== "error" && !event.type.startsWith("response.")) continue;
6902
+ if (started && event.type === "response.created") throw new ResponsesProtocolError("Duplicate response.created within a request.");
6903
+ if (!started && event.type !== "error") {
6904
+ if (event.type !== "response.created" || !isRecord2(event.response) || typeof event.response.id !== "string" || !event.response.id || event.response.id === state.lastResponseId) {
6905
+ throw new ResponsesProtocolError("Expected a new response.created before output.");
6906
+ }
6907
+ started = true;
6908
+ responseId = event.response.id;
6795
6909
  }
6796
- started = true;
6797
- responseId = event.response.id;
6910
+ if (responseId && isRecord2(event.response) && event.response.id !== responseId) throw new ResponsesProtocolError("Response identity changed within a request.");
6911
+ events = reducer.feed(event);
6912
+ } catch (error) {
6913
+ reducer.message.remoteFailure = { category: "other" };
6914
+ throw error;
6798
6915
  }
6799
- if (responseId && isRecord2(event.response) && event.response.id !== responseId) throw new ResponsesProtocolError("Response identity changed within a request.");
6800
- const events = reducer.feed(event);
6801
6916
  if (reducer.isTerminal) {
6802
- if (reducer.message.stopReason === "error") reducer.message.retryable = false;
6803
6917
  const response = reducer.terminalResponse;
6804
6918
  state.lastResponseId = response?.id;
6805
6919
  if (!options?.onPayload && compat.responsesContinuation && identity && response?.status === "completed" && reducer.message.stopReason !== "error") {
@@ -6818,10 +6932,11 @@ function streamResponsesWS(model, context, options) {
6818
6932
  }
6819
6933
  finished = true;
6820
6934
  clearRequestTimers();
6935
+ retryDecision = reducer.message.remoteFailure ? `remote_${reducer.message.remoteFailure.category}` : "terminal";
6821
6936
  lifecycle("terminal_accepted", {
6822
6937
  terminalAccepted: true,
6823
6938
  retryAllowed: reducer.message.retryable !== false,
6824
- retryDecision: "terminal"
6939
+ retryDecision
6825
6940
  });
6826
6941
  for (const e of events) publish(e);
6827
6942
  break;
@@ -6847,28 +6962,30 @@ function streamResponsesWS(model, context, options) {
6847
6962
  const userAborted = options?.signal?.aborted === true;
6848
6963
  const ownerDisposed = !userAborted && !timedOut && state.abort.signal.aborted;
6849
6964
  message.stopReason = userAborted || ownerDisposed ? "aborted" : "error";
6965
+ if (userAborted || ownerDisposed) delete message.remoteFailure;
6850
6966
  const protocolFailure = !endedWithoutTerminal && (error instanceof ResponsesProtocolError || error instanceof SyntaxError || !transportLost && error instanceof TypeError || error instanceof WebSocketTransportError && (error.kind === "protocol" || error.kind === "overflow"));
6851
6967
  const cause = providerRejected && error instanceof WebSocketTransportError ? `${error.message} (HTTP status ${error.status})` : timedOut && !protocolFailure ? `Responses request timeout (${timedOut}) after ${ageMs()}ms` : error instanceof Error ? error.message : String(error);
6852
6968
  message.errorMessage = cause;
6853
6969
  const streamLost = (endedWithoutTerminal || transportLost) && !protocolFailure && sent && !timedOut && !providerRejected && message.stopReason === "error";
6854
- if (timedOut && timedOut !== "connect" && !protocolFailure && !localFailure && sent && !providerRejected && !userAborted && !ownerDisposed && compat.timeoutReplay) {
6970
+ if (timedOut && timedOut !== "connect" && !message.remoteFailure && !protocolFailure && !localFailure && sent && !providerRejected && !userAborted && !ownerDisposed && compat.timeoutReplay) {
6855
6971
  message.replayEligible = true;
6856
6972
  message.replayClass = timedOut;
6857
- } else if (streamLost && compat.timeoutReplay) {
6973
+ } else if (streamLost && !message.remoteFailure && compat.timeoutReplay) {
6858
6974
  message.replayEligible = true;
6859
6975
  message.replayClass = receivedMessageCount === 0 ? "stream_lost" : "stream_lost_partial";
6860
6976
  }
6861
- if (localFailure || providerRejected || protocolFailure) {
6977
+ if (!message.remoteFailure && (localFailure || providerRejected || protocolFailure || userAborted || ownerDisposed)) {
6862
6978
  message.retryable = false;
6863
6979
  }
6864
6980
  if (sent) {
6865
6981
  if (streamLost && receivedMessageCount === 0) {
6866
6982
  retryDecision = message.replayEligible ? "replay_exempt_stream_lost" : "stream_lost_no_evidence";
6867
6983
  } else {
6868
- message.retryable = false;
6984
+ if (!message.remoteFailure) message.retryable = false;
6869
6985
  if (!timedOut) retryDecision = message.replayEligible ? "replay_exempt_after_submission" : "not_retryable_after_submission";
6870
6986
  }
6871
6987
  }
6988
+ if (message.remoteFailure) retryDecision = `remote_${message.remoteFailure.category}`;
6872
6989
  cleanupCancelSource = userAborted ? "user" : timedOut ? "internal_timeout" : ownerDisposed ? "owner_disposal" : "none";
6873
6990
  stream.push({ type: "error", reason: message.stopReason, error: message });
6874
6991
  }
@@ -6890,7 +7007,7 @@ function streamResponsesWS(model, context, options) {
6890
7007
  terminalAccepted: finished,
6891
7008
  timeoutKind: timedOut,
6892
7009
  submissionAttempted: sent,
6893
- retryAllowed: !finished && reducer.message.stopReason !== "aborted" && reducer.message.retryable !== false,
7010
+ retryAllowed: (!finished || !!reducer.message.remoteFailure) && reducer.message.stopReason !== "aborted" && reducer.message.retryable !== false,
6894
7011
  cancelSource,
6895
7012
  retryDecision,
6896
7013
  cleanupOutcome
@@ -6,8 +6,8 @@ import {
6
6
  bindToolCallerIdentity,
7
7
  createToolCallerIdentity,
8
8
  getToolCallerIdentity
9
- } from "./chunk-MLRF72MK.js";
10
- import "./chunk-SUPAWIKP.js";
9
+ } from "./chunk-5YWEUFLM.js";
10
+ import "./chunk-ZF5FHTES.js";
11
11
  import "./chunk-XXGYUYXI.js";
12
12
  import "./chunk-LZQXQOPJ.js";
13
13
  export {
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  EventStream
4
- } from "./chunk-SUPAWIKP.js";
4
+ } from "./chunk-ZF5FHTES.js";
5
5
  import "./chunk-XXGYUYXI.js";
6
6
  import "./chunk-LZQXQOPJ.js";
7
7
 
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  logTransportLifecycle,
24
24
  migrateConfigFromAgentDir,
25
25
  truncateHeadTail
26
- } from "./chunks/chunk-OOUL3DRE.js";
26
+ } from "./chunks/chunk-GAUIKMBA.js";
27
27
  import {
28
28
  resolveCliProjectRoot
29
29
  } from "./chunks/chunk-WLFOBECN.js";
@@ -85,8 +85,8 @@ import {
85
85
  shouldPreserveExecutionStateForUserText,
86
86
  supersedeExecutionState,
87
87
  verifyPreparedCompactionCommit
88
- } from "./chunks/chunk-BFHCZVNO.js";
89
- import "./chunks/chunk-MLRF72MK.js";
88
+ } from "./chunks/chunk-YWWLRZSG.js";
89
+ import "./chunks/chunk-5YWEUFLM.js";
90
90
  import {
91
91
  Deref,
92
92
  EMPTY_ASSISTANT_CONTENT_ERROR,
@@ -111,7 +111,7 @@ import {
111
111
  sortToolModelCandidatesByCapability,
112
112
  streamSimple,
113
113
  type_exports
114
- } from "./chunks/chunk-SUPAWIKP.js";
114
+ } from "./chunks/chunk-ZF5FHTES.js";
115
115
  import {
116
116
  IsArray,
117
117
  IsBigInt,
@@ -82190,7 +82190,7 @@ var InteractiveMode = class {
82190
82190
  async init() {
82191
82191
  const activeSession = this.sessionManager.getActiveSession();
82192
82192
  this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
82193
- const { Agent } = await import("./chunks/src-DV4UYUNJ.js");
82193
+ const { Agent } = await import("./chunks/src-6WK5KYWQ.js");
82194
82194
  this.agent = new Agent({
82195
82195
  initialState: {
82196
82196
  systemPrompt: this.buildSystemPrompt(),
@@ -83049,7 +83049,7 @@ async function runPrintMode(params) {
83049
83049
  `);
83050
83050
  console.log("Assistant: ");
83051
83051
  }
83052
- const { Agent: AgentClass } = await import("./chunks/src-DV4UYUNJ.js");
83052
+ const { Agent: AgentClass } = await import("./chunks/src-6WK5KYWQ.js");
83053
83053
  let agent;
83054
83054
  const printModeExtensions = await loadPrintModeExtensions({
83055
83055
  cwd: runtime.cwd,
@@ -83905,7 +83905,7 @@ async function runJsonEventsMode(params) {
83905
83905
  return;
83906
83906
  }
83907
83907
  const parent = agent;
83908
- const { Agent: AgentClass } = await import("./chunks/src-DV4UYUNJ.js");
83908
+ const { Agent: AgentClass } = await import("./chunks/src-6WK5KYWQ.js");
83909
83909
  const sideAgent = new AgentClass({
83910
83910
  initialState: {
83911
83911
  systemPrompt: parent.state.systemPrompt,
@@ -84259,7 +84259,7 @@ async function runJsonEventsMode(params) {
84259
84259
  if (runtime.initialModel.unconfigured || controller) {
84260
84260
  return;
84261
84261
  }
84262
- const { Agent: AgentClass } = await import("./chunks/src-DV4UYUNJ.js");
84262
+ const { Agent: AgentClass } = await import("./chunks/src-6WK5KYWQ.js");
84263
84263
  if (runtimeClosing) return;
84264
84264
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
84265
84265
  if (runtimeClosing) {
@@ -84866,7 +84866,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
84866
84866
  }
84867
84867
  async function createCliTestStreamFnFromEnv() {
84868
84868
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
84869
- return (await import("./chunks/test-stream-SWO34GSS.js")).createTestStreamFnFromSequenceEnv();
84869
+ return (await import("./chunks/test-stream-7EH7BGY6.js")).createTestStreamFnFromSequenceEnv();
84870
84870
  }
84871
84871
  function resolveJsonEventsDetailFlag() {
84872
84872
  for (let index = 0; index < process.argv.length; index += 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "2.7.5",
3
+ "version": "2.7.6",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {