@cydm/pie 2.6.3 → 2.6.5

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-Y4CYXJR7.js";
5
+ } from "./chunk-AETQBDEG.js";
6
6
  import {
7
7
  FileSystemGateway,
8
8
  completeSimple,
@@ -11,7 +11,7 @@ import {
11
11
  getPlatformConfig,
12
12
  hashText,
13
13
  streamSimple
14
- } from "./chunk-O2DKMLNX.js";
14
+ } from "./chunk-5OXH6NUH.js";
15
15
  import {
16
16
  Type
17
17
  } from "./chunk-XXGYUYXI.js";
@@ -1595,13 +1595,16 @@ function inferUncertainty(text, signals) {
1595
1595
  if (signals.some((signal) => signal.type === "tool_error" || signal.type === "model_fallback")) {
1596
1596
  return "medium";
1597
1597
  }
1598
+ if (signals.some((signal) => signal.type === "no_text_report")) {
1599
+ return "medium";
1600
+ }
1598
1601
  if (signals.some((signal) => signal.type === "tool_success" || signal.type === "file_read" || signal.type === "command_run")) {
1599
1602
  return "low";
1600
1603
  }
1601
1604
  return "medium";
1602
1605
  }
1603
1606
  function isParentHandoffRequired(task) {
1604
- return task.mode === "edit" || task.needsParentWrite || task.status === "timeout" || task.status === "failed" || task.confidenceSignals.some((signal) => signal.type === "tool_error" || signal.type === "no_tool_use");
1607
+ return task.mode === "edit" || task.needsParentWrite || task.status === "timeout" || task.status === "failed" || task.confidenceSignals.some((signal) => signal.type === "tool_error" || signal.type === "no_tool_use" || signal.type === "no_text_report");
1605
1608
  }
1606
1609
  async function runSubagentWithProgress(deps, task, reportProgress, signal) {
1607
1610
  const startTime = Date.now();
@@ -1746,12 +1749,16 @@ ${formatSkillsForPrompt(deps.skills ?? [])}`;
1746
1749
  const lastAssistant = [...messages].reverse().find((m) => m?.role === "assistant");
1747
1750
  const terminalStopReason = lastAssistant?.stopReason;
1748
1751
  const terminalError = typeof lastAssistant?.errorMessage === "string" ? lastAssistant.errorMessage : void 0;
1749
- const collectedResponse = collectLastAssistantText(messages);
1750
- if (terminalStopReason === "error" || terminalStopReason === "aborted" || terminalError || !collectedResponse) {
1752
+ const collectedResponse = collectLastAssistantText(messages) || void 0;
1753
+ const streamInterrupted = terminalStopReason === "error" || terminalStopReason === "aborted" || terminalError || !collectedResponse && terminalStopReason !== "stop";
1754
+ if (streamInterrupted) {
1751
1755
  const detail = terminalError ? `: ${terminalError.slice(0, 200)}` : "";
1752
1756
  throw new Error(`Subagent stream interrupted (SSE stream aborted before the report was produced, stopReason=${terminalStopReason ?? "none"}${collectedResponse ? ", partial transcript discarded" : ", no text response"})${detail}`);
1753
1757
  }
1754
- let response = collectedResponse;
1758
+ let response = collectedResponse ?? "[No textual report: the subagent finished normally (stopReason=stop) but produced no text \u2014 every assistant message was tool calls only. Review the task's effects directly, or rerun it with an explicit instruction to summarize findings.]";
1759
+ if (!collectedResponse) {
1760
+ task.confidenceSignals.push({ type: "no_text_report", message: "subagent finished normally without any textual report" });
1761
+ }
1755
1762
  const outputTruncated = terminalStopReason === "length";
1756
1763
  if (outputTruncated) {
1757
1764
  task.confidenceSignals.push({ type: "output_truncated", message: "final response hit the provider's output token limit" });
@@ -3344,7 +3351,10 @@ var FileSessionStore = class {
3344
3351
  const previous = head.metadata;
3345
3352
  const merged = mergeMetadata(previous, {
3346
3353
  ...metadataPatch ?? {},
3347
- entryCount: previous.entryCount + newHeaders.length,
3354
+ // Self-heal drifted counters: seqs are dense, so the committed
3355
+ // frontier is also a lower bound on the entry count. A stale
3356
+ // entryCount (concurrent-writer lost update) must not persist.
3357
+ entryCount: Math.max(previous.entryCount + newHeaders.length, seq),
3348
3358
  messageCount: previous.messageCount + newHeaders.filter((header) => header.type === "message").length,
3349
3359
  rootEntryId: metadataPatch?.rootEntryId ?? previous.rootEntryId ?? newHeaders.find((header) => header.parentSeq === null)?.id ?? null,
3350
3360
  activeEntryId: activeEntryId ?? metadataPatch?.activeEntryId ?? newHeaders[newHeaders.length - 1]?.id ?? previous.activeEntryId
@@ -3419,7 +3429,12 @@ var FileSessionStore = class {
3419
3429
  return {
3420
3430
  summaries: collected.slice(0, limit).map(toSummary),
3421
3431
  hasMore: collected.length > limit,
3422
- total: head.metadata.entryCount
3432
+ // Sequence numbers are dense (one per committed entry), so
3433
+ // committedSeq is the authoritative entry count. metadata.entryCount
3434
+ // can drift behind it when concurrent writers race head manifests
3435
+ // (lost update), which would otherwise surface as ranges like
3436
+ // "seqs 1582-1621 of 1574" in paged UIs.
3437
+ total: Math.max(head.metadata.entryCount, head.committedSeq)
3423
3438
  };
3424
3439
  }
3425
3440
  getEntrySummary(sessionId, entryId) {
@@ -3477,6 +3492,7 @@ var FileSessionStore = class {
3477
3492
  }
3478
3493
  delete(sessionId) {
3479
3494
  const paths = this.pathsFor(sessionId);
3495
+ if (sessionDirIsSymlink(paths.dir)) return false;
3480
3496
  if (!this.gateway.exists(paths.dir)) return false;
3481
3497
  this.gateway.deleteDirectory(paths.dir, { recursive: true });
3482
3498
  this.dropCaches();
@@ -5693,7 +5709,12 @@ var AgentSessionRetryController = class {
5693
5709
  removeTrailingAssistantError;
5694
5710
  continueTurn;
5695
5711
  setRecoveryState;
5696
- retryAttempt = 0;
5712
+ /** Attempts consumed per failure KIND: budgets are granted per kind (a
5713
+ * 10-attempt network budget must not be eaten by interleaved provider
5714
+ * errors, and vice versa), so each kind counts its own attempts. */
5715
+ retryAttempts = /* @__PURE__ */ new Map();
5716
+ /** Total attempts across kinds in this recovery episode, for reporting. */
5717
+ totalRetryAttempts = 0;
5697
5718
  retryTimer;
5698
5719
  pendingRetry;
5699
5720
  resolvePendingRetry;
@@ -5712,36 +5733,41 @@ var AgentSessionRetryController = class {
5712
5733
  return;
5713
5734
  }
5714
5735
  if (!failure) {
5715
- if (this.retryAttempt > 0) {
5716
- this.emit({ type: "retry_succeeded", attempts: this.retryAttempt });
5717
- this.emit({ type: "turn_retry_succeeded", attempts: this.retryAttempt });
5718
- this.retryAttempt = 0;
5736
+ if (this.totalRetryAttempts > 0) {
5737
+ this.emit({ type: "retry_succeeded", attempts: this.totalRetryAttempts });
5738
+ this.emit({ type: "turn_retry_succeeded", attempts: this.totalRetryAttempts });
5739
+ this.resetAttempts();
5719
5740
  this.setRecoveryState("none");
5720
5741
  this.resolvePending();
5721
5742
  }
5722
5743
  return;
5723
5744
  }
5724
5745
  if (!failure.retryable) {
5725
- if (this.retryAttempt > 0) {
5726
- this.retryAttempt = 0;
5746
+ if (this.totalRetryAttempts > 0) {
5747
+ this.resetAttempts();
5727
5748
  this.setRecoveryState("none");
5728
5749
  this.resolvePending();
5729
5750
  }
5730
5751
  return;
5731
5752
  }
5732
5753
  const maxRetries = this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3;
5733
- this.retryAttempt += 1;
5734
- if (this.retryAttempt > maxRetries) {
5754
+ const kindAttempts = (this.retryAttempts.get(failure.kind) ?? 0) + 1;
5755
+ this.retryAttempts.set(failure.kind, kindAttempts);
5756
+ this.totalRetryAttempts += 1;
5757
+ const totalBudget = this.retry.maxTotalRetries;
5758
+ const kindExhausted = kindAttempts > maxRetries;
5759
+ const totalExhausted = totalBudget !== void 0 && this.totalRetryAttempts > totalBudget;
5760
+ if (kindExhausted || totalExhausted) {
5735
5761
  const terminalFailure = asTerminalFailure(failure);
5736
- this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries });
5762
+ this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries: totalExhausted ? totalBudget : maxRetries });
5737
5763
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
5738
5764
  this.emit({ type: "turn_settled" });
5739
- this.retryAttempt = 0;
5765
+ this.resetAttempts();
5740
5766
  this.setRecoveryState("terminal");
5741
5767
  this.resolvePending();
5742
5768
  return;
5743
5769
  }
5744
- const attempt = this.retryAttempt;
5770
+ const attempt = kindAttempts;
5745
5771
  const rawDelayMs = (this.retry.baseDelayMs ?? 2e3) * 2 ** (attempt - 1);
5746
5772
  const delayMs = this.retry.maxDelayMs !== void 0 ? Math.min(rawDelayMs, this.retry.maxDelayMs) : rawDelayMs;
5747
5773
  this.ensurePending();
@@ -5766,7 +5792,7 @@ var AgentSessionRetryController = class {
5766
5792
  });
5767
5793
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
5768
5794
  this.emit({ type: "turn_settled" });
5769
- this.retryAttempt = 0;
5795
+ this.resetAttempts();
5770
5796
  this.setRecoveryState("terminal");
5771
5797
  this.resolvePending();
5772
5798
  });
@@ -5795,15 +5821,19 @@ var AgentSessionRetryController = class {
5795
5821
  this.emit({ type: "retry_exhausted", errorMessage: terminalFailure.message, maxRetries });
5796
5822
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure });
5797
5823
  this.emit({ type: "turn_settled" });
5798
- this.retryAttempt = 0;
5824
+ this.resetAttempts();
5799
5825
  this.setRecoveryState("terminal");
5800
5826
  this.resolvePending();
5801
5827
  }
5802
5828
  cancel() {
5803
5829
  this.cancelTimerOnly();
5804
- this.retryAttempt = 0;
5830
+ this.resetAttempts();
5805
5831
  this.resolvePending();
5806
5832
  }
5833
+ resetAttempts() {
5834
+ this.retryAttempts.clear();
5835
+ this.totalRetryAttempts = 0;
5836
+ }
5807
5837
  cancelTimerOnly() {
5808
5838
  if (this.retryTimer === void 0) {
5809
5839
  return;
@@ -9288,10 +9318,28 @@ function isSpecialDevicePath(path4) {
9288
9318
  function detectUnderstandingKind(filePath) {
9289
9319
  const lower = filePath.toLowerCase();
9290
9320
  if (/\.(mp4|mov|m4v|webm|avi|mkv)$/.test(lower)) {
9291
- return { kind: "video", mimeType: lower.endsWith(".mov") ? "video/quicktime" : lower.endsWith(".webm") ? "video/webm" : "video/mp4" };
9321
+ const videoMime = {
9322
+ mp4: "video/mp4",
9323
+ mov: "video/quicktime",
9324
+ m4v: "video/x-m4v",
9325
+ webm: "video/webm",
9326
+ avi: "video/x-msvideo",
9327
+ mkv: "video/x-matroska"
9328
+ };
9329
+ const ext2 = lower.split(".").pop();
9330
+ return { kind: "video", mimeType: videoMime[ext2] ?? "video/mp4" };
9292
9331
  }
9293
9332
  if (/\.(mp3|wav|m4a|aac|flac|ogg)$/.test(lower)) {
9294
- return { kind: "audio", mimeType: lower.endsWith(".wav") ? "audio/wav" : lower.endsWith(".m4a") ? "audio/mp4" : "audio/mpeg" };
9333
+ const audioMime = {
9334
+ mp3: "audio/mpeg",
9335
+ wav: "audio/wav",
9336
+ m4a: "audio/mp4",
9337
+ aac: "audio/aac",
9338
+ flac: "audio/flac",
9339
+ ogg: "audio/ogg"
9340
+ };
9341
+ const ext2 = lower.split(".").pop();
9342
+ return { kind: "audio", mimeType: audioMime[ext2] ?? "audio/mpeg" };
9295
9343
  }
9296
9344
  if (/\.(pdf)$/.test(lower)) {
9297
9345
  return { kind: "document", mimeType: "application/pdf" };
@@ -13651,13 +13699,14 @@ Focus: ${request.question.trim()}` : ""}` },
13651
13699
  if (request.signal?.aborted) throw new Error("Operation aborted");
13652
13700
  const data = await fs2.readFile(request.absolutePath, "base64");
13653
13701
  if (request.signal?.aborted) throw new Error("Operation aborted");
13654
- if (data) return {
13702
+ const readBytes = Math.floor(data.length * 3 / 4) - (data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0);
13703
+ if (readBytes > 0 && readBytes <= cap && data) return {
13655
13704
  content: [
13656
13705
  { type: "text", text: `Read ${request.kind} file ${request.displayPath} [${request.mimeType}]. Original media attached for the current model.${request.question?.trim() ? `
13657
13706
  Focus: ${request.question.trim()}` : ""}` },
13658
13707
  { type: request.kind, data, mimeType: request.mimeType }
13659
13708
  ],
13660
- details: { understanding: { purpose, kind: request.kind, mimeType: request.mimeType, agentModel: getModelLabel(agentModel), routeSource: "current_model", inputMode: "nativeAttachment", attachmentBytes: size } },
13709
+ details: { understanding: { purpose, kind: request.kind, mimeType: request.mimeType, agentModel: getModelLabel(agentModel), routeSource: "current_model", inputMode: "nativeAttachment", attachmentBytes: readBytes } },
13661
13710
  isError: false
13662
13711
  };
13663
13712
  }
@@ -8,7 +8,7 @@ import {
8
8
  createSharedWebSearchTool,
9
9
  interpretShellExit,
10
10
  requestInteraction
11
- } from "./chunk-WG6E54WK.js";
11
+ } from "./chunk-QKSK5K5N.js";
12
12
  import {
13
13
  getBuiltinDir,
14
14
  getConfigDir
@@ -6,8 +6,8 @@ import {
6
6
  bindToolCallerIdentity,
7
7
  createToolCallerIdentity,
8
8
  getToolCallerIdentity
9
- } from "./chunk-Y4CYXJR7.js";
10
- import "./chunk-O2DKMLNX.js";
9
+ } from "./chunk-AETQBDEG.js";
10
+ import "./chunk-5OXH6NUH.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-O2DKMLNX.js";
4
+ } from "./chunk-5OXH6NUH.js";
5
5
  import "./chunk-XXGYUYXI.js";
6
6
  import "./chunk-LZQXQOPJ.js";
7
7