@cydm/pie 2.7.1 → 2.7.3

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.
@@ -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-NJFPBU36.js";
5
+ } from "./chunk-MPTME6HX.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-XUROMYTT.js";
15
+ } from "./chunk-E5JQ5SVA.js";
16
16
  import {
17
17
  Type
18
18
  } from "./chunk-XXGYUYXI.js";
@@ -978,6 +978,39 @@ var SIMPLE_READ_COMMANDS = /* @__PURE__ */ new Set(["pwd", "ls", "cat", "head",
978
978
  var GIT_READ_SUBCOMMANDS = /* @__PURE__ */ new Set(["status", "log", "diff", "show", "rev-parse", "ls-files", "ls-tree", "blame", "describe", "shortlog", "merge-base"]);
979
979
  var UNSAFE_GIT_FLAGS = /^(?:-c|--config-env|--exec|--output|--ext-diff|--textconv)(?:=|$)/;
980
980
  var UNSAFE_RG_FLAGS = /^(?:--pre|--pre-glob)(?:=|$)/;
981
+ function longOptionUnsafe(arg, dangerous, benign) {
982
+ const name = arg.slice(2).split("=", 1)[0];
983
+ if (!name) return true;
984
+ if (dangerous.some((option) => option.startsWith(name))) return true;
985
+ return !benign.some((option) => option.startsWith(name));
986
+ }
987
+ function isReadOnlyUniq(args) {
988
+ let operands = 0;
989
+ let endOptions = false;
990
+ for (let i = 0; i < args.length; i++) {
991
+ const arg = args[i];
992
+ if (!endOptions && arg === "--") {
993
+ endOptions = true;
994
+ continue;
995
+ }
996
+ if (!endOptions && arg.startsWith("--")) {
997
+ if (/^--(?:skip-fields|skip-chars|check-chars)(?:=\d+)?$/.test(arg)) {
998
+ if (!arg.includes("=") && !/^\d+$/.test(args[++i] ?? "")) return false;
999
+ } else if (longOptionUnsafe(arg, [], ["count", "repeated", "unique", "all-repeated", "group", "ignore-case", "zero-terminated", "help", "version"])) {
1000
+ return false;
1001
+ }
1002
+ continue;
1003
+ }
1004
+ if (!endOptions && arg.startsWith("-") && arg !== "-") {
1005
+ const match2 = /^-[cdDuiz]*(?:([fsw])(\d*))?$/.exec(arg);
1006
+ if (!match2) return false;
1007
+ if (match2[1] && !match2[2] && !/^\d+$/.test(args[++i] ?? "")) return false;
1008
+ continue;
1009
+ }
1010
+ if (++operands > 1) return false;
1011
+ }
1012
+ return true;
1013
+ }
981
1014
  function isReadOnlySegment(words) {
982
1015
  if (words.length === 0) return false;
983
1016
  const [program, ...args] = words;
@@ -991,11 +1024,72 @@ function isReadOnlySegment(words) {
991
1024
  return !args.some((arg) => /^-(?:exec|execdir|ok|okdir|delete|fprint|fls|fprintf)/.test(arg));
992
1025
  }
993
1026
  if (program === "tree") {
994
- return !args.some((arg) => /^-o./.test(arg) || arg === "-o" || arg === "--output" || arg.startsWith("--output="));
1027
+ return !args.some((arg) => /^-[^-]*o/.test(arg) || arg.startsWith("--") && arg !== "--" && longOptionUnsafe(arg, ["output"], [
1028
+ "ascii",
1029
+ "charset",
1030
+ "color",
1031
+ "dirsfirst",
1032
+ "du",
1033
+ "filelimit",
1034
+ "hardlinks",
1035
+ "help",
1036
+ "ignore-case",
1037
+ "inode",
1038
+ "links",
1039
+ "metafirst",
1040
+ "noreport",
1041
+ "nolinks",
1042
+ "outdent",
1043
+ "quote",
1044
+ "sort",
1045
+ "timefmt",
1046
+ "version",
1047
+ "pattern",
1048
+ "matchdirs",
1049
+ "prune"
1050
+ ]));
995
1051
  }
996
1052
  if (program === "sort") {
997
- return !args.some((arg) => /^-o./.test(arg) || arg === "-o" || arg === "--output" || arg.startsWith("--output=") || arg === "--compress-program" || arg.startsWith("--compress-program="));
1053
+ return !args.some((arg) => {
1054
+ if (arg === "--") return false;
1055
+ if (arg.startsWith("--")) {
1056
+ return longOptionUnsafe(arg, ["output", "compress-program"], [
1057
+ "numeric-sort",
1058
+ "general-numeric-sort",
1059
+ "human-numeric-sort",
1060
+ "month-sort",
1061
+ "version-sort",
1062
+ "random-sort",
1063
+ "random-source",
1064
+ "reverse",
1065
+ "unique",
1066
+ "check",
1067
+ "check-silent",
1068
+ "ignore-case",
1069
+ "ignore-leading-blanks",
1070
+ "ignore-nonprinting",
1071
+ "ignore-blanks",
1072
+ "dictionary-order",
1073
+ "merge",
1074
+ "stable",
1075
+ "batch-size",
1076
+ "buffer-size",
1077
+ "pipe-size",
1078
+ "parallel",
1079
+ "temporary-directory",
1080
+ "field-separator",
1081
+ "zero-terminated",
1082
+ "help",
1083
+ "version",
1084
+ "debug",
1085
+ "sort"
1086
+ ]);
1087
+ }
1088
+ if (arg.startsWith("-") && arg !== "-") return arg.slice(1).includes("o");
1089
+ return false;
1090
+ });
998
1091
  }
1092
+ if (program === "uniq") return isReadOnlyUniq(args);
999
1093
  if (program === "date") {
1000
1094
  return args.every((arg) => arg.startsWith("-") || arg.startsWith("+"));
1001
1095
  }
@@ -1059,6 +1153,7 @@ ${inlineMatch[1]}`;
1059
1153
  function isPlanModeSafeCommand(command) {
1060
1154
  const trimmed = command.trim();
1061
1155
  if (!trimmed || /[$`\n\r\0]/.test(trimmed)) return false;
1156
+ if (/\{[^{}]*\}/.test(trimmed) || /\{\s*,/.test(trimmed)) return false;
1062
1157
  let tokens;
1063
1158
  try {
1064
1159
  tokens = (0, import_shell_quote.parse)(trimmed);
@@ -3191,7 +3286,11 @@ function isTransientCompactionFailure(error) {
3191
3286
  if (record?.name === "AbortError" || /request was aborted|local abort signal|user abort|user_interrupt|interrupted by user|esc pressed|ctrl\+c|\bcancel(?:led|ed)\b|insufficient[_ ]quota|exceeded[_ ]current[_ ]quota|exceeded your current quota|insufficient[_ ]balance|credit balance is too low|\barrearage\b|余额不足|\b(?:account|monthly|billing) quota (?:has been |is )?exhausted|billing|invalid api key|unauthorized|forbidden/i.test(text)) return false;
3192
3287
  const status = record?.status ?? record?.statusCode;
3193
3288
  if (status !== void 0) return status === 429 || status >= 500 && status <= 599;
3194
- return /\b(?:429|5\d\d|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|EPIPE)\b|fetch failed|network error|request timeout|socket hang up|connection error|sse stream (?:aborted|closed before end|ended before response completed)|rate.?limit|too many requests|overloaded|service unavailable/i.test(text);
3289
+ return /\b(?:429|5\d\d|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|EPIPE)\b|fetch failed|network error|request timeout|socket hang up|connection error|sse stream (?:aborted|closed before end|ended before response completed)|responses stream ended without a terminal event|rate.?limit|too many requests|overloaded|service unavailable/i.test(text);
3290
+ }
3291
+ function explicitlyNonRetryable(error) {
3292
+ if (Boolean(error && typeof error === "object" && error.replayEligible === true)) return false;
3293
+ return Boolean(error && typeof error === "object" && error.retryable === false);
3195
3294
  }
3196
3295
  function waitForCompactionRetry(delayMs, signal) {
3197
3296
  return new Promise((resolve2, reject) => {
@@ -3245,11 +3344,15 @@ Return a text-only successor handoff. Do not call any tools.` }],
3245
3344
  ).result();
3246
3345
  throwIfAborted();
3247
3346
  if (response.stopReason === "error" && !response.content.some((block) => block.type === "toolCall")) {
3248
- throw new Error(response.errorMessage || "Compaction provider error");
3347
+ const providerError = new Error(response.errorMessage || "Compaction provider error");
3348
+ const explicitRetryable = response.retryable;
3349
+ if (typeof explicitRetryable === "boolean") providerError.retryable = explicitRetryable;
3350
+ if (response.replayEligible === true) providerError.replayEligible = true;
3351
+ throw providerError;
3249
3352
  }
3250
3353
  } catch (error) {
3251
3354
  throwIfAborted();
3252
- if (attempt >= 2 || !isTransientCompactionFailure(error)) throw error;
3355
+ if (attempt >= 2 || explicitlyNonRetryable(error) || !isTransientCompactionFailure(error)) throw error;
3253
3356
  await waitForCompactionRetry(250 * 2 ** attempt, signal);
3254
3357
  continue;
3255
3358
  }
@@ -3680,6 +3783,10 @@ var LruCache = class {
3680
3783
  weigh;
3681
3784
  maxWeight;
3682
3785
  map = /* @__PURE__ */ new Map();
3786
+ total = 0;
3787
+ weightOf(value) {
3788
+ return this.weigh ? this.weigh(value) : 1;
3789
+ }
3683
3790
  get(key) {
3684
3791
  const value = this.map.get(key);
3685
3792
  if (value !== void 0) {
@@ -3690,34 +3797,36 @@ var LruCache = class {
3690
3797
  }
3691
3798
  /** Insert a value, evicting until the entry and total weight fit. */
3692
3799
  set(key, value) {
3693
- this.map.delete(key);
3694
- const weight = this.weigh ? this.weigh(value) : 1;
3800
+ const existing = this.map.get(key);
3801
+ if (existing !== void 0) {
3802
+ this.total -= this.weightOf(existing);
3803
+ this.map.delete(key);
3804
+ }
3805
+ const weight = this.weightOf(value);
3695
3806
  if (weight > this.maxWeight) {
3696
3807
  return;
3697
3808
  }
3698
- let total = this.totalWeight() + weight;
3699
- while ((this.map.size >= this.limit || total > this.maxWeight) && this.map.size > 0) {
3809
+ this.total += weight;
3810
+ while ((this.map.size >= this.limit || this.total > this.maxWeight) && this.map.size > 0) {
3700
3811
  const oldest = this.map.keys().next().value;
3701
- const evicted = this.map.get(oldest);
3702
- total -= this.weigh ? this.weigh(evicted) : 1;
3812
+ this.total -= this.weightOf(this.map.get(oldest));
3703
3813
  this.map.delete(oldest);
3704
3814
  }
3705
3815
  this.map.set(key, value);
3706
3816
  }
3707
3817
  delete(key) {
3708
- this.map.delete(key);
3818
+ const existing = this.map.get(key);
3819
+ if (existing !== void 0) {
3820
+ this.total -= this.weightOf(existing);
3821
+ this.map.delete(key);
3822
+ }
3709
3823
  }
3710
3824
  clear() {
3711
3825
  this.map.clear();
3826
+ this.total = 0;
3712
3827
  }
3713
3828
  get weight() {
3714
- return this.totalWeight();
3715
- }
3716
- totalWeight() {
3717
- if (!this.weigh) return this.map.size;
3718
- let total = 0;
3719
- for (const value of this.map.values()) total += this.weigh(value);
3720
- return total;
3829
+ return this.total;
3721
3830
  }
3722
3831
  };
3723
3832
  function isRecord(value) {
@@ -6855,6 +6964,17 @@ function isAssistantTerminalCompletion(message) {
6855
6964
  }
6856
6965
  function createFailureClassification(context, retry, classifyFailure) {
6857
6966
  if (context.message?.role === "assistant" && context.message.retryable === false) {
6967
+ if (context.message.replayEligible === true) {
6968
+ return {
6969
+ kind: "provider_transient",
6970
+ retryable: true,
6971
+ compactable: false,
6972
+ userAbort: context.message.stopReason === "aborted",
6973
+ terminal: false,
6974
+ message: context.errorMessage,
6975
+ replayExempt: true
6976
+ };
6977
+ }
6858
6978
  return { kind: "unknown", retryable: false, compactable: false, userAbort: context.message.stopReason === "aborted", terminal: true, message: context.errorMessage };
6859
6979
  }
6860
6980
  const hostClassification = classifyFailure?.(context);
@@ -6873,13 +6993,7 @@ function createFailureClassification(context, retry, classifyFailure) {
6873
6993
  };
6874
6994
  }
6875
6995
  function asTerminalFailure(failure, message = failure.message) {
6876
- return {
6877
- ...failure,
6878
- retryable: false,
6879
- compactable: false,
6880
- terminal: true,
6881
- message
6882
- };
6996
+ return { ...failure, retryable: false, compactable: false, terminal: true, message };
6883
6997
  }
6884
6998
  function emitTurnEndPolicyFailure(emit, error) {
6885
6999
  const message = error instanceof Error ? error.message : String(error);
@@ -6907,6 +7021,36 @@ function handleTurnEndPolicyThrow(emit, error, context) {
6907
7021
  emit({ type: "turn_policy_error", message: `Turn-end policy failed after settle: ${message}` });
6908
7022
  }
6909
7023
 
7024
+ // ../../packages/agent-framework/src/session/controller/replay-stall-circuit.ts
7025
+ var ReplayStallCircuit = class {
7026
+ constructor(limit) {
7027
+ this.limit = limit;
7028
+ }
7029
+ limit;
7030
+ consecutiveStalls = 0;
7031
+ open = false;
7032
+ get isOpen() {
7033
+ return this.open;
7034
+ }
7035
+ get consecutiveTurnStalls() {
7036
+ return this.consecutiveStalls;
7037
+ }
7038
+ /** A replay-exempt retry budget was exhausted for this turn. */
7039
+ recordReplayExhaustion() {
7040
+ this.consecutiveStalls += 1;
7041
+ if (this.limit !== void 0 && this.consecutiveStalls >= this.limit && !this.open) {
7042
+ this.open = true;
7043
+ return { opened: true, consecutive: this.consecutiveStalls };
7044
+ }
7045
+ return { opened: false, consecutive: this.consecutiveStalls };
7046
+ }
7047
+ /** A turn succeeded, or failed in a way the endpoint actively answered. */
7048
+ recordHealthyTurn() {
7049
+ this.consecutiveStalls = 0;
7050
+ this.open = false;
7051
+ }
7052
+ };
7053
+
6910
7054
  // ../../packages/agent-framework/src/session/controller/retry-policy.ts
6911
7055
  function defaultSetTimeout4(callback, delay) {
6912
7056
  return setTimeout(callback, delay);
@@ -6921,6 +7065,7 @@ var AgentSessionRetryController = class {
6921
7065
  this.removeTrailingAssistantError = removeTrailingAssistantError2;
6922
7066
  this.continueTurn = continueTurn;
6923
7067
  this.setRecoveryState = setRecoveryState;
7068
+ this.replayCircuit = new ReplayStallCircuit(retry?.systemicReplayStallLimit);
6924
7069
  }
6925
7070
  retry;
6926
7071
  emit;
@@ -6933,6 +7078,8 @@ var AgentSessionRetryController = class {
6933
7078
  retryAttempts = /* @__PURE__ */ new Map();
6934
7079
  /** Total attempts across kinds in this recovery episode, for reporting. */
6935
7080
  totalRetryAttempts = 0;
7081
+ /** L2 systemic-stall circuit (see replay-stall-circuit.ts). */
7082
+ replayCircuit;
6936
7083
  retryTimer;
6937
7084
  retryEpoch = 0;
6938
7085
  pendingRetry;
@@ -6946,12 +7093,17 @@ var AgentSessionRetryController = class {
6946
7093
  waitForRetry() {
6947
7094
  return this.pendingRetry ?? Promise.resolve();
6948
7095
  }
7096
+ /** L2 circuit: healthy turn (success or an actively-answered failure). */
7097
+ noteEndpointHealthy() {
7098
+ this.replayCircuit.recordHealthyTurn();
7099
+ }
6949
7100
  async handleTurnEnd(message, failure) {
6950
7101
  if (!this.retry || !message || message.role !== "assistant") {
6951
7102
  this.settleStrandedRetry(failure);
6952
7103
  return;
6953
7104
  }
6954
7105
  if (!failure) {
7106
+ this.noteEndpointHealthy();
6955
7107
  if (this.totalRetryAttempts > 0) {
6956
7108
  this.emit({ type: "retry_succeeded", attempts: this.totalRetryAttempts });
6957
7109
  this.emit({ type: "turn_retry_succeeded", attempts: this.totalRetryAttempts });
@@ -6962,6 +7114,9 @@ var AgentSessionRetryController = class {
6962
7114
  return;
6963
7115
  }
6964
7116
  if (!failure.retryable) {
7117
+ if (failure.kind !== "unknown" && failure.kind !== "internal_error") {
7118
+ this.noteEndpointHealthy();
7119
+ }
6965
7120
  if (this.totalRetryAttempts > 0) {
6966
7121
  this.resetAttempts();
6967
7122
  this.setRecoveryState("none");
@@ -6969,6 +7124,16 @@ var AgentSessionRetryController = class {
6969
7124
  }
6970
7125
  return;
6971
7126
  }
7127
+ if (failure.replayExempt === true && this.replayCircuit.isOpen) {
7128
+ const openFailure = asTerminalFailure(failure, `${failure.message} (replay circuit open: ${this.replayCircuit.consecutiveTurnStalls} consecutive turns ended by timeout-replay exhaustion)`);
7129
+ this.emit({ type: "retry_exhausted", errorMessage: openFailure.message, maxRetries: 0 });
7130
+ this.emit({ type: "turn_failed_terminal", failure: openFailure, message });
7131
+ this.emit({ type: "turn_settled" });
7132
+ this.resetAttempts();
7133
+ this.setRecoveryState("terminal");
7134
+ this.resolvePending();
7135
+ return;
7136
+ }
6972
7137
  const maxRetries = this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3;
6973
7138
  const kindAttempts = (this.retryAttempts.get(failure.kind) ?? 0) + 1;
6974
7139
  this.retryAttempts.set(failure.kind, kindAttempts);
@@ -6978,6 +7143,12 @@ var AgentSessionRetryController = class {
6978
7143
  const totalExhausted = totalBudget !== void 0 && this.totalRetryAttempts > totalBudget;
6979
7144
  if (kindExhausted || totalExhausted) {
6980
7145
  const terminalFailure = asTerminalFailure(failure);
7146
+ if (failure.replayExempt === true) {
7147
+ const outcome = this.replayCircuit.recordReplayExhaustion();
7148
+ if (outcome.opened) {
7149
+ this.emit({ type: "retry_exhausted", errorMessage: `systemic timeout-stall: ${outcome.consecutive} consecutive turns ended by timeout-replay exhaustion`, maxRetries: totalExhausted ? totalBudget : maxRetries });
7150
+ }
7151
+ }
6981
7152
  this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries: totalExhausted ? totalBudget : maxRetries });
6982
7153
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
6983
7154
  this.emit({ type: "turn_settled" });
@@ -7012,11 +7183,7 @@ var AgentSessionRetryController = class {
7012
7183
  if (epoch !== this.retryEpoch || pending !== this.pendingRetry) return;
7013
7184
  const errorMessage = error instanceof Error ? error.message : String(error);
7014
7185
  const terminalFailure = asTerminalFailure(failure, errorMessage);
7015
- this.emit({
7016
- type: "retry_exhausted",
7017
- errorMessage,
7018
- maxRetries
7019
- });
7186
+ this.emit({ type: "retry_exhausted", errorMessage, maxRetries });
7020
7187
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
7021
7188
  this.emit({ type: "turn_settled" });
7022
7189
  this.resetAttempts();
@@ -7071,9 +7238,7 @@ var AgentSessionRetryController = class {
7071
7238
  this.retryTimer = void 0;
7072
7239
  }
7073
7240
  ensurePending() {
7074
- if (this.pendingRetry) {
7075
- return;
7076
- }
7241
+ if (this.pendingRetry) return;
7077
7242
  this.pendingRetry = new Promise((resolve2) => {
7078
7243
  this.resolvePendingRetry = resolve2;
7079
7244
  });
@@ -4,7 +4,7 @@ import {
4
4
  disposeModelTransports,
5
5
  streamSimple,
6
6
  validateToolArguments
7
- } from "./chunk-XUROMYTT.js";
7
+ } from "./chunk-E5JQ5SVA.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-M44CWVDZ.js";
9
+ } from "./chunk-F3U2TYDT.js";
10
10
  import {
11
11
  getLogger
12
- } from "./chunk-XUROMYTT.js";
12
+ } from "./chunk-E5JQ5SVA.js";
13
13
  import {
14
14
  Type
15
15
  } from "./chunk-XXGYUYXI.js";
@@ -153,6 +153,7 @@ function formatTransportLifecycle(event) {
153
153
  if (event.terminalAccepted !== void 0) parts.push(`terminal=${event.terminalAccepted ? "yes" : "no"}`);
154
154
  if (event.retryAllowed !== void 0) parts.push(`retryAllowed=${event.retryAllowed ? "yes" : "no"}`);
155
155
  if (event.retryDecision) parts.push(`retryDecision=${event.retryDecision}`);
156
+ if (event.replayExempt === true) parts.push("replayExempt=yes");
156
157
  if (event.cancelSource) parts.push(`cancelSource=${event.cancelSource}`);
157
158
  if (event.cleanupOutcome) parts.push(`cleanup=${event.cleanupOutcome}`);
158
159
  if (event.singleAttempt) parts.push(`singleAttempt=${event.singleAttempt}`);
@@ -6,8 +6,8 @@ import {
6
6
  bindToolCallerIdentity,
7
7
  createToolCallerIdentity,
8
8
  getToolCallerIdentity
9
- } from "./chunk-NJFPBU36.js";
10
- import "./chunk-XUROMYTT.js";
9
+ } from "./chunk-MPTME6HX.js";
10
+ import "./chunk-E5JQ5SVA.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-XUROMYTT.js";
4
+ } from "./chunk-E5JQ5SVA.js";
5
5
  import "./chunk-XXGYUYXI.js";
6
6
  import "./chunk-LZQXQOPJ.js";
7
7