@cydm/pie 1.0.51 → 2.1.1

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.
Files changed (73) hide show
  1. package/README.md +36 -16
  2. package/dist/builtin/extensions/ask-user/index.js +4 -3
  3. package/dist/builtin/extensions/ask-user/package.json +8 -7
  4. package/dist/builtin/extensions/changelog/package.json +9 -9
  5. package/dist/builtin/extensions/computer-use/index.js +9352 -0
  6. package/dist/builtin/extensions/computer-use/package.json +11 -0
  7. package/dist/builtin/extensions/computer-use/prebuilt/linux/arm64/linux-bridge +0 -0
  8. package/dist/builtin/extensions/computer-use/prebuilt/linux/x64/linux-bridge +0 -0
  9. package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
  10. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +24 -0
  11. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
  12. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +115 -0
  13. package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
  14. package/dist/builtin/extensions/computer-use/prebuilt/windows/windows-bridge.exe +0 -0
  15. package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +277 -0
  16. package/dist/builtin/extensions/computer-use/scripts/helper-path.mjs +48 -0
  17. package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +549 -0
  18. package/dist/builtin/extensions/document-attachments/package.json +9 -9
  19. package/dist/builtin/extensions/init/package.json +9 -9
  20. package/dist/builtin/extensions/mcp-adapter/index.js +25250 -0
  21. package/dist/builtin/extensions/mcp-adapter/package.json +11 -0
  22. package/dist/builtin/extensions/plan-mode/index.js +4 -3
  23. package/dist/builtin/extensions/plan-mode/package.json +9 -9
  24. package/dist/builtin/extensions/subagent/index.js +6 -4
  25. package/dist/builtin/extensions/subagent/package.json +16 -12
  26. package/dist/builtin/extensions/todo/index.js +4 -3
  27. package/dist/builtin/extensions/todo/package.json +9 -9
  28. package/dist/builtin/skills/chrome-devtools-axi/CHANGELOG.md +5 -0
  29. package/dist/builtin/skills/chrome-devtools-axi/LICENSE +21 -0
  30. package/dist/builtin/skills/chrome-devtools-axi/README.md +17 -0
  31. package/dist/builtin/skills/chrome-devtools-axi/SKILL.md +50 -0
  32. package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +20034 -0
  33. package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +83 -0
  34. package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +26 -0
  35. package/dist/builtin/skills/chrome-devtools-axi/chunk-42SGITKJ.js +11 -0
  36. package/dist/builtin/skills/chrome-devtools-axi/chunk-OJ6N23UZ.js +47 -0
  37. package/dist/builtin/skills/chrome-devtools-axi/chunk-UPATXALW.js +215 -0
  38. package/dist/builtin/skills/chrome-devtools-axi/cli-F2VCSVL4.js +4424 -0
  39. package/dist/builtin/skills/chrome-devtools-axi/package.json +12 -0
  40. package/dist/builtin/skills/skill-creator/SKILL.md +5 -2
  41. package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.mjs +7 -20
  42. package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +15 -15
  43. package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.mjs +20 -19
  44. package/dist/builtin/skills/skill-creator/scripts/generate_report.mjs +3 -3
  45. package/dist/builtin/skills/skill-creator/scripts/improve_description.mjs +12 -8
  46. package/dist/builtin/skills/skill-creator/scripts/package_skill.mjs +1 -0
  47. package/dist/builtin/skills/skill-creator/scripts/pie_runner.mjs +77 -31
  48. package/dist/builtin/skills/skill-creator/scripts/run_eval.mjs +38 -11
  49. package/dist/builtin/skills/skill-creator/scripts/run_loop.mjs +12 -6
  50. package/dist/builtin/skills/skill-creator/scripts/skill_metadata.mjs +12 -1
  51. package/dist/builtin/skills/tui-use/LICENSE +21 -0
  52. package/dist/builtin/skills/tui-use/README.md +17 -0
  53. package/dist/builtin/skills/tui-use/SKILL.md +106 -0
  54. package/dist/builtin/skills/tui-use/tui-use-cli.cjs +10608 -0
  55. package/dist/builtin/skills/tui-use/tui-use-cli.js +39 -0
  56. package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +7916 -0
  57. package/dist/chunks/chunk-5353DEEC.js +130 -0
  58. package/dist/chunks/{chunk-S2J3SZZX.js → chunk-IM43UYVV.js} +827 -3385
  59. package/dist/chunks/{chunk-A644H2XX.js → chunk-LU7RKALH.js} +241 -96
  60. package/dist/chunks/{chunk-B3SMW2XW.js → chunk-QJH6YN2W.js} +1 -1
  61. package/dist/chunks/{chunk-KDPAGHYY.js → chunk-TJ2F4FL5.js} +190 -207
  62. package/dist/chunks/chunk-XXGYUYXI.js +2718 -0
  63. package/dist/chunks/{src-UKCIAX6F.js → src-QSP2OPHU.js} +3 -2
  64. package/dist/chunks/{test-stream-NCBFPM2I.js → test-stream-CVGWFLSX.js} +2 -1
  65. package/dist/chunks/webapi-MBCKO7ZV.js +2481 -0
  66. package/dist/cli.js +7866 -369
  67. package/package.json +29 -20
  68. package/scripts/repair-node-pty.mjs +45 -0
  69. package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -5
  70. package/dist/builtin/skills/browser-tools/README.md +0 -17
  71. package/dist/builtin/skills/browser-tools/SKILL.md +0 -43
  72. package/dist/builtin/skills/browser-tools/package.json +0 -12
  73. package/dist/builtin/skills/browser-tools/playwright-cli.js +0 -45
@@ -1,17 +1,19 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  Agent
4
- } from "./chunk-B3SMW2XW.js";
4
+ } from "./chunk-QJH6YN2W.js";
5
5
  import {
6
6
  FileSystemGateway,
7
- Type,
8
7
  completeSimple,
9
8
  detectPlatform,
10
9
  getFileSystem,
11
10
  getPlatformConfig,
12
11
  hashText,
13
12
  streamSimple
14
- } from "./chunk-S2J3SZZX.js";
13
+ } from "./chunk-IM43UYVV.js";
14
+ import {
15
+ Type
16
+ } from "./chunk-XXGYUYXI.js";
15
17
  import {
16
18
  __commonJS,
17
19
  __toESM
@@ -5998,6 +6000,47 @@ function setExtensionEnabledInSettings(settingsObject, identity, enabled) {
5998
6000
  return setEnablementInMap(settingsObject, "extensions", identity, enabled);
5999
6001
  }
6000
6002
 
6003
+ // ../../packages/agent-framework/src/extensions/resources.ts
6004
+ var ExtensionResourceScope = class {
6005
+ handlers = /* @__PURE__ */ new Set();
6006
+ disposal;
6007
+ closed = false;
6008
+ register(handler) {
6009
+ if (this.closed) throw new Error("Extension resources are already closing.");
6010
+ this.handlers.add(handler);
6011
+ return () => {
6012
+ this.handlers.delete(handler);
6013
+ };
6014
+ }
6015
+ dispose(reason = "shutdown", timeoutMs = 7500) {
6016
+ if (this.disposal) return this.disposal;
6017
+ this.closed = true;
6018
+ const handlers = [...this.handlers].reverse();
6019
+ this.handlers.clear();
6020
+ const controller = new AbortController();
6021
+ this.disposal = (async () => {
6022
+ let timer;
6023
+ try {
6024
+ const results = await Promise.race([
6025
+ Promise.allSettled(handlers.map((handler) => Promise.resolve().then(() => handler(reason, controller.signal)))),
6026
+ new Promise((_, reject) => {
6027
+ timer = setTimeout(() => {
6028
+ controller.abort();
6029
+ reject(new Error(`Extension cleanup exceeded ${timeoutMs}ms.`));
6030
+ }, timeoutMs);
6031
+ })
6032
+ ]);
6033
+ const errors = results.filter((result) => result.status === "rejected").map((result) => result.reason);
6034
+ if (errors.length) throw new AggregateError(errors, "Extension resource cleanup failed.");
6035
+ } finally {
6036
+ clearTimeout(timer);
6037
+ controller.abort();
6038
+ }
6039
+ })();
6040
+ return this.disposal;
6041
+ }
6042
+ };
6043
+
6001
6044
  // ../../packages/agent-framework/src/interaction.ts
6002
6045
  var InteractionUnavailableError = class extends Error {
6003
6046
  request;
@@ -6254,7 +6297,10 @@ async function askSingleQuestion(args) {
6254
6297
  if (response.type === "multiline_input" && (response.skipped || response.timedOut)) {
6255
6298
  return buildSkippedResult(question, response.timedOut === true);
6256
6299
  }
6257
- const answer = response.type === "multiline_input" ? response.value : void 0;
6300
+ const answer = response.type === "multiline_input" ? response.value?.trim() : void 0;
6301
+ if (answer === "") {
6302
+ return buildSkippedResult(question, false);
6303
+ }
6258
6304
  if (answer === void 0) {
6259
6305
  return { content: [{ type: "text", text: "User cancelled" }], details: { cancelled: true } };
6260
6306
  }
@@ -6272,7 +6318,12 @@ async function askSingleQuestion(args) {
6272
6318
  id: `ask-user:select:${Date.now()}`,
6273
6319
  prompt: question,
6274
6320
  options: displayOptions,
6275
- timeoutMs: DEFAULT_ASK_TIMEOUT_MS
6321
+ timeoutMs: DEFAULT_ASK_TIMEOUT_MS,
6322
+ // Tab-style navigation for hosts that support it: ← at the first page
6323
+ // selects Back, → at the last page selects Review (row presence mirrors
6324
+ // allowBack/allowReview). Hosts without shortcut support ignore these.
6325
+ leftShortcut: allowBack ? BACK_OPTION : void 0,
6326
+ rightShortcut: allowReview ? REVIEW_OPTION : void 0
6276
6327
  });
6277
6328
  if (selection.type === "select_one" && (selection.skipped || selection.timedOut)) {
6278
6329
  return buildSkippedResult(question, selection.timedOut === true);
@@ -6297,7 +6348,10 @@ async function askSingleQuestion(args) {
6297
6348
  if (response.type === "text_input" && (response.skipped || response.timedOut)) {
6298
6349
  return buildSkippedResult(question, response.timedOut === true);
6299
6350
  }
6300
- const customAnswer = response.type === "text_input" ? response.value : void 0;
6351
+ const customAnswer = response.type === "text_input" ? response.value?.trim() : void 0;
6352
+ if (customAnswer === "") {
6353
+ return buildSkippedResult(question, false);
6354
+ }
6301
6355
  if (customAnswer === void 0) {
6302
6356
  return { content: [{ type: "text", text: "User cancelled" }], details: { cancelled: true } };
6303
6357
  }
@@ -6377,8 +6431,11 @@ function createAskUserCapability() {
6377
6431
  }
6378
6432
  answers[q.id] = {
6379
6433
  question: q.question,
6380
- answer: result.details?.answer || result.content[0].text,
6381
- ...result.details
6434
+ ...result.details,
6435
+ // After the spread: `answer` wins over the same spread key, and
6436
+ // `??` preserves intentional values (`||` let "" re-clobber the
6437
+ // fallback — a latent trap for any falsy answer).
6438
+ answer: result.details?.answer ?? result.content[0].text
6382
6439
  };
6383
6440
  currentIndex++;
6384
6441
  }
@@ -6387,7 +6444,7 @@ function createAskUserCapability() {
6387
6444
  const reviewOptions = [
6388
6445
  CONFIRM_OPTION,
6389
6446
  ...questions.map((q2, i) => {
6390
- const answer = answers[q2.id]?.answer || "(not answered)";
6447
+ const answer = answers[q2.id]?.answer ?? "(not answered)";
6391
6448
  const displayAnswer = answer.length > 20 ? `${answer.substring(0, 20)}...` : answer;
6392
6449
  return `\u270F\uFE0F Q${i + 1}: ${displayAnswer}`;
6393
6450
  }),
@@ -6441,8 +6498,8 @@ function createAskUserCapability() {
6441
6498
  }
6442
6499
  answers[q.id] = {
6443
6500
  question: q.question,
6444
- answer: result.details?.answer || result.content[0].text,
6445
- ...result.details
6501
+ ...result.details,
6502
+ answer: result.details?.answer ?? result.content[0].text
6446
6503
  };
6447
6504
  }
6448
6505
  }
@@ -8816,6 +8873,8 @@ var commaPattern = /\\,/g;
8816
8873
  var periodPattern = /\\\./g;
8817
8874
  var EXPANSION_MAX = 1e5;
8818
8875
  var EXPANSION_MAX_LENGTH = 4e6;
8876
+ var EXPANSION_MAX_DEPTH = 1e3;
8877
+ var EXPANSION_MAX_REWRITES = 1e3;
8819
8878
  function numeric(str) {
8820
8879
  return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
8821
8880
  }
@@ -8825,36 +8884,44 @@ function escapeBraces(str) {
8825
8884
  function unescapeBraces(str) {
8826
8885
  return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
8827
8886
  }
8828
- function parseCommaParts(str) {
8829
- if (!str) {
8830
- return [""];
8887
+ function pushAll(target, items) {
8888
+ for (let i = 0; i < items.length; i++) {
8889
+ target.push(items[i]);
8831
8890
  }
8891
+ }
8892
+ function parseCommaParts(str) {
8832
8893
  const parts = [];
8833
- const m = balanced("{", "}", str);
8834
- if (!m) {
8835
- return str.split(",");
8836
- }
8837
- const { pre, body, post } = m;
8838
- const p = pre.split(",");
8839
- p[p.length - 1] += "{" + body + "}";
8840
- const postParts = parseCommaParts(post);
8841
- if (post.length) {
8842
- ;
8843
- p[p.length - 1] += postParts.shift();
8844
- p.push.apply(p, postParts);
8845
- }
8846
- parts.push.apply(parts, p);
8847
- return parts;
8894
+ let carry = "";
8895
+ for (; ; ) {
8896
+ const m = balanced("{", "}", str);
8897
+ if (!m) {
8898
+ const tail = str.split(",");
8899
+ tail[0] = carry + tail[0];
8900
+ pushAll(parts, tail);
8901
+ return parts;
8902
+ }
8903
+ const { pre, body, post } = m;
8904
+ const p = pre.split(",");
8905
+ p[0] = carry + p[0];
8906
+ p[p.length - 1] += "{" + body + "}";
8907
+ if (!post.length) {
8908
+ pushAll(parts, p);
8909
+ return parts;
8910
+ }
8911
+ carry = p.pop();
8912
+ pushAll(parts, p);
8913
+ str = post;
8914
+ }
8848
8915
  }
8849
8916
  function expand(str, options = {}) {
8850
8917
  if (!str) {
8851
8918
  return [];
8852
8919
  }
8853
- const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
8920
+ const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH, maxDepth = EXPANSION_MAX_DEPTH, maxRewrites = EXPANSION_MAX_REWRITES } = options;
8854
8921
  if (str.slice(0, 2) === "{}") {
8855
8922
  str = "\\{\\}" + str.slice(2);
8856
8923
  }
8857
- return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
8924
+ return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
8858
8925
  }
8859
8926
  function embrace(str) {
8860
8927
  return "{" + str + "}";
@@ -8932,8 +8999,12 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
8932
8999
  }
8933
9000
  return N;
8934
9001
  }
8935
- function expand_(str, max, maxLength, isTop) {
9002
+ function expand_(str, max, maxLength, maxDepth, depth, maxRewrites, isTop) {
9003
+ if (depth > maxDepth) {
9004
+ return [str];
9005
+ }
8936
9006
  let acc = [""];
9007
+ let rewrites = 0;
8937
9008
  let dropEmpties = false;
8938
9009
  let firstGroup = true;
8939
9010
  for (; ; ) {
@@ -8955,7 +9026,8 @@ function expand_(str, max, maxLength, isTop) {
8955
9026
  const isSequence = isNumericSequence || isAlphaSequence;
8956
9027
  const isOptions = m.body.indexOf(",") >= 0;
8957
9028
  if (!isSequence && !isOptions) {
8958
- if (m.post.match(/,(?!,).*\}/)) {
9029
+ if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
9030
+ rewrites++;
8959
9031
  str = m.pre + "{" + m.body + escClose + m.post;
8960
9032
  isTop = true;
8961
9033
  continue;
@@ -8972,7 +9044,7 @@ function expand_(str, max, maxLength, isTop) {
8972
9044
  } else {
8973
9045
  let n = parseCommaParts(m.body);
8974
9046
  if (n.length === 1 && n[0] !== void 0) {
8975
- n = expand_(n[0], max, maxLength, false).map(embrace);
9047
+ n = expand_(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
8976
9048
  if (n.length === 1) {
8977
9049
  acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
8978
9050
  if (!m.post.length)
@@ -8990,7 +9062,7 @@ function expand_(str, max, maxLength, isTop) {
8990
9062
  values = [];
8991
9063
  let valuesLength = 0;
8992
9064
  outer: for (let j = 0; j < n.length; j++) {
8993
- const expanded = expand_(n[j], max, maxLength, false);
9065
+ const expanded = expand_(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
8994
9066
  for (let k = 0; k < expanded.length; k++) {
8995
9067
  const v = expanded[k];
8996
9068
  if (dropsEmpties && !v)
@@ -11651,6 +11723,13 @@ function getModelLabel(model) {
11651
11723
  function textFromAssistant(message) {
11652
11724
  return message.content.filter((block) => block.type === "text").map((block) => block.text).join("\n").trim();
11653
11725
  }
11726
+ function classifyUnderstandingFailure(message) {
11727
+ if (/\b40[123]\b|payment required|insufficient[ _-]?balance|arrearage|余额|quota/i.test(message)) return "auth_or_balance";
11728
+ if (/\b429\b|rate.?limit|too many requests/i.test(message)) return "rate_limited";
11729
+ if (/timed? ?out|timeout|etimedout/i.test(message)) return "timeout";
11730
+ if (/does not support|unsupported|multimodal|modality|not declare/i.test(message)) return "unsupported";
11731
+ return "provider_error";
11732
+ }
11654
11733
  function modalityForReadFileUnderstandingKind(kind) {
11655
11734
  if (kind === "image") return "image";
11656
11735
  if (kind === "video") return "video";
@@ -11683,83 +11762,147 @@ function createReadFileUnderstandingHandler(deps) {
11683
11762
  }
11684
11763
  async function understandFileWithModel(deps, request) {
11685
11764
  const purpose = `read_file.${request.kind}`;
11686
- const decision = deps.resolveToolModel(purpose);
11687
11765
  const agentModel = deps.getAgentModel();
11688
- const routeDetails = {
11766
+ const singleDecision = deps.resolveToolModel(purpose);
11767
+ const candidateDecisions = deps.resolveToolModelCandidates?.(purpose) ?? [singleDecision];
11768
+ const sessionId = deps.getSessionId() || `read-file-${Date.now()}`;
11769
+ const attempts = [];
11770
+ let sendAttemptCount = 0;
11771
+ const baseRouteDetails = {
11689
11772
  purpose,
11690
- requiredCapability: decision.requiredCapability,
11691
- routeSource: decision.routeSource,
11773
+ requiredCapability: singleDecision.requiredCapability,
11692
11774
  agentModel: getModelLabel(agentModel),
11693
- toolModel: getModelLabel(decision.model),
11694
- fallbackReason: decision.fallbackReason,
11695
11775
  kind: request.kind,
11696
11776
  mimeType: request.mimeType
11697
11777
  };
11698
- if (!decision.model || !decision.apiKey) {
11778
+ for (const decision of candidateDecisions) {
11779
+ const attemptBase = { toolModel: getModelLabel(decision.model), routeSource: decision.routeSource };
11780
+ if (!decision.model || !decision.apiKey) {
11781
+ attempts.push({
11782
+ ...attemptBase,
11783
+ failureCategory: "unavailable",
11784
+ fallbackReason: decision.fallbackReason,
11785
+ durationMs: 0
11786
+ });
11787
+ continue;
11788
+ }
11789
+ const startedAt = Date.now();
11790
+ sendAttemptCount += 1;
11791
+ try {
11792
+ const directImageContent = buildDirectImageUnderstandingContent(request);
11793
+ const prepared = directImageContent ? { content: directImageContent, details: { inputMode: "inlineDataUrl" } } : await deps.prepareFileContent({
11794
+ request,
11795
+ model: decision.model,
11796
+ apiKey: decision.apiKey,
11797
+ sessionId
11798
+ });
11799
+ const send = deps.sendUnderstandingRequest ?? completeSimple;
11800
+ const response = await send(
11801
+ decision.model,
11802
+ {
11803
+ systemPrompt: "You are a file-understanding tool. Answer only from the provided file. Keep the answer concise and factual.",
11804
+ messages: [{ role: "user", content: [buildReadFileUnderstandingPrompt(request), ...prepared.content], timestamp: Date.now() }]
11805
+ },
11806
+ {
11807
+ apiKey: decision.apiKey,
11808
+ maxTokens: Math.min(decision.model.maxTokens || 4096, 4096),
11809
+ signal: request.signal
11810
+ }
11811
+ );
11812
+ const errorMessage = response.stopReason === "error" || response.stopReason === "aborted" ? response.errorMessage : void 0;
11813
+ const durationMs = Date.now() - startedAt;
11814
+ if (response.stopReason === "aborted") {
11815
+ attempts.push({ ...attemptBase, failureCategory: "aborted", error: errorMessage, durationMs });
11816
+ return {
11817
+ content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${errorMessage ?? "aborted"}` }],
11818
+ details: { understanding: { ...baseRouteDetails, ...attemptBase, error: errorMessage, attempts } },
11819
+ isError: true
11820
+ };
11821
+ }
11822
+ if (errorMessage) {
11823
+ attempts.push({
11824
+ ...attemptBase,
11825
+ failureCategory: classifyUnderstandingFailure(errorMessage),
11826
+ error: errorMessage,
11827
+ durationMs
11828
+ });
11829
+ continue;
11830
+ }
11831
+ attempts.push({ ...attemptBase, durationMs });
11832
+ const text = textFromAssistant(response) || "(file understanding model returned no text)";
11833
+ return {
11834
+ content: [{ type: "text", text }],
11835
+ details: {
11836
+ understanding: {
11837
+ ...baseRouteDetails,
11838
+ // Capability follows the candidate that actually served the request,
11839
+ // not the first decision's.
11840
+ requiredCapability: decision.requiredCapability,
11841
+ ...attemptBase,
11842
+ fallbackReason: decision.fallbackReason,
11843
+ responseStopReason: response.stopReason,
11844
+ ...prepared.details,
11845
+ attempts
11846
+ }
11847
+ },
11848
+ isError: false
11849
+ };
11850
+ } catch (error) {
11851
+ const message = error instanceof Error ? error.message : String(error);
11852
+ const durationMs = Date.now() - startedAt;
11853
+ if (request.signal?.aborted) {
11854
+ attempts.push({ ...attemptBase, failureCategory: "aborted", error: message, durationMs });
11855
+ return {
11856
+ content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${message}` }],
11857
+ details: { understanding: { ...baseRouteDetails, ...attemptBase, error: message, attempts } },
11858
+ isError: true
11859
+ };
11860
+ }
11861
+ attempts.push({
11862
+ ...attemptBase,
11863
+ failureCategory: classifyUnderstandingFailure(message),
11864
+ error: message,
11865
+ durationMs
11866
+ });
11867
+ }
11868
+ }
11869
+ const routedAttempts = attempts.filter((attempt) => attempt.toolModel !== void 0);
11870
+ if (routedAttempts.length === 0 || sendAttemptCount === 0) {
11699
11871
  return {
11700
11872
  content: [{
11701
11873
  type: "text",
11702
- text: decision.fallbackReason || `No configured model declares ${request.kind} capability for ${purpose}.`
11874
+ text: singleDecision.fallbackReason || `No configured model declares ${request.kind} capability for ${purpose}.`
11703
11875
  }],
11704
- details: { understanding: routeDetails },
11705
- isError: true
11706
- };
11707
- }
11708
- const sessionId = deps.getSessionId() || `read-file-${Date.now()}`;
11709
- try {
11710
- const directImageContent = buildDirectImageUnderstandingContent(request);
11711
- const prepared = directImageContent ? { content: directImageContent, details: { inputMode: "inlineDataUrl" } } : await deps.prepareFileContent({
11712
- request,
11713
- model: decision.model,
11714
- apiKey: decision.apiKey,
11715
- sessionId
11716
- });
11717
- const fileContent = prepared.content;
11718
- const content = [
11719
- buildReadFileUnderstandingPrompt(request),
11720
- ...fileContent
11721
- ];
11722
- const response = await completeSimple(
11723
- decision.model,
11724
- {
11725
- systemPrompt: "You are a file-understanding tool. Answer only from the provided file. Keep the answer concise and factual.",
11726
- messages: [{ role: "user", content, timestamp: Date.now() }]
11727
- },
11728
- {
11729
- apiKey: decision.apiKey,
11730
- maxTokens: Math.min(decision.model.maxTokens || 4096, 4096),
11731
- signal: request.signal
11732
- }
11733
- );
11734
- const errorMessage = response.stopReason === "error" || response.stopReason === "aborted" ? response.errorMessage : void 0;
11735
- const text = textFromAssistant(response) || (errorMessage ? `read_file ${request.kind} understanding failed: ${errorMessage}` : "(file understanding model returned no text)");
11736
- return {
11737
- content: [{ type: "text", text }],
11738
11876
  details: {
11739
11877
  understanding: {
11740
- ...routeDetails,
11741
- toolModel: getModelLabel(decision.model),
11742
- responseStopReason: response.stopReason,
11743
- ...prepared.details,
11744
- ...errorMessage ? { error: errorMessage } : {}
11745
- }
11746
- },
11747
- isError: response.stopReason === "error" || response.stopReason === "aborted"
11748
- };
11749
- } catch (error) {
11750
- const message = error instanceof Error ? error.message : String(error);
11751
- return {
11752
- content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${message}` }],
11753
- details: {
11754
- understanding: {
11755
- ...routeDetails,
11756
- toolModel: getModelLabel(decision.model),
11757
- error: message
11878
+ ...baseRouteDetails,
11879
+ toolModel: getModelLabel(singleDecision.model),
11880
+ routeSource: singleDecision.routeSource,
11881
+ fallbackReason: singleDecision.fallbackReason,
11882
+ attempts
11758
11883
  }
11759
11884
  },
11760
11885
  isError: true
11761
11886
  };
11762
11887
  }
11888
+ const lastAttempt = routedAttempts[routedAttempts.length - 1];
11889
+ const viaSegments = attempts.filter((attempt) => attempt.error || attempt.fallbackReason).map((attempt) => `via ${attempt.toolModel ?? "unconfigured route"}: ${attempt.error ?? attempt.fallbackReason}`);
11890
+ const firstFailure = attempts.find((attempt) => attempt.error || attempt.fallbackReason);
11891
+ const combinedError = sendAttemptCount === 1 ? `read_file ${request.kind} understanding failed: ${firstFailure?.error ?? firstFailure?.fallbackReason ?? "unknown error"}` : `read_file ${request.kind} understanding failed after ${sendAttemptCount} route(s): ${viaSegments.join("; ")}`;
11892
+ return {
11893
+ content: [{ type: "text", text: combinedError }],
11894
+ details: {
11895
+ understanding: {
11896
+ ...baseRouteDetails,
11897
+ toolModel: lastAttempt.toolModel,
11898
+ routeSource: lastAttempt.routeSource,
11899
+ fallbackReason: lastAttempt.fallbackReason ?? lastAttempt.error,
11900
+ error: combinedError,
11901
+ attempts
11902
+ }
11903
+ },
11904
+ isError: true
11905
+ };
11763
11906
  }
11764
11907
 
11765
11908
  // ../../packages/shared-headless-capabilities/src/session-trace.ts
@@ -13859,7 +14002,7 @@ function createSharedWebFetchTool(deps = {}) {
13859
14002
  const extractionMethod = isHtml ? "html_readability" : isPdf ? "pdf_text" : "plain_text";
13860
14003
  if (isHtml && looksJavaScriptHeavy(raw, text)) {
13861
14004
  return {
13862
- content: [{ type: "text", text: `web_fetch could not read meaningful content from ${url}; this page appears to require JavaScript. Use Playwright browser tools for browser-rendered content.` }],
14005
+ content: [{ type: "text", text: `web_fetch could not read meaningful content from ${url}; this page appears to require JavaScript. Use the chrome-devtools-axi skill (or computer-use browser tools) for browser-rendered content.` }],
13863
14006
  details: {
13864
14007
  url,
13865
14008
  sourceUrl: url,
@@ -15200,6 +15343,7 @@ export {
15200
15343
  calculateTotalTokens,
15201
15344
  estimateContextTokens,
15202
15345
  getAutoCompactTokenLimit,
15346
+ isCompactSummaryMessage,
15203
15347
  findFirstKeptEntryId,
15204
15348
  createCompactionSummary,
15205
15349
  generateEntryId,
@@ -15213,6 +15357,7 @@ export {
15213
15357
  extractExtensionSettings,
15214
15358
  setEnablementInMap,
15215
15359
  setExtensionEnabledInSettings,
15360
+ ExtensionResourceScope,
15216
15361
  registerInteractionHandler,
15217
15362
  hasInteractionHandler,
15218
15363
  requestInteraction,
@@ -3,7 +3,7 @@ import {
3
3
  EventStream,
4
4
  streamSimple,
5
5
  validateToolArguments
6
- } from "./chunk-S2J3SZZX.js";
6
+ } from "./chunk-IM43UYVV.js";
7
7
 
8
8
  // ../../packages/agent-core/src/agent-loop.ts
9
9
  function createLoopErrorMessage(error, config, signal) {