@cydm/pie 2.6.4 → 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.
@@ -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-3AOMWS2Z.js";
5
- import "../../../chunks/chunk-YEUBQBOB.js";
6
- import "../../../chunks/chunk-OCEYHWVX.js";
4
+ } from "../../../chunks/chunk-QKSK5K5N.js";
5
+ import "../../../chunks/chunk-AETQBDEG.js";
6
+ import "../../../chunks/chunk-5OXH6NUH.js";
7
7
  import "../../../chunks/chunk-XXGYUYXI.js";
8
8
  import "../../../chunks/chunk-LZQXQOPJ.js";
9
9
 
@@ -24461,6 +24461,72 @@ function redactSecrets(text, secrets) {
24461
24461
  }
24462
24462
  return sanitized;
24463
24463
  }
24464
+ function encodedSecretVariants(secrets) {
24465
+ const variants = [...secrets];
24466
+ for (const secret of secrets) {
24467
+ if (secret.length < 4) continue;
24468
+ try {
24469
+ const base642 = Buffer.from(secret, "utf-8").toString("base64");
24470
+ if (base642.length >= 4) {
24471
+ variants.push(base642);
24472
+ const base64url2 = Buffer.from(secret, "utf-8").toString("base64url");
24473
+ if (base64url2 !== base642 && base64url2.length >= 4) variants.push(base64url2);
24474
+ }
24475
+ const urlEncoded = encodeURIComponent(secret);
24476
+ if (urlEncoded !== secret && urlEncoded.length >= 4) variants.push(urlEncoded);
24477
+ } catch {
24478
+ }
24479
+ }
24480
+ return variants;
24481
+ }
24482
+ function hexSecretVariants(secrets) {
24483
+ const variants = [];
24484
+ for (const secret of secrets) {
24485
+ if (secret.length < 6) continue;
24486
+ try {
24487
+ const hex = Buffer.from(secret, "utf-8").toString("hex");
24488
+ if (hex.length >= 12) variants.push(hex);
24489
+ } catch {
24490
+ }
24491
+ }
24492
+ return variants;
24493
+ }
24494
+ var MIN_SECRET_FRAGMENT = 8;
24495
+ function redactSecretFragments(text, secrets) {
24496
+ const candidates = secrets.filter((secret) => secret.length >= MIN_SECRET_FRAGMENT);
24497
+ if (candidates.length === 0 || text.length < MIN_SECRET_FRAGMENT) return text;
24498
+ const grams = /* @__PURE__ */ new Map();
24499
+ for (const secret of candidates) {
24500
+ for (let offset = 0; offset + MIN_SECRET_FRAGMENT <= secret.length; offset++) {
24501
+ const gram = secret.slice(offset, offset + MIN_SECRET_FRAGMENT);
24502
+ const bucket = grams.get(gram);
24503
+ if (bucket) bucket.push({ secret, offset });
24504
+ else grams.set(gram, [{ secret, offset }]);
24505
+ }
24506
+ }
24507
+ let out = "";
24508
+ let index = 0;
24509
+ while (index < text.length) {
24510
+ const bucket = grams.get(text.slice(index, index + MIN_SECRET_FRAGMENT));
24511
+ let best = 0;
24512
+ if (bucket) {
24513
+ for (const { secret, offset } of bucket) {
24514
+ let length = MIN_SECRET_FRAGMENT;
24515
+ const maxLength = Math.min(secret.length - offset, text.length - index);
24516
+ while (length < maxLength && text[index + length] === secret[offset + length]) length += 1;
24517
+ if (length > best) best = length;
24518
+ }
24519
+ }
24520
+ if (best > 0) {
24521
+ out += "[redacted]";
24522
+ index += best;
24523
+ } else {
24524
+ out += text[index];
24525
+ index += 1;
24526
+ }
24527
+ }
24528
+ return out;
24529
+ }
24464
24530
  function redactLeadingSecretSuffix(text, secrets) {
24465
24531
  if (secrets.length === 0 || text.length === 0) return text;
24466
24532
  for (const secret of secrets) {
@@ -24483,13 +24549,26 @@ function redactTrailingSecretPrefix(text, secrets) {
24483
24549
  }
24484
24550
  return text;
24485
24551
  }
24552
+ function redactAllSecrets(text, secrets) {
24553
+ const encoded = encodedSecretVariants(secrets);
24554
+ const wholeVariants = [...encoded, ...hexSecretVariants(secrets)];
24555
+ return redactTrailingSecretPrefix(
24556
+ redactLeadingSecretSuffix(
24557
+ redactSecretFragments(redactSecrets(text, wholeVariants), encoded),
24558
+ secrets
24559
+ ),
24560
+ secrets
24561
+ );
24562
+ }
24486
24563
  function redactStderrTail(tail, secrets) {
24487
- return redactTrailingSecretPrefix(redactLeadingSecretSuffix(redactSecrets(tail, secrets), secrets), secrets);
24564
+ return redactAllSecrets(tail, secrets);
24488
24565
  }
24489
24566
  function sanitizeDiagnostic(text, secrets) {
24490
- const sanitized = redactLeadingSecretSuffix(redactSecrets(text, secrets), secrets);
24567
+ let sanitized = redactAllSecrets(text, secrets);
24491
24568
  if (sanitized.length > DIAGNOSTIC_TEXT_LIMIT) {
24492
- return `${sanitized.slice(0, DIAGNOSTIC_TEXT_LIMIT)}\u2026[truncated ${sanitized.length - DIAGNOSTIC_TEXT_LIMIT} chars]`;
24569
+ const omitted = sanitized.length - DIAGNOSTIC_TEXT_LIMIT;
24570
+ sanitized = redactAllSecrets(sanitized.slice(0, DIAGNOSTIC_TEXT_LIMIT), secrets);
24571
+ return `${sanitized}\u2026[truncated ${omitted} chars]`;
24493
24572
  }
24494
24573
  return sanitized;
24495
24574
  }
@@ -24589,6 +24668,17 @@ var McpServerManager = class {
24589
24668
  );
24590
24669
  }
24591
24670
  }
24671
+ const byLowercase = /* @__PURE__ */ new Map();
24672
+ for (const key of this.definitions.keys()) {
24673
+ const lower = key.toLowerCase();
24674
+ byLowercase.set(lower, [...byLowercase.get(lower) ?? [], key]);
24675
+ }
24676
+ const caseClashes = [...byLowercase.entries()].filter(([, keys]) => keys.length > 1).map(([, keys]) => keys.map((key) => `"${key}"`).join(" and "));
24677
+ if (caseClashes.length > 0) {
24678
+ throw new Error(
24679
+ `MCP server names collide case-insensitively (their cache shard files share one name on macOS/Windows): ${caseClashes.join("; ")}. Rename one of them.`
24680
+ );
24681
+ }
24592
24682
  this.cacheDir = cacheDir;
24593
24683
  this.log = log;
24594
24684
  }
@@ -7,9 +7,9 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-3AOMWS2Z.js";
11
- import "../../../chunks/chunk-YEUBQBOB.js";
12
- import "../../../chunks/chunk-OCEYHWVX.js";
10
+ } from "../../../chunks/chunk-QKSK5K5N.js";
11
+ import "../../../chunks/chunk-AETQBDEG.js";
12
+ import "../../../chunks/chunk-5OXH6NUH.js";
13
13
  import {
14
14
  Type
15
15
  } from "../../../chunks/chunk-XXGYUYXI.js";
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createCliHostCapabilities
4
- } from "../../../chunks/chunk-6QEDYZUR.js";
4
+ } from "../../../chunks/chunk-TFRQE7UQ.js";
5
5
  import {
6
6
  createSharedFileSystemTools,
7
7
  createSubagentCapability
8
- } from "../../../chunks/chunk-3AOMWS2Z.js";
9
- import "../../../chunks/chunk-YEUBQBOB.js";
10
- import "../../../chunks/chunk-OCEYHWVX.js";
8
+ } from "../../../chunks/chunk-QKSK5K5N.js";
9
+ import "../../../chunks/chunk-AETQBDEG.js";
10
+ import "../../../chunks/chunk-5OXH6NUH.js";
11
11
  import "../../../chunks/chunk-5353DEEC.js";
12
12
  import "../../../chunks/chunk-XXGYUYXI.js";
13
13
  import "../../../chunks/chunk-LZQXQOPJ.js";
@@ -8,9 +8,9 @@ import {
8
8
  executeManageTodoList,
9
9
  executionStateToTodos,
10
10
  restoreExecutionState
11
- } from "../../../chunks/chunk-3AOMWS2Z.js";
12
- import "../../../chunks/chunk-YEUBQBOB.js";
13
- import "../../../chunks/chunk-OCEYHWVX.js";
11
+ } from "../../../chunks/chunk-QKSK5K5N.js";
12
+ import "../../../chunks/chunk-AETQBDEG.js";
13
+ import "../../../chunks/chunk-5OXH6NUH.js";
14
14
  import "../../../chunks/chunk-XXGYUYXI.js";
15
15
  import "../../../chunks/chunk-LZQXQOPJ.js";
16
16
 
@@ -21,6 +21,6 @@ function tryFastPath(argv, options) {
21
21
 
22
22
  // vendor/chrome-devtools-axi/bin/chrome-devtools-axi.ts
23
23
  if (!tryFastPath(process.argv.slice(2), { version: VERSION })) {
24
- const { main } = await import("./cli-GB37NZHQ.js");
24
+ const { main } = await import("./cli-5Z4COIKQ.js");
25
25
  await main(process.argv.slice(2));
26
26
  }
@@ -1934,6 +1934,45 @@ async function waitForProcessExit(pid, timeoutMs) {
1934
1934
  }
1935
1935
  return !isProcessAlive(pid);
1936
1936
  }
1937
+ function splitCommandLine(command) {
1938
+ const tokens = [];
1939
+ let current = "";
1940
+ let quote = null;
1941
+ for (const char of command.trim()) {
1942
+ if (quote !== null) {
1943
+ if (char === quote) quote = null;
1944
+ else current += char;
1945
+ continue;
1946
+ }
1947
+ if (char === '"' || char === "'") {
1948
+ quote = char;
1949
+ continue;
1950
+ }
1951
+ if (/\s/.test(char)) {
1952
+ if (current.length > 0) {
1953
+ tokens.push(current);
1954
+ current = "";
1955
+ }
1956
+ continue;
1957
+ }
1958
+ current += char;
1959
+ }
1960
+ if (current.length > 0) tokens.push(current);
1961
+ return tokens;
1962
+ }
1963
+ function commandLineLooksLikeBridge(command) {
1964
+ const tokens = splitCommandLine(command);
1965
+ if (tokens.length === 0) return false;
1966
+ if (!/(?:^|[\\/])(node|npx|tsx)(?:\.(?:exe|cmd))?$/i.test(tokens[0])) return false;
1967
+ for (let index = 1; index < tokens.length; index++) {
1968
+ const token = tokens[index];
1969
+ if (token.startsWith("-")) continue;
1970
+ if (/(?:^|[\\/])tsx(?:\.(?:exe|cmd))?$/i.test(token)) continue;
1971
+ const base = token.split(/[\\/]/).pop() ?? token;
1972
+ return /^chrome-devtools-axi-bridge\.(?:js|mjs|cjs|ts)$/i.test(base);
1973
+ }
1974
+ return false;
1975
+ }
1937
1976
  function isBridgeProcess(pid) {
1938
1977
  if (process.platform === "win32") {
1939
1978
  try {
@@ -1947,7 +1986,7 @@ function isBridgeProcess(pid) {
1947
1986
  ],
1948
1987
  { encoding: "utf-8", timeout: 4e3 }
1949
1988
  );
1950
- return command.includes("chrome-devtools-axi-bridge");
1989
+ return commandLineLooksLikeBridge(command);
1951
1990
  } catch {
1952
1991
  return false;
1953
1992
  }
@@ -1957,7 +1996,7 @@ function isBridgeProcess(pid) {
1957
1996
  encoding: "utf-8",
1958
1997
  timeout: 1e3
1959
1998
  });
1960
- return command.includes("chrome-devtools-axi-bridge");
1999
+ return commandLineLooksLikeBridge(command);
1961
2000
  } catch {
1962
2001
  return false;
1963
2002
  }
@@ -1983,15 +2022,17 @@ async function judgeRecordedBridge(pidInfo, sessionName) {
1983
2022
  if (probe.identity === "own") {
1984
2023
  if (probe.reportedPid !== void 0) {
1985
2024
  if (probe.reportedPid === pidInfo.pid) {
2025
+ const verified = isBridgeProcess(pidInfo.pid);
1986
2026
  return {
1987
- terminate: true,
1988
- killProcessGroup: isBridgeProcess(pidInfo.pid),
2027
+ terminate: verified,
2028
+ killProcessGroup: verified,
1989
2029
  targetPid: pidInfo.pid
1990
2030
  };
1991
2031
  }
2032
+ const reportedIsBridge = isBridgeProcess(probe.reportedPid);
1992
2033
  return {
1993
- terminate: true,
1994
- killProcessGroup: isBridgeProcess(probe.reportedPid),
2034
+ terminate: reportedIsBridge,
2035
+ killProcessGroup: reportedIsBridge,
1995
2036
  targetPid: probe.reportedPid
1996
2037
  };
1997
2038
  }
@@ -1755,6 +1755,7 @@ var NodeHttpClient = class {
1755
1755
  let done = false;
1756
1756
  let error = null;
1757
1757
  let waiting = null;
1758
+ let consumerClosed = false;
1758
1759
  const wake = (value) => {
1759
1760
  if (!waiting) return;
1760
1761
  const w = waiting;
@@ -1840,6 +1841,7 @@ var NodeHttpClient = class {
1840
1841
  failStream(requestTimeoutError ?? new Error("SSE stream aborted"));
1841
1842
  });
1842
1843
  res.on("close", () => {
1844
+ if (consumerClosed) return;
1843
1845
  if (!done || !res.complete) {
1844
1846
  failStream(requestTimeoutError ?? new Error("SSE stream closed before end"));
1845
1847
  }
@@ -1865,6 +1867,7 @@ var NodeHttpClient = class {
1865
1867
  void waitResult;
1866
1868
  }
1867
1869
  } finally {
1870
+ consumerClosed = true;
1868
1871
  if (signal && abortHandler) {
1869
1872
  signal.removeEventListener("abort", abortHandler);
1870
1873
  }
@@ -2524,9 +2527,19 @@ var FileSystemGateway = class {
2524
2527
  const recursive = options?.recursive ?? true;
2525
2528
  const platform = detectPlatform();
2526
2529
  if (platform === "puerts" && typeof CS !== "undefined") {
2527
- if (CS.System.IO.Directory.Exists(path)) {
2530
+ if (!CS.System.IO.Directory.Exists(path)) {
2531
+ return;
2532
+ }
2533
+ if (typeof CS.System.IO.Directory.Delete === "function") {
2528
2534
  CS.System.IO.Directory.Delete(path, recursive);
2535
+ return;
2536
+ }
2537
+ const info = new CS.System.IO.DirectoryInfo(path);
2538
+ if (info && typeof info.Delete === "function") {
2539
+ info.Delete(recursive);
2540
+ return;
2529
2541
  }
2542
+ deletePuertsDirectoryByEnumeration(path, recursive);
2530
2543
  return;
2531
2544
  }
2532
2545
  const fs = nodeRequire("fs");
@@ -2549,9 +2562,20 @@ var FileSystemGateway = class {
2549
2562
  throw new Error(`Directory not found: ${source}`);
2550
2563
  }
2551
2564
  if (CS.System.IO.Directory.Exists(destination)) {
2552
- throw new Error(`Move target already exists: ${destination}`);
2565
+ const destinationFiles = Array.from(CS.System.IO.Directory.GetFiles(destination) ?? []);
2566
+ const destinationDirs = Array.from(CS.System.IO.Directory.GetDirectories(destination) ?? []);
2567
+ const isEmpty = destinationFiles.length === 0 && destinationDirs.length === 0;
2568
+ if (!isEmpty) {
2569
+ throw new Error(`Move target already exists: ${destination}`);
2570
+ }
2571
+ movePuertsDirectoryContents(source, destination);
2572
+ return;
2573
+ }
2574
+ if (typeof CS.System.IO.Directory.Move === "function") {
2575
+ CS.System.IO.Directory.Move(source, destination);
2576
+ } else {
2577
+ new CS.System.IO.DirectoryInfo(source).MoveTo(destination);
2553
2578
  }
2554
- CS.System.IO.Directory.Move(source, destination);
2555
2579
  return;
2556
2580
  }
2557
2581
  const fs = nodeRequire("fs");
@@ -2671,6 +2695,83 @@ var FileSystemGateway = class {
2671
2695
  return this.config;
2672
2696
  }
2673
2697
  };
2698
+ function movePuertsDirectoryContents(source, destination) {
2699
+ const directory = CS.System.IO.Directory;
2700
+ const file = CS.System.IO.File;
2701
+ if (typeof directory.GetFiles !== "function" || typeof directory.GetDirectories !== "function" || typeof directory.CreateDirectory !== "function" || typeof file.Copy !== "function") {
2702
+ throw new Error(
2703
+ `Host filesystem binding cannot move onto existing directory '${destination}': directory enumeration/copy is unavailable`
2704
+ );
2705
+ }
2706
+ if (isPuertsReparsePoint(source) || isPuertsReparsePoint(destination)) {
2707
+ throw new Error(
2708
+ `Refusing to move '${source}' through a reparse point (symlink/junction); resolve the link or delete it first`
2709
+ );
2710
+ }
2711
+ directory.CreateDirectory(destination);
2712
+ for (const entry of Array.from(directory.GetFiles(source) ?? [])) {
2713
+ const name = String(entry).replace(/\\/g, "/").split("/").pop();
2714
+ file.Copy(String(entry), `${destination}/${name}`, true);
2715
+ }
2716
+ for (const subdir of Array.from(directory.GetDirectories(source) ?? [])) {
2717
+ const name = String(subdir).replace(/\\/g, "/").split("/").pop();
2718
+ if (isPuertsReparsePoint(String(subdir))) continue;
2719
+ movePuertsDirectoryContents(String(subdir), `${destination}/${name}`);
2720
+ }
2721
+ for (const entry of Array.from(directory.GetFiles(source) ?? [])) {
2722
+ try {
2723
+ file.Delete(String(entry));
2724
+ } catch {
2725
+ }
2726
+ }
2727
+ }
2728
+ var warnedMissingPuertsGetAttributes = false;
2729
+ function isPuertsReparsePoint(path) {
2730
+ const file = CS.System.IO.File;
2731
+ if (typeof file.GetAttributes !== "function") {
2732
+ if (!warnedMissingPuertsGetAttributes) {
2733
+ warnedMissingPuertsGetAttributes = true;
2734
+ try {
2735
+ console.warn(
2736
+ "[platform] File.GetAttributes is unbound on this host; directory symlink checks are disabled (move/delete follow links)"
2737
+ );
2738
+ } catch {
2739
+ }
2740
+ }
2741
+ return false;
2742
+ }
2743
+ try {
2744
+ const attrs = file.GetAttributes(path);
2745
+ const raw = typeof attrs === "number" ? attrs : attrs.value__;
2746
+ const value = typeof raw === "number" ? raw : Number(raw);
2747
+ if (!Number.isFinite(value)) return false;
2748
+ return (value & 1024) !== 0;
2749
+ } catch {
2750
+ return false;
2751
+ }
2752
+ }
2753
+ function deletePuertsDirectoryByEnumeration(path, recursive) {
2754
+ const directory = CS.System.IO.Directory;
2755
+ const file = CS.System.IO.File;
2756
+ if (typeof directory.GetFiles !== "function" || typeof file.Delete !== "function") {
2757
+ throw new Error(
2758
+ `Host filesystem binding cannot delete directory '${path}': Directory.Delete and enumeration are unavailable`
2759
+ );
2760
+ }
2761
+ if (isPuertsReparsePoint(path)) {
2762
+ throw new Error(
2763
+ `Refusing to delete '${path}' through a reparse point (symlink/junction); resolve the link or delete it directly`
2764
+ );
2765
+ }
2766
+ const files = Array.from(directory.GetFiles(path) ?? []);
2767
+ for (const entry of files) file.Delete(entry);
2768
+ if (!recursive) return;
2769
+ const subdirs = Array.from(directory.GetDirectories(path) ?? []);
2770
+ for (const subdir of subdirs) {
2771
+ if (isPuertsReparsePoint(String(subdir))) continue;
2772
+ deletePuertsDirectoryByEnumeration(String(subdir), true);
2773
+ }
2774
+ }
2674
2775
 
2675
2776
  // ../../packages/platform/src/index.ts
2676
2777
  var fileSystemInstance = null;
@@ -3734,8 +3835,11 @@ ${entry.partialArgs}`;
3734
3835
  block.arguments = parseFinalToolArguments(partialArgs, block.name);
3735
3836
  stream.push({ type: "toolcall_end", contentIndex, toolCall: block, partial: output });
3736
3837
  }
3737
- if (output.stopReason !== "error" && output.stopReason !== "aborted" && output.content.some((block) => block.type === "toolCall")) {
3838
+ const hasToolCallBlocks = output.content.some((block) => block.type === "toolCall");
3839
+ if (output.stopReason !== "error" && output.stopReason !== "aborted" && hasToolCallBlocks) {
3738
3840
  output.stopReason = "toolUse";
3841
+ } else if (output.stopReason === "toolUse" && !hasToolCallBlocks) {
3842
+ output.stopReason = "stop";
3739
3843
  }
3740
3844
  if (options?.signal?.aborted) {
3741
3845
  throw new Error("Request was aborted");
@@ -3,7 +3,7 @@ import {
3
3
  EventStream,
4
4
  streamSimple,
5
5
  validateToolArguments
6
- } from "./chunk-OCEYHWVX.js";
6
+ } from "./chunk-5OXH6NUH.js";
7
7
 
8
8
  // ../../packages/agent-core/src/agent-loop.ts
9
9
  function createLoopErrorMessage(error, config, signal) {
@@ -986,7 +986,7 @@ var Agent = class {
986
986
  message: event.message,
987
987
  toolResults: event.toolResults
988
988
  });
989
- } else if (hasToolCalls || stopReason === "toolUse") {
989
+ } else if (hasToolCalls) {
990
990
  this.updateStatusSnapshot({
991
991
  phase: "responding",
992
992
  turnState: "continuing",
@@ -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-YEUBQBOB.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-OCEYHWVX.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" });
@@ -3485,6 +3492,7 @@ var FileSessionStore = class {
3485
3492
  }
3486
3493
  delete(sessionId) {
3487
3494
  const paths = this.pathsFor(sessionId);
3495
+ if (sessionDirIsSymlink(paths.dir)) return false;
3488
3496
  if (!this.gateway.exists(paths.dir)) return false;
3489
3497
  this.gateway.deleteDirectory(paths.dir, { recursive: true });
3490
3498
  this.dropCaches();
@@ -5701,7 +5709,12 @@ var AgentSessionRetryController = class {
5701
5709
  removeTrailingAssistantError;
5702
5710
  continueTurn;
5703
5711
  setRecoveryState;
5704
- 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;
5705
5718
  retryTimer;
5706
5719
  pendingRetry;
5707
5720
  resolvePendingRetry;
@@ -5720,36 +5733,41 @@ var AgentSessionRetryController = class {
5720
5733
  return;
5721
5734
  }
5722
5735
  if (!failure) {
5723
- if (this.retryAttempt > 0) {
5724
- this.emit({ type: "retry_succeeded", attempts: this.retryAttempt });
5725
- this.emit({ type: "turn_retry_succeeded", attempts: this.retryAttempt });
5726
- 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();
5727
5740
  this.setRecoveryState("none");
5728
5741
  this.resolvePending();
5729
5742
  }
5730
5743
  return;
5731
5744
  }
5732
5745
  if (!failure.retryable) {
5733
- if (this.retryAttempt > 0) {
5734
- this.retryAttempt = 0;
5746
+ if (this.totalRetryAttempts > 0) {
5747
+ this.resetAttempts();
5735
5748
  this.setRecoveryState("none");
5736
5749
  this.resolvePending();
5737
5750
  }
5738
5751
  return;
5739
5752
  }
5740
5753
  const maxRetries = this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3;
5741
- this.retryAttempt += 1;
5742
- 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) {
5743
5761
  const terminalFailure = asTerminalFailure(failure);
5744
- this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries });
5762
+ this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries: totalExhausted ? totalBudget : maxRetries });
5745
5763
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
5746
5764
  this.emit({ type: "turn_settled" });
5747
- this.retryAttempt = 0;
5765
+ this.resetAttempts();
5748
5766
  this.setRecoveryState("terminal");
5749
5767
  this.resolvePending();
5750
5768
  return;
5751
5769
  }
5752
- const attempt = this.retryAttempt;
5770
+ const attempt = kindAttempts;
5753
5771
  const rawDelayMs = (this.retry.baseDelayMs ?? 2e3) * 2 ** (attempt - 1);
5754
5772
  const delayMs = this.retry.maxDelayMs !== void 0 ? Math.min(rawDelayMs, this.retry.maxDelayMs) : rawDelayMs;
5755
5773
  this.ensurePending();
@@ -5774,7 +5792,7 @@ var AgentSessionRetryController = class {
5774
5792
  });
5775
5793
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
5776
5794
  this.emit({ type: "turn_settled" });
5777
- this.retryAttempt = 0;
5795
+ this.resetAttempts();
5778
5796
  this.setRecoveryState("terminal");
5779
5797
  this.resolvePending();
5780
5798
  });
@@ -5803,15 +5821,19 @@ var AgentSessionRetryController = class {
5803
5821
  this.emit({ type: "retry_exhausted", errorMessage: terminalFailure.message, maxRetries });
5804
5822
  this.emit({ type: "turn_failed_terminal", failure: terminalFailure });
5805
5823
  this.emit({ type: "turn_settled" });
5806
- this.retryAttempt = 0;
5824
+ this.resetAttempts();
5807
5825
  this.setRecoveryState("terminal");
5808
5826
  this.resolvePending();
5809
5827
  }
5810
5828
  cancel() {
5811
5829
  this.cancelTimerOnly();
5812
- this.retryAttempt = 0;
5830
+ this.resetAttempts();
5813
5831
  this.resolvePending();
5814
5832
  }
5833
+ resetAttempts() {
5834
+ this.retryAttempts.clear();
5835
+ this.totalRetryAttempts = 0;
5836
+ }
5815
5837
  cancelTimerOnly() {
5816
5838
  if (this.retryTimer === void 0) {
5817
5839
  return;
@@ -9296,10 +9318,28 @@ function isSpecialDevicePath(path4) {
9296
9318
  function detectUnderstandingKind(filePath) {
9297
9319
  const lower = filePath.toLowerCase();
9298
9320
  if (/\.(mp4|mov|m4v|webm|avi|mkv)$/.test(lower)) {
9299
- 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" };
9300
9331
  }
9301
9332
  if (/\.(mp3|wav|m4a|aac|flac|ogg)$/.test(lower)) {
9302
- 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" };
9303
9343
  }
9304
9344
  if (/\.(pdf)$/.test(lower)) {
9305
9345
  return { kind: "document", mimeType: "application/pdf" };
@@ -13659,13 +13699,14 @@ Focus: ${request.question.trim()}` : ""}` },
13659
13699
  if (request.signal?.aborted) throw new Error("Operation aborted");
13660
13700
  const data = await fs2.readFile(request.absolutePath, "base64");
13661
13701
  if (request.signal?.aborted) throw new Error("Operation aborted");
13662
- 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 {
13663
13704
  content: [
13664
13705
  { type: "text", text: `Read ${request.kind} file ${request.displayPath} [${request.mimeType}]. Original media attached for the current model.${request.question?.trim() ? `
13665
13706
  Focus: ${request.question.trim()}` : ""}` },
13666
13707
  { type: request.kind, data, mimeType: request.mimeType }
13667
13708
  ],
13668
- 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 } },
13669
13710
  isError: false
13670
13711
  };
13671
13712
  }