@cydm/pie 2.7.10 → 2.7.12

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.
@@ -1519,6 +1519,9 @@ function getSystemIO() {
1519
1519
  }
1520
1520
  return CS.System.IO;
1521
1521
  }
1522
+ function looksLikeBase64(value) {
1523
+ return value.length > 0 && value.length % 4 === 0 && /^[A-Za-z0-9+/]+={0,2}$/.test(value);
1524
+ }
1522
1525
  function getPieFileBridge() {
1523
1526
  if (typeof CS === "undefined" || !CS?.Pie?.PieFileBridge) {
1524
1527
  throw new Error("CS.Pie.PieFileBridge not available - runtime file bridge is missing");
@@ -1667,11 +1670,15 @@ var PuerTSFileSystem = class {
1667
1670
  }
1668
1671
  if (encoding === "base64") {
1669
1672
  if (typeof bridge.ReadAllBytesBase64Async === "function") {
1670
- const content3 = await taskToPromise(bridge.ReadAllBytesBase64Async(normalizedPath));
1671
- return String(content3 ?? "");
1673
+ const content2 = await taskToPromise(bridge.ReadAllBytesBase64Async(normalizedPath));
1674
+ if (typeof content2 === "string" && looksLikeBase64(content2)) {
1675
+ return content2;
1676
+ }
1677
+ console.warn(
1678
+ `[pie] async base64 file bridge returned an empty/invalid result for '${path}'; falling back to a synchronous read.`
1679
+ );
1672
1680
  }
1673
- const content2 = CS.System.Convert.ToBase64String(IO.File.ReadAllBytes(normalizedPath));
1674
- return String(content2 ?? "");
1681
+ return this.readBinaryAsBase64Sync(normalizedPath);
1675
1682
  }
1676
1683
  const content = await taskToPromise(bridge.ReadAllTextAsync(normalizedPath));
1677
1684
  return String(content ?? "");
@@ -1683,10 +1690,18 @@ var PuerTSFileSystem = class {
1683
1690
  throw new Error(`ENOENT: no such file or directory, open '${path}'`);
1684
1691
  }
1685
1692
  if (encoding === "base64") {
1686
- return String(CS.System.Convert.ToBase64String(IO.File.ReadAllBytes(normalizedPath)) ?? "");
1693
+ return this.readBinaryAsBase64Sync(normalizedPath);
1687
1694
  }
1688
1695
  return IO.File.ReadAllText(normalizedPath);
1689
1696
  }
1697
+ readBinaryAsBase64Sync(normalizedPath) {
1698
+ const bridge = typeof CS !== "undefined" && CS?.Pie?.PieFileBridge ? CS.Pie.PieFileBridge : null;
1699
+ if (bridge && typeof bridge.ReadAllBytesBase64 === "function") {
1700
+ return String(bridge.ReadAllBytesBase64(normalizedPath) ?? "");
1701
+ }
1702
+ const IO = getSystemIO();
1703
+ return String(CS.System.Convert.ToBase64String(IO.File.ReadAllBytes(normalizedPath)) ?? "");
1704
+ }
1690
1705
  async readFilePrefix(path, maxBytes) {
1691
1706
  const IO = getSystemIO();
1692
1707
  const bridge = getPieFileBridge();
@@ -3074,11 +3089,17 @@ var FileSystemGateway = class {
3074
3089
  this.validatePath(destination, "copy");
3075
3090
  const platform = detectPlatform();
3076
3091
  const dir = this.dirname(destination);
3077
- this.mkdir(dir, { recursive: true });
3078
3092
  if (platform === "puerts" && typeof CS !== "undefined") {
3093
+ if (isPuertsReparsePoint(source) || isPuertsReparsePoint(destination) || containsPuertsReparsePoint(dir) || containsPuertsReparsePoint(this.dirname(source))) {
3094
+ throw new Error(
3095
+ `Refusing to copy through a reparse point (symlink/junction): '${source}' -> '${destination}'; resolve the link or copy inside it explicitly`
3096
+ );
3097
+ }
3098
+ this.mkdir(dir, { recursive: true });
3079
3099
  CS.System.IO.File.Copy(source, destination, true);
3080
3100
  return;
3081
3101
  }
3102
+ this.mkdir(dir, { recursive: true });
3082
3103
  const fs = nodeRequire("fs");
3083
3104
  fs.copyFileSync(source, destination);
3084
3105
  }
@@ -3093,14 +3114,30 @@ var FileSystemGateway = class {
3093
3114
  this.validatePath(destination, "rename");
3094
3115
  const platform = detectPlatform();
3095
3116
  const dir = this.dirname(destination);
3096
- this.mkdir(dir, { recursive: true });
3097
3117
  if (platform === "puerts" && typeof CS !== "undefined") {
3118
+ if (isPuertsReparsePoint(source) || isPuertsReparsePoint(destination) || containsPuertsReparsePoint(dir) || containsPuertsReparsePoint(this.dirname(source))) {
3119
+ throw new Error(
3120
+ `Refusing to rename through a reparse point (symlink/junction): '${source}' -> '${destination}'; resolve the link or move inside it explicitly`
3121
+ );
3122
+ }
3123
+ this.mkdir(dir, { recursive: true });
3124
+ if (!CS.System.IO.File.Exists(source)) {
3125
+ throw new Error(`File not found: ${source}`);
3126
+ }
3127
+ if (this.normalizePath(source) === this.normalizePath(destination)) {
3128
+ return;
3129
+ }
3098
3130
  if (CS.System.IO.File.Exists(destination)) {
3099
- CS.System.IO.File.Delete(destination);
3131
+ if (typeof CS.System.IO.File.Replace !== "function") {
3132
+ throw new Error("File.Replace is unavailable; refusing unsafe file replacement");
3133
+ }
3134
+ CS.System.IO.File.Replace(source, destination, null);
3135
+ return;
3100
3136
  }
3101
3137
  CS.System.IO.File.Move(source, destination);
3102
3138
  return;
3103
3139
  }
3140
+ this.mkdir(dir, { recursive: true });
3104
3141
  const fs = nodeRequire("fs");
3105
3142
  fs.renameSync(source, destination);
3106
3143
  }
@@ -3352,7 +3389,7 @@ function isPuertsReparsePoint(path) {
3352
3389
  warnedMissingPuertsGetAttributes = true;
3353
3390
  try {
3354
3391
  console.warn(
3355
- "[platform] File.GetAttributes is unbound on this host; directory symlink checks are disabled (move/delete follow links)"
3392
+ "[platform] File.GetAttributes is unbound on this host; directory symlink checks are disabled (move/delete/copy follow links)"
3356
3393
  );
3357
3394
  } catch {
3358
3395
  }
@@ -3369,6 +3406,42 @@ function isPuertsReparsePoint(path) {
3369
3406
  return false;
3370
3407
  }
3371
3408
  }
3409
+ function containsPuertsReparsePoint(directory) {
3410
+ const slashed = directory.replace(/\\/g, "/");
3411
+ const trimmed = slashed.replace(/\/+$/, "");
3412
+ if (!trimmed || trimmed === "/") return false;
3413
+ const unc = /^\/\/([^/]+)\/([^/]+)/.exec(trimmed);
3414
+ let prefix;
3415
+ let rest;
3416
+ if (unc) {
3417
+ prefix = unc[0];
3418
+ rest = trimmed.slice(prefix.length);
3419
+ } else {
3420
+ const driveRoot = /^([a-zA-Z]:)\//.exec(trimmed);
3421
+ if (driveRoot) {
3422
+ prefix = `${driveRoot[1]}/`;
3423
+ rest = trimmed.slice(prefix.length);
3424
+ } else {
3425
+ const bareDrive = /^[a-zA-Z]:$/.test(trimmed);
3426
+ if (bareDrive) {
3427
+ return isPuertsReparsePoint(trimmed);
3428
+ }
3429
+ if (trimmed.startsWith("/")) {
3430
+ prefix = "/";
3431
+ rest = trimmed.slice(1);
3432
+ } else {
3433
+ prefix = "";
3434
+ rest = trimmed;
3435
+ }
3436
+ }
3437
+ }
3438
+ let current = prefix;
3439
+ for (const part of rest.split("/").filter((segment) => segment.length > 0 && segment !== ".")) {
3440
+ current = current ? current.endsWith("/") ? `${current}${part}` : `${current}/${part}` : part;
3441
+ if (isPuertsReparsePoint(current)) return true;
3442
+ }
3443
+ return false;
3444
+ }
3372
3445
  var warnedPuertsDeletionShells = false;
3373
3446
  function warnPuertsDeletionShellsOnce(path) {
3374
3447
  if (warnedPuertsDeletionShells) return;
@@ -6056,6 +6129,13 @@ function nextLocalRequestId(prefix = "req") {
6056
6129
  localRequestCounter += 1;
6057
6130
  return `${prefix}-${localRequestCounter}-${Math.random().toString(36).slice(2, 8)}`;
6058
6131
  }
6132
+ function timeoutSuffix(budgetMs, lagMs) {
6133
+ const budget = budgetMs && budgetMs > 0 ? ` (budget ${Math.round(budgetMs / 1e3)}s)` : "";
6134
+ if (lagMs > 1e3) {
6135
+ return `${budget} \u2014 timer fired ${Math.round(lagMs / 1e3)}s late (system sleep or suspended process)`;
6136
+ }
6137
+ return budget;
6138
+ }
6059
6139
  function monotonicNow() {
6060
6140
  const perf = globalThis.performance;
6061
6141
  return typeof perf?.now === "function" ? perf.now() : Date.now();
@@ -6343,7 +6423,9 @@ function streamResponsesSSE(model, context, options) {
6343
6423
  internalTimeout = adapterTimeoutKind === "first_byte" ? "first_response" : "stream_idle";
6344
6424
  }
6345
6425
  const protocolFailure = !endedWithoutTerminal && (error instanceof ResponsesProtocolError || error instanceof SyntaxError || !transportLost && error instanceof TypeError);
6346
- message.errorMessage = providerErrorMessage ?? (internalTimeout && !protocolFailure ? `Responses request timeout (${internalTimeout}) after ${Math.round(monotonicNow() - startedAt)}ms` : error instanceof Error ? error.message : JSON.stringify(error));
6426
+ const adapterBudgetMs = internalTimeout === "first_response" ? budgets?.firstResponseTimeoutMs : internalTimeout === "stream_idle" ? budgets?.streamIdleTimeoutMs : void 0;
6427
+ const adapterAgeMs = Math.round(monotonicNow() - startedAt);
6428
+ message.errorMessage = providerErrorMessage ?? (internalTimeout && !protocolFailure ? `Responses request timeout (${internalTimeout}) after ${adapterAgeMs}ms${timeoutSuffix(adapterBudgetMs, 0)}` : error instanceof Error ? error.message : JSON.stringify(error));
6347
6429
  const compat = getResponsesCompat(model);
6348
6430
  const streamLost = (endedWithoutTerminal || transportLost) && !protocolFailure && !internalTimeout && submitted && !localFailure && !providerRejected && message.stopReason === "error";
6349
6431
  if (internalTimeout && !message.remoteFailure && !protocolFailure && submitted && !providerRejected && !localFailure && !userAborted && compat.timeoutReplay) {
@@ -6601,6 +6683,8 @@ function streamResponsesWS(model, context, options) {
6601
6683
  let terminalEvents = [];
6602
6684
  let fallback = false;
6603
6685
  let timedOut;
6686
+ let timedOutBudgetMs;
6687
+ let timedOutLagMs;
6604
6688
  let providerRejected = false;
6605
6689
  let localFailure = true;
6606
6690
  let transportLost = false;
@@ -6715,17 +6799,25 @@ function streamResponsesWS(model, context, options) {
6715
6799
  if (timer !== void 0) clearTimeout(timer);
6716
6800
  }
6717
6801
  };
6802
+ let phaseTimerInfo;
6718
6803
  const armPhaseTimer = (kind, timeoutMs) => {
6719
6804
  if (requestTimer !== void 0) {
6720
6805
  clearTimeout(requestTimer);
6721
6806
  requestTimer = void 0;
6722
6807
  }
6723
- if (timeoutMs === void 0 || timeoutMs <= 0 || finished) return;
6808
+ if (timeoutMs === void 0 || timeoutMs <= 0 || finished) {
6809
+ phaseTimerInfo = void 0;
6810
+ return;
6811
+ }
6724
6812
  const generation = requestGeneration;
6813
+ phaseTimerInfo = { kind, budgetMs: timeoutMs, armedAt: monotonicNow() };
6725
6814
  requestTimer = setTimeout(() => {
6726
6815
  requestTimer = void 0;
6727
6816
  if (generation !== requestGeneration || finished || requestAbort.signal.aborted) return;
6817
+ const info = phaseTimerInfo;
6728
6818
  timedOut = kind;
6819
+ timedOutBudgetMs = info?.budgetMs;
6820
+ timedOutLagMs = info ? Math.max(0, monotonicNow() - info.armedAt - info.budgetMs) : 0;
6729
6821
  retryDecision = sent ? "not_retryable_after_submission" : "not_submitted";
6730
6822
  lifecycle("timeout", {
6731
6823
  timeoutKind: kind,
@@ -6916,7 +7008,7 @@ function streamResponsesWS(model, context, options) {
6916
7008
  armPhaseTimer("stream_idle", budgets.streamIdleTimeoutMs);
6917
7009
  if (receivedMessageCount === 1) lifecycle("first_application_message");
6918
7010
  if (state.abort.signal.aborted || requestAbort.signal.aborted) {
6919
- throw new Error(timedOut ? `Responses request timeout (${timedOut})` : "Request aborted");
7011
+ throw new Error(timedOut ? `Responses request timeout (${timedOut})${timeoutSuffix(timedOutBudgetMs, timedOutLagMs ?? 0)}` : "Request aborted");
6920
7012
  }
6921
7013
  let events;
6922
7014
  try {
@@ -7000,7 +7092,7 @@ function streamResponsesWS(model, context, options) {
7000
7092
  message.stopReason = userAborted || ownerDisposed ? "aborted" : "error";
7001
7093
  if (userAborted || ownerDisposed) delete message.remoteFailure;
7002
7094
  const protocolFailure = !endedWithoutTerminal && (error instanceof ResponsesProtocolError || error instanceof SyntaxError || !transportLost && error instanceof TypeError || error instanceof WebSocketTransportError && (error.kind === "protocol" || error.kind === "overflow"));
7003
- 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);
7095
+ const cause = providerRejected && error instanceof WebSocketTransportError ? `${error.message} (HTTP status ${error.status})` : timedOut && !protocolFailure ? `Responses request timeout (${timedOut}) after ${ageMs()}ms${timeoutSuffix(timedOutBudgetMs, timedOutLagMs ?? 0)}` : error instanceof Error ? error.message : String(error);
7004
7096
  message.errorMessage = cause;
7005
7097
  const streamLost = (endedWithoutTerminal || transportLost) && !protocolFailure && !localFailure && sent && !timedOut && !providerRejected && message.stopReason === "error";
7006
7098
  if (timedOut && timedOut !== "connect" && !message.remoteFailure && !protocolFailure && !localFailure && sent && !providerRejected && !userAborted && !ownerDisposed && compat.timeoutReplay) {
@@ -7,10 +7,12 @@ import {
7
7
  defaultShellKindForPlatform,
8
8
  interpretShellExit,
9
9
  requestInteraction
10
- } from "./chunk-C4LXD56O.js";
10
+ } from "./chunk-AFPRX5XI.js";
11
11
  import {
12
+ EMPTY_ASSISTANT_CONTENT_ERROR,
13
+ OPENAI_COMPAT_PROTOCOL_ERROR_CODE,
12
14
  getLogger
13
- } from "./chunk-2B6VS2NH.js";
15
+ } from "./chunk-EN47TIBG.js";
14
16
  import {
15
17
  Type
16
18
  } from "./chunk-XXGYUYXI.js";
@@ -128,6 +130,153 @@ function migrateConfigFromAgentDir() {
128
130
  }
129
131
  }
130
132
 
133
+ // src/runtime/retry-policy.ts
134
+ var TRANSIENT_NETWORK_ERROR_PATTERN = /sse stream aborted|sse stream closed before end|sse stream ended before response completed|responses stream ended without a terminal event|(?:read\s+)?ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|(?:read\s+|write\s+)?EPIPE|socket hang up|request timeout|websocket upgrade refused|websocket handshake|websocket connection failed|websocket transport failed|connection closed before opening|client network socket disconnected before secure TLS connection was established|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i;
135
+ var TLS_VALIDATION_ERROR_PATTERN = /certificate (?:has )?expired|certificate is not yet valid|unable to verify (?:the first certificate|certificate)|unable to get (?:local )?issuer certificate|self[-_ ]signed cert(?:ificate)?|CERT_HAS_EXPIRED|SELF_SIGNED_CERT|does not match certificate's altnames|ERR_TLS_CERT_ALTNAME_INVALID/i;
136
+ var PROVIDER_TRANSIENT_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|\b429\b|\b500\b|\b502\b|\b503\b|\b504\b|service.?unavailable|server error|internal error|retry delay|quota (?:has been |is )?exhausted/i;
137
+ var USER_ABORT_PATTERN = /request was aborted|local abort signal|user abort|user_interrupt|interrupted by user|esc pressed|ctrl\+c/i;
138
+ var AUTH_CONFIG_PATTERN = /missing api key|invalid api key|api key.*invalid|unauthorized|\b401\b|\b403\b|forbidden|authentication failed|no configured model|no models? are configured/i;
139
+ var QUOTA_EXHAUSTED_PATTERN = /insufficient[_ ]quota|exceeded[_ ]current[_ ]quota|exceeded your current quota|billing[_ ]hard[_ ]limit|insufficient[_ ]balance|credit balance is too low|\barrearage\b|余额不足|\b(?:account|monthly|billing) quota (?:has been |is )?exhausted/i;
140
+ var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this file|invalid_authentication_error/i;
141
+ var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
142
+ var CLI_RETRY_MAX_RETRIES = 3;
143
+ var CLI_RETRY_BASE_DELAY_MS = 2e3;
144
+ var CLI_TRANSIENT_NETWORK_MAX_RETRIES = 10;
145
+ var CLI_RETRY_TOTAL_MAX_RETRIES = 12;
146
+ var CLI_RETRY_MAX_DELAY_MS = 6e4;
147
+ function isCliContextOverflowError(errorMessage) {
148
+ return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
149
+ errorMessage
150
+ );
151
+ }
152
+ function createClassification(kind, message, overrides) {
153
+ return {
154
+ kind,
155
+ message,
156
+ retryable: false,
157
+ compactable: false,
158
+ userAbort: false,
159
+ terminal: true,
160
+ ...overrides
161
+ };
162
+ }
163
+ function classifyCliFailure(context) {
164
+ const errorMessage = typeof context === "string" ? context : context.errorMessage;
165
+ const structuredReplayClass = typeof context === "string" ? void 0 : context.message?.role === "assistant" ? context.message.replayClass : void 0;
166
+ if (isCliContextOverflowError(errorMessage)) {
167
+ return createClassification("context_overflow", errorMessage, {
168
+ compactable: true,
169
+ terminal: false
170
+ });
171
+ }
172
+ if (USER_ABORT_PATTERN.test(errorMessage)) {
173
+ return createClassification("user_abort", errorMessage, {
174
+ userAbort: true,
175
+ terminal: false
176
+ });
177
+ }
178
+ if (INVALID_FILE_REFERENCE_PATTERN.test(errorMessage)) {
179
+ return createClassification("invalid_file_reference", errorMessage);
180
+ }
181
+ if (AUTH_CONFIG_PATTERN.test(errorMessage) || QUOTA_EXHAUSTED_PATTERN.test(errorMessage)) {
182
+ return createClassification("auth_config", errorMessage);
183
+ }
184
+ if (TLS_VALIDATION_ERROR_PATTERN.test(errorMessage)) {
185
+ return createClassification("tls_config", errorMessage, {
186
+ retryable: true,
187
+ terminal: false
188
+ });
189
+ }
190
+ if (structuredReplayClass === "stream_lost" || structuredReplayClass === "stream_lost_partial" || TRANSIENT_NETWORK_ERROR_PATTERN.test(errorMessage)) {
191
+ return createClassification("transient_network", errorMessage, {
192
+ retryable: true,
193
+ terminal: false
194
+ });
195
+ }
196
+ if (errorMessage.includes(EMPTY_ASSISTANT_CONTENT_ERROR)) {
197
+ return createClassification("provider_transient", errorMessage, {
198
+ retryable: true,
199
+ terminal: false
200
+ });
201
+ }
202
+ if (errorMessage.includes(OPENAI_COMPAT_PROTOCOL_ERROR_CODE)) {
203
+ return createClassification("provider_transient", errorMessage, {
204
+ retryable: true,
205
+ terminal: false
206
+ });
207
+ }
208
+ if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(errorMessage)) {
209
+ return createClassification("provider_transient", errorMessage, {
210
+ retryable: true,
211
+ terminal: false
212
+ });
213
+ }
214
+ if (INVALID_REQUEST_PATTERN.test(errorMessage)) {
215
+ return createClassification("invalid_request", errorMessage);
216
+ }
217
+ return createClassification("unknown", errorMessage);
218
+ }
219
+ function isCliRetryableError(errorMessage) {
220
+ return classifyCliFailure(errorMessage).retryable;
221
+ }
222
+ function getCliRetryBaseDelayMs() {
223
+ const override = process.env.PIE_TEST_CLI_RETRY_BASE_DELAY_MS;
224
+ if (!override) {
225
+ return CLI_RETRY_BASE_DELAY_MS;
226
+ }
227
+ const parsed = Number(override);
228
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_BASE_DELAY_MS;
229
+ }
230
+ function getCliTransientNetworkMaxRetries() {
231
+ const override = process.env.PIE_RETRY_TRANSIENT_NETWORK_MAX_RETRIES;
232
+ if (!override) {
233
+ return CLI_TRANSIENT_NETWORK_MAX_RETRIES;
234
+ }
235
+ const parsed = Number(override);
236
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : CLI_TRANSIENT_NETWORK_MAX_RETRIES;
237
+ }
238
+ function getCliRetryMaxDelayMs() {
239
+ const override = process.env.PIE_RETRY_MAX_DELAY_MS;
240
+ if (!override) {
241
+ return CLI_RETRY_MAX_DELAY_MS;
242
+ }
243
+ const parsed = Number(override);
244
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_MAX_DELAY_MS;
245
+ }
246
+ function getCliRetryTotalMaxRetries() {
247
+ const override = process.env.PIE_RETRY_TOTAL_MAX_RETRIES;
248
+ if (!override) {
249
+ return CLI_RETRY_TOTAL_MAX_RETRIES;
250
+ }
251
+ const parsed = Number(override);
252
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : CLI_RETRY_TOTAL_MAX_RETRIES;
253
+ }
254
+ function createCliRetryPolicy(isRetryableErrorOverride) {
255
+ return {
256
+ isRetryableError: isRetryableErrorOverride ?? isCliRetryableError,
257
+ maxRetries: CLI_RETRY_MAX_RETRIES,
258
+ baseDelayMs: getCliRetryBaseDelayMs(),
259
+ maxDelayMs: getCliRetryMaxDelayMs(),
260
+ maxRetriesForFailure: (failure) => failure.kind === "transient_network" ? getCliTransientNetworkMaxRetries() : failure.replayExempt === true ? getCliTimeoutReplayMaxRetries() : CLI_RETRY_MAX_RETRIES,
261
+ maxTotalRetries: getCliRetryTotalMaxRetries(),
262
+ systemicReplayStallLimit: getCliSystemicReplayStallLimit()
263
+ };
264
+ }
265
+ var CLI_TIMEOUT_REPLAY_MAX_RETRIES = 5;
266
+ function getCliTimeoutReplayMaxRetries() {
267
+ const override = process.env.PIE_TIMEOUT_REPLAY_MAX_RETRIES;
268
+ if (!override) return CLI_TIMEOUT_REPLAY_MAX_RETRIES;
269
+ const parsed = Number(override);
270
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : CLI_TIMEOUT_REPLAY_MAX_RETRIES;
271
+ }
272
+ var CLI_SYSTEMIC_REPLAY_STALL_LIMIT = 3;
273
+ function getCliSystemicReplayStallLimit() {
274
+ const override = process.env.PIE_SYSTEMIC_REPLAY_STALL_LIMIT;
275
+ if (!override) return CLI_SYSTEMIC_REPLAY_STALL_LIMIT;
276
+ const parsed = Number(override);
277
+ return Number.isFinite(parsed) && parsed >= 1 ? Math.floor(parsed) : CLI_SYSTEMIC_REPLAY_STALL_LIMIT;
278
+ }
279
+
131
280
  // src/runtime/transport-diagnostics.ts
132
281
  function numberOrDash(value) {
133
282
  return typeof value === "number" ? String(value) : "-";
@@ -687,10 +836,28 @@ async function requestHighRiskConfirmation(request) {
687
836
  "",
688
837
  request.command
689
838
  ].join("\n"),
690
- timeoutMs: 12e4
839
+ timeoutMs: 12e4,
840
+ // An entry labeled Yolo (e.g. "Yolo (5 min)") is a time-boxed YOLO
841
+ // grant: hosts that understand it answer with yoloGrantMs so subsequent
842
+ // confirmations are bypassed for that window; hosts without support
843
+ // render the labels as plain options and a selection still confirms
844
+ // this one command.
845
+ options: ["Yes", "No", "Yolo (5 min)"]
691
846
  });
847
+ const yoloGrantMs = response.type === "confirm" ? response.yoloGrantMs : void 0;
848
+ if (yoloGrantMs && yoloGrantMs > 0) notifyYoloGrantAwarded(yoloGrantMs);
692
849
  return response.type === "confirm" && response.confirmed === true;
693
850
  }
851
+ var yoloGrantListener;
852
+ function setYoloGrantListener(listener) {
853
+ yoloGrantListener = listener;
854
+ }
855
+ function notifyYoloGrantAwarded(grantMs) {
856
+ try {
857
+ yoloGrantListener?.(grantMs);
858
+ } catch {
859
+ }
860
+ }
694
861
  function validateWorkingDirectory(cwd) {
695
862
  if (!existsSync2(cwd)) {
696
863
  throw new Error(`Invalid bash cwd: ${cwd} does not exist. Use the current workspace path or pass an existing directory in cwd.`);
@@ -1600,8 +1767,14 @@ export {
1600
1767
  createCliWebResearchHealthStore,
1601
1768
  truncateHeadTail,
1602
1769
  formatSize,
1770
+ setYoloGrantListener,
1603
1771
  cleanupBashOutputArtifacts,
1604
1772
  createBashTool,
1773
+ CLI_RETRY_MAX_RETRIES,
1774
+ isCliContextOverflowError,
1775
+ classifyCliFailure,
1776
+ isCliRetryableError,
1777
+ createCliRetryPolicy,
1605
1778
  formatTransportLifecycle,
1606
1779
  createTransportDiagnosticsStreamFn,
1607
1780
  logTransportLifecycle,
@@ -6,8 +6,8 @@ import {
6
6
  bindToolCallerIdentity,
7
7
  createToolCallerIdentity,
8
8
  getToolCallerIdentity
9
- } from "./chunk-JO6EDWHP.js";
10
- import "./chunk-2B6VS2NH.js";
9
+ } from "./chunk-2NBUFVUQ.js";
10
+ import "./chunk-EN47TIBG.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-2B6VS2NH.js";
4
+ } from "./chunk-EN47TIBG.js";
5
5
  import "./chunk-XXGYUYXI.js";
6
6
  import "./chunk-LZQXQOPJ.js";
7
7