@qwen-code/qwen-code 0.17.1 → 0.18.0-preview.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 (120) hide show
  1. package/README.md +4 -6
  2. package/bundled/qc-helper/SKILL.md +30 -24
  3. package/bundled/qc-helper/docs/features/auto-mode.md +54 -9
  4. package/bundled/qc-helper/docs/features/commands.md +11 -11
  5. package/bundled/qc-helper/docs/features/markdown-rendering.md +21 -1
  6. package/bundled/qc-helper/docs/overview.md +4 -4
  7. package/bundled/qc-helper/docs/quickstart.md +4 -4
  8. package/bundled/qc-helper/docs/support/Uninstall.md +19 -1
  9. package/bundled/qc-helper/docs/support/troubleshooting.md +2 -1
  10. package/chunks/{agent-ZJHHICAC.js → agent-SXS4NQWS.js} +18 -22
  11. package/chunks/{anthropicContentGenerator-M45RXZVS.js → anthropicContentGenerator-4QBVSFSJ.js} +5 -5
  12. package/chunks/{askUserQuestion-TGRD7FNQ.js → askUserQuestion-NOOLRWCJ.js} +5 -7
  13. package/chunks/{ca-6RSCDYUS.js → ca-WRHFBIDH.js} +38 -3
  14. package/chunks/{chunk-SOGUPKP6.js → chunk-5RNZ2QKF.js} +3 -5
  15. package/chunks/{chunk-2KEXT6RB.js → chunk-6KH2Q7XN.js} +91245 -78527
  16. package/chunks/{chunk-GVWPJCXU.js → chunk-6VFG3EUJ.js} +1 -1
  17. package/chunks/{chunk-NQ3E7YLD.js → chunk-AVLOK27J.js} +42 -8
  18. package/chunks/{chunk-JBSYXHJF.js → chunk-BBTV54KB.js} +2 -2
  19. package/chunks/{chunk-3BJBCG2K.js → chunk-C6WMLUNB.js} +1 -1
  20. package/chunks/{chunk-TDZCEIK6.js → chunk-D46KOV3C.js} +1 -1
  21. package/chunks/{chunk-NJJER6E2.js → chunk-ERREX2ES.js} +10 -6
  22. package/chunks/{chunk-HX3JRTWL.js → chunk-F5ORN4YO.js} +1 -1
  23. package/chunks/{chunk-C5CUHYSM.js → chunk-F6FLCHCS.js} +895 -490
  24. package/chunks/{chunk-JKUAX6UT.js → chunk-G763GDO6.js} +125 -12
  25. package/chunks/{chunk-OIL7KDWV.js → chunk-GBEPNWYB.js} +1 -1
  26. package/chunks/{chunk-G4K6P5KN.js → chunk-JMLIPZUU.js} +3 -3
  27. package/chunks/{chunk-OJFMTECH.js → chunk-JSYEZAYV.js} +2 -2
  28. package/chunks/{chunk-AKBFRR6J.js → chunk-K5PGHDBN.js} +132 -112
  29. package/chunks/{chunk-5JBZM7FZ.js → chunk-KOA52UTF.js} +6 -6
  30. package/chunks/{chunk-QVJ33ZBG.js → chunk-MVX64PNU.js} +1 -1
  31. package/chunks/{chunk-PLYRQYKC.js → chunk-NQZ33PWX.js} +11 -11
  32. package/chunks/{chunk-EY6BDW7Y.js → chunk-PLYZAP4W.js} +45 -9
  33. package/chunks/{chunk-ACBGEKB7.js → chunk-R5PDRHEF.js} +2 -1
  34. package/chunks/{chunk-6O244QKR.js → chunk-SCHRFI7O.js} +1 -1
  35. package/chunks/{chunk-GJHMAWS7.js → chunk-SHUT5MQY.js} +1 -1
  36. package/chunks/{chunk-RQW7WUJR.js → chunk-UABFCMPA.js} +34 -6
  37. package/chunks/{chunk-33RDTIU6.js → chunk-UFC57OYT.js} +3 -5
  38. package/chunks/{chunk-NP3ICQCN.js → chunk-USE2VQ5P.js} +1 -1
  39. package/chunks/{chunk-QWSRH265.js → chunk-WFVXF3OM.js} +776 -776
  40. package/chunks/{chunk-X2474BTT.js → chunk-ZW7GBCRE.js} +147 -10
  41. package/chunks/{computer-use-NAHQPV2L.js → computer-use-CT6MU6P3.js} +51 -18
  42. package/chunks/contextCommand-YODJQYIV.js +46 -0
  43. package/chunks/{cron-create-V3UK2SJN.js → cron-create-PIPMXQN4.js} +5 -7
  44. package/chunks/{cron-delete-MANALPCP.js → cron-delete-6Y5XIDMS.js} +5 -7
  45. package/chunks/{cron-list-UDIYK3B3.js → cron-list-A4WNRUWZ.js} +5 -7
  46. package/chunks/{de-APURNJ3I.js → de-M5RPB2NB.js} +38 -3
  47. package/chunks/{dist-XTTPOFAH.js → dist-BXDUQ2QY.js} +3 -4
  48. package/chunks/{dist-AHZNZWRI.js → dist-R2SXPG74.js} +4 -5
  49. package/chunks/{dist-ATAKC63R.js → dist-TE5QKMGR.js} +3 -4
  50. package/chunks/{dist-6RUZ2JD6.js → dist-ZMQ4TXD5.js} +3 -4
  51. package/chunks/{edit-JWXCQ4KK.js → edit-A4YK7AIB.js} +22 -27
  52. package/chunks/{en-FYO57HJW.js → en-UMYKQAZE.js} +46 -3
  53. package/chunks/{enter-worktree-G4CJXPT4.js → enter-worktree-VNEQINLC.js} +20 -25
  54. package/chunks/{exit-worktree-MYZ2FGU2.js → exit-worktree-AVSMXC33.js} +20 -25
  55. package/chunks/{exitPlanMode-ELJ6FSMU.js → exitPlanMode-5SQYVROD.js} +20 -25
  56. package/chunks/{fr-32YHQZIS.js → fr-MPYXXXPW.js} +38 -3
  57. package/chunks/{geminiContentGenerator-3LR7MKCQ.js → geminiContentGenerator-CR2WGARL.js} +5 -5
  58. package/chunks/{getMachineId-bsd-GS3V2GK7.js → getMachineId-bsd-F7GNPTER.js} +1 -1
  59. package/chunks/{getMachineId-darwin-ZQB4Q7EW.js → getMachineId-darwin-T73DJL27.js} +1 -1
  60. package/chunks/{getMachineId-linux-JQ4NN4DN.js → getMachineId-linux-MKQTFPQM.js} +1 -1
  61. package/chunks/{getMachineId-unsupported-U7H4V4HJ.js → getMachineId-unsupported-MUR5KOQE.js} +1 -1
  62. package/chunks/{getMachineId-win-VHUZGBQ3.js → getMachineId-win-CDYFC6ZM.js} +1 -1
  63. package/chunks/{glob-CANUAUTC.js → glob-5V32KOG5.js} +20 -25
  64. package/chunks/{grep-WZWNJRDX.js → grep-PUTEPBR4.js} +20 -25
  65. package/chunks/{ja-PEUXN4XT.js → ja-NFZ32AB3.js} +38 -3
  66. package/chunks/{keychain-token-storage-3552ENXE.js → keychain-token-storage-UHGOCDD6.js} +3 -3
  67. package/chunks/{ls-T4SVZWR6.js → ls-34DLNYCD.js} +6 -8
  68. package/chunks/{lsp-U4ZQLNIS.js → lsp-NCDEHH3V.js} +5 -7
  69. package/chunks/{monitor-CCKNOUFG.js → monitor-EJBR5VCR.js} +20 -25
  70. package/chunks/{notebook-edit-XDUY5Q4I.js → notebook-edit-DZHGPP2L.js} +21 -26
  71. package/chunks/{openaiContentGenerator-N3O3MYIT.js → openaiContentGenerator-4QNV3CHM.js} +12 -14
  72. package/chunks/{pt-2INS7YVC.js → pt-BR43FRBA.js} +38 -3
  73. package/chunks/{qwenContentGenerator-DEOIWKVH.js → qwenContentGenerator-3XOCEMQO.js} +20 -24
  74. package/chunks/{qwenOAuth2-LKXG7XVO.js → qwenOAuth2-KRJT35QH.js} +5 -5
  75. package/chunks/{read-file-BRNXGILN.js → read-file-VZ2SQQIX.js} +9 -11
  76. package/chunks/ripGrep-SBIZCPOL.js +42 -0
  77. package/chunks/{ru-6CQ5HNHB.js → ru-DQCW2KHD.js} +38 -3
  78. package/chunks/{scheduler-SSFABMN5.js → scheduler-H32DZVDV.js} +18 -22
  79. package/chunks/{send-message-GFYV7WLL.js → send-message-YYF56TS7.js} +5 -7
  80. package/chunks/{serve-B5O72CRN.js → serve-56G4B5W6.js} +21 -25
  81. package/chunks/{shell-SGYNBVMK.js → shell-Q77KNP4N.js} +18 -22
  82. package/chunks/{skill-V7Y6DOFB.js → skill-CLWFJYBG.js} +88 -25
  83. package/chunks/{src-OKFFQGXB.js → src-47L2LUOU.js} +90 -33
  84. package/chunks/{syntheticOutput-DM43O6TY.js → syntheticOutput-T5SWX3YF.js} +4 -5
  85. package/chunks/{task-stop-WKP5OB3V.js → task-stop-3VHAQMYM.js} +5 -7
  86. package/chunks/{todoWrite-GHL6DCLP.js → todoWrite-EAGJGKO5.js} +7 -9
  87. package/chunks/{tool-search-7MHT3HGM.js → tool-search-Q75AYDTP.js} +27 -15
  88. package/chunks/{web-fetch-SZIV74ZX.js → web-fetch-SS6IKK6N.js} +7 -9
  89. package/chunks/{write-file-ARS2Z6BJ.js → write-file-RENGC25N.js} +23 -28
  90. package/chunks/{zh-ZHZCMIRG.js → zh-6VFXOAR5.js} +49 -3
  91. package/chunks/{zh-TW-SSL3ATVZ.js → zh-TW-IQZ4AD5M.js} +45 -3
  92. package/cli.js +8153 -4156
  93. package/examples/agent/agents/diary.md +86 -0
  94. package/examples/agent/qwen-extension.json +4 -0
  95. package/examples/commands/commands/fs/grep-code.md +3 -0
  96. package/examples/commands/qwen-extension.json +4 -0
  97. package/examples/context/QWEN.md +8 -0
  98. package/examples/context/qwen-extension.json +4 -0
  99. package/examples/mcp-server/example.ts +60 -0
  100. package/examples/mcp-server/package.json +18 -0
  101. package/examples/mcp-server/qwen-extension.json +11 -0
  102. package/examples/mcp-server/tsconfig.json +13 -0
  103. package/examples/skills/qwen-extension.json +4 -0
  104. package/examples/skills/skills/synonyms/SKILL.md +48 -0
  105. package/locales/ca.js +64 -4
  106. package/locales/de.js +63 -4
  107. package/locales/en.js +75 -4
  108. package/locales/fr.js +65 -4
  109. package/locales/ja.js +61 -4
  110. package/locales/pt.js +64 -4
  111. package/locales/ru.js +62 -4
  112. package/locales/zh-TW.js +70 -4
  113. package/locales/zh.js +74 -4
  114. package/package.json +3 -2
  115. package/chunks/chunk-24YKA2DA.js +0 -233
  116. package/chunks/chunk-6RQTH7UQ.js +0 -115
  117. package/chunks/chunk-7TQVELRB.js +0 -10412
  118. package/chunks/chunk-W57YDFU5.js +0 -41
  119. package/chunks/contextCommand-7KJT3UJS.js +0 -50
  120. package/chunks/ripGrep-ZRY5PKUZ.js +0 -46
@@ -14,30 +14,25 @@ import {
14
14
  import {
15
15
  require_hasown
16
16
  } from "./chunk-UWCTAVOD.js";
17
- import {
18
- safeJsonStringify
19
- } from "./chunk-W57YDFU5.js";
20
17
  import {
21
18
  DEFAULT_QWEN_MODEL,
22
19
  MAINLINE_CODER_MODEL
23
20
  } from "./chunk-OFEVLU4C.js";
24
21
  import {
25
- isAutoMemPath
26
- } from "./chunk-NQ3E7YLD.js";
22
+ isAnyAutoMemPath
23
+ } from "./chunk-AVLOK27J.js";
27
24
  import {
28
25
  InstallationManager
29
- } from "./chunk-OJFMTECH.js";
26
+ } from "./chunk-JSYEZAYV.js";
30
27
  import {
31
28
  STRUCTURED_OUTPUT_REDACTED_ARGS
32
- } from "./chunk-SOGUPKP6.js";
29
+ } from "./chunk-5RNZ2QKF.js";
33
30
  import {
31
+ BaseDeclarativeTool,
32
+ BaseToolInvocation,
34
33
  ToolDisplayNames,
35
34
  ToolNames
36
- } from "./chunk-6RQTH7UQ.js";
37
- import {
38
- BaseDeclarativeTool,
39
- BaseToolInvocation
40
- } from "./chunk-JKUAX6UT.js";
35
+ } from "./chunk-G763GDO6.js";
41
36
  import {
42
37
  DEFAULT_OPENAI_BASE_URL,
43
38
  convertSchema,
@@ -45,7 +40,7 @@ import {
45
40
  runtimeDiagnostics,
46
41
  safeJsonParse,
47
42
  tokenLimit
48
- } from "./chunk-TDZCEIK6.js";
43
+ } from "./chunk-D46KOV3C.js";
49
44
  import {
50
45
  FinishReason,
51
46
  GenerateContentResponse
@@ -65,7 +60,7 @@ import {
65
60
  setSessionContext,
66
61
  shortenPath,
67
62
  unescapePath
68
- } from "./chunk-ACBGEKB7.js";
63
+ } from "./chunk-R5PDRHEF.js";
69
64
  import {
70
65
  require_dist
71
66
  } from "./chunk-ZERZSAZL.js";
@@ -86,7 +81,7 @@ import {
86
81
  isSpanContextValid,
87
82
  metrics,
88
83
  trace
89
- } from "./chunk-QWSRH265.js";
84
+ } from "./chunk-WFVXF3OM.js";
90
85
  import {
91
86
  __qwen_dirname,
92
87
  init_esbuild_shims
@@ -48138,19 +48133,19 @@ var require_getMachineId = __commonJS({
48138
48133
  if (!getMachineIdImpl) {
48139
48134
  switch (process3.platform) {
48140
48135
  case "darwin":
48141
- getMachineIdImpl = (await import("./getMachineId-darwin-ZQB4Q7EW.js")).getMachineId;
48136
+ getMachineIdImpl = (await import("./getMachineId-darwin-T73DJL27.js")).getMachineId;
48142
48137
  break;
48143
48138
  case "linux":
48144
- getMachineIdImpl = (await import("./getMachineId-linux-JQ4NN4DN.js")).getMachineId;
48139
+ getMachineIdImpl = (await import("./getMachineId-linux-MKQTFPQM.js")).getMachineId;
48145
48140
  break;
48146
48141
  case "freebsd":
48147
- getMachineIdImpl = (await import("./getMachineId-bsd-GS3V2GK7.js")).getMachineId;
48142
+ getMachineIdImpl = (await import("./getMachineId-bsd-F7GNPTER.js")).getMachineId;
48148
48143
  break;
48149
48144
  case "win32":
48150
- getMachineIdImpl = (await import("./getMachineId-win-VHUZGBQ3.js")).getMachineId;
48145
+ getMachineIdImpl = (await import("./getMachineId-win-CDYFC6ZM.js")).getMachineId;
48151
48146
  break;
48152
48147
  default:
48153
- getMachineIdImpl = (await import("./getMachineId-unsupported-U7H4V4HJ.js")).getMachineId;
48148
+ getMachineIdImpl = (await import("./getMachineId-unsupported-MUR5KOQE.js")).getMachineId;
48154
48149
  break;
48155
48150
  }
48156
48151
  }
@@ -62731,6 +62726,7 @@ var EVENT_IDE_CONNECTION = "qwen-code.ide_connection";
62731
62726
  var EVENT_CHAT_COMPRESSION = "qwen-code.chat_compression";
62732
62727
  var EVENT_CONTENT_RETRY = "qwen-code.chat.content_retry";
62733
62728
  var EVENT_CONTENT_RETRY_FAILURE = "qwen-code.chat.content_retry_failure";
62729
+ var EVENT_API_RETRY = "qwen-code.api_retry";
62734
62730
  var EVENT_CONVERSATION_FINISHED = "qwen-code.conversation_finished";
62735
62731
  var EVENT_FILE_OPERATION = "qwen-code.file_operation";
62736
62732
  var EVENT_MODEL_SLASH_COMMAND = "qwen-code.slash_command.model";
@@ -62752,6 +62748,7 @@ var SPAN_TOOL = "qwen-code.tool";
62752
62748
  var SPAN_TOOL_EXECUTION = "qwen-code.tool.execution";
62753
62749
  var SPAN_TOOL_BLOCKED_ON_USER = "qwen-code.tool.blocked_on_user";
62754
62750
  var SPAN_HOOK = "qwen-code.hook";
62751
+ var SPAN_SUBAGENT = "qwen-code.subagent";
62755
62752
 
62756
62753
  // packages/core/src/telemetry/metrics.ts
62757
62754
  var TOOL_CALL_COUNT = `${SERVICE_NAME}.tool.call.count`;
@@ -62764,6 +62761,7 @@ var FILE_OPERATION_COUNT = `${SERVICE_NAME}.file.operation.count`;
62764
62761
  var INVALID_CHUNK_COUNT = `${SERVICE_NAME}.chat.invalid_chunk.count`;
62765
62762
  var CONTENT_RETRY_COUNT = `${SERVICE_NAME}.chat.content_retry.count`;
62766
62763
  var CONTENT_RETRY_FAILURE_COUNT = `${SERVICE_NAME}.chat.content_retry_failure.count`;
62764
+ var API_RETRY_COUNT = `${SERVICE_NAME}.api.retry.count`;
62767
62765
  var MODEL_SLASH_COMMAND_CALL_COUNT = `${SERVICE_NAME}.slash_command.model.call_count`;
62768
62766
  var SUBAGENT_EXECUTION_COUNT = `${SERVICE_NAME}.subagent.execution.count`;
62769
62767
  var ARENA_SESSION_COUNT = `${SERVICE_NAME}.arena.session.count`;
@@ -62853,6 +62851,12 @@ var COUNTER_DEFINITIONS = {
62853
62851
  assign: /* @__PURE__ */ __name((c) => contentRetryFailureCounter = c, "assign"),
62854
62852
  attributes: {}
62855
62853
  },
62854
+ [API_RETRY_COUNT]: {
62855
+ description: "Counts HTTP-status retries (429/5xx) at LLM call sites, emitted by retryWithBackoff onRetry callback.",
62856
+ valueType: ValueType.INT,
62857
+ assign: /* @__PURE__ */ __name((c) => apiRetryCounter = c, "assign"),
62858
+ attributes: {}
62859
+ },
62856
62860
  [MODEL_SLASH_COMMAND_CALL_COUNT]: {
62857
62861
  description: "Counts model slash command calls.",
62858
62862
  valueType: ValueType.INT,
@@ -63010,6 +63014,7 @@ var chatCompressionCounter;
63010
63014
  var invalidChunkCounter;
63011
63015
  var contentRetryCounter;
63012
63016
  var contentRetryFailureCounter;
63017
+ var apiRetryCounter;
63013
63018
  var subagentExecutionCounter;
63014
63019
  var modelSlashCommandCallCounter;
63015
63020
  var startupTimeHistogram;
@@ -63216,6 +63221,14 @@ function recordContentRetryFailure(config) {
63216
63221
  );
63217
63222
  }
63218
63223
  __name(recordContentRetryFailure, "recordContentRetryFailure");
63224
+ function recordApiRetry(config, attributes) {
63225
+ if (!apiRetryCounter || !isMetricsInitialized) return;
63226
+ apiRetryCounter.add(1, {
63227
+ ...baseMetricDefinition.getCommonAttributes(config),
63228
+ ...attributes
63229
+ });
63230
+ }
63231
+ __name(recordApiRetry, "recordApiRetry");
63219
63232
  function recordModelSlashCommand(config, event) {
63220
63233
  if (!modelSlashCommandCallCounter || !isMetricsInitialized) return;
63221
63234
  modelSlashCommandCallCounter.add(1, {
@@ -63591,6 +63604,30 @@ function isInternalPromptId(promptId) {
63591
63604
  }
63592
63605
  __name(isInternalPromptId, "isInternalPromptId");
63593
63606
 
63607
+ // packages/core/src/utils/safeJsonStringify.ts
63608
+ init_esbuild_shims();
63609
+ function safeJsonStringify(obj, space) {
63610
+ const ancestors = [];
63611
+ return JSON.stringify(
63612
+ obj,
63613
+ function(_key, value) {
63614
+ if (typeof value !== "object" || value === null) {
63615
+ return value;
63616
+ }
63617
+ while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {
63618
+ ancestors.pop();
63619
+ }
63620
+ if (ancestors.includes(value)) {
63621
+ return "[Circular]";
63622
+ }
63623
+ ancestors.push(value);
63624
+ return value;
63625
+ },
63626
+ space
63627
+ );
63628
+ }
63629
+ __name(safeJsonStringify, "safeJsonStringify");
63630
+
63594
63631
  // packages/core/src/telemetry/qwen-logger/qwen-logger.ts
63595
63632
  init_esbuild_shims();
63596
63633
  var import_https_proxy_agent = __toESM(require_dist(), 1);
@@ -64738,6 +64775,50 @@ var ContentRetryEvent = class {
64738
64775
  this.model = model;
64739
64776
  }
64740
64777
  };
64778
+ var ApiRetryEvent = class {
64779
+ static {
64780
+ __name(this, "ApiRetryEvent");
64781
+ }
64782
+ "event.name";
64783
+ "event.timestamp";
64784
+ // ISO 8601
64785
+ model;
64786
+ prompt_id;
64787
+ attempt_number;
64788
+ // 1-based monotonic counter (matches ALS retryContext.attempt)
64789
+ error_type;
64790
+ error_message;
64791
+ status_code;
64792
+ retry_delay_ms;
64793
+ /**
64794
+ * Reports the backoff delay following this failed attempt (NOT the attempt's
64795
+ * own duration — that lives on the corresponding `qwen-code.llm_request`
64796
+ * span's `duration_ms` attribute). Set equal to `retry_delay_ms` so the
64797
+ * LogToSpanProcessor bridge span visualises the sleep window between the
64798
+ * failed and next attempt in the trace timeline.
64799
+ */
64800
+ duration_ms;
64801
+ /**
64802
+ * Name of the subagent that issued the retrying request, or undefined when
64803
+ * the request originates from the main conversation. Read from
64804
+ * `subagentNameContext.getStore()` at the caller site (subagentNameContext
64805
+ * is still active inside `retry.ts`'s catch block where `onRetry` fires).
64806
+ */
64807
+ subagent_name;
64808
+ constructor(opts) {
64809
+ this["event.name"] = "api_retry";
64810
+ this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
64811
+ this.model = opts.model;
64812
+ this.prompt_id = opts.promptId;
64813
+ this.attempt_number = opts.attemptNumber;
64814
+ this.error_message = opts.error instanceof Error ? opts.error.message : String(opts.error ?? "unknown error");
64815
+ this.error_type = opts.error instanceof Error ? opts.error.constructor.name : void 0;
64816
+ this.status_code = opts.statusCode;
64817
+ this.retry_delay_ms = opts.retryDelayMs;
64818
+ this.duration_ms = opts.retryDelayMs;
64819
+ this.subagent_name = opts.subagentName;
64820
+ }
64821
+ };
64741
64822
  var ContentRetryFailureEvent = class {
64742
64823
  static {
64743
64824
  __name(this, "ContentRetryFailureEvent");
@@ -66692,367 +66773,6 @@ function randomHexString(length) {
66692
66773
  }
66693
66774
  __name(randomHexString, "randomHexString");
66694
66775
 
66695
- // packages/core/src/telemetry/log-to-span-processor.ts
66696
- var EXPORT_TIMEOUT_MS = 3e4;
66697
- var DEFAULT_MAX_BUFFER_SIZE = 1e4;
66698
- var BUFFER_OVERFLOW_WARNING_INTERVAL_MS = 3e4;
66699
- var LOG_EVENT_ERROR_STATUS_MESSAGE = "Log event recorded error";
66700
- var DEFAULT_LOG_SPAN_NAME = "log.event";
66701
- var MAX_SPAN_NAME_LENGTH = 128;
66702
- var SENSITIVE_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
66703
- "error",
66704
- "error.message",
66705
- "error_message",
66706
- "prompt",
66707
- "function_args",
66708
- "response_text"
66709
- ]);
66710
- var defaultDiagnosticsSink = /* @__PURE__ */ __name((message) => {
66711
- process.stderr.write(`${message}
66712
- `);
66713
- }, "defaultDiagnosticsSink");
66714
- var LogToSpanProcessor = class {
66715
- constructor(spanExporter, flushIntervalMsOrOptions = 5e3, maxBufferSize = DEFAULT_MAX_BUFFER_SIZE) {
66716
- this.spanExporter = spanExporter;
66717
- if (typeof flushIntervalMsOrOptions === "number") {
66718
- this.flushIntervalMs = flushIntervalMsOrOptions;
66719
- this.includeSensitiveSpanAttributes = false;
66720
- this.maxBufferSize = normalizeMaxBufferSize(maxBufferSize);
66721
- this.diagnosticsSink = defaultDiagnosticsSink;
66722
- } else {
66723
- this.flushIntervalMs = flushIntervalMsOrOptions.flushIntervalMs ?? 5e3;
66724
- this.includeSensitiveSpanAttributes = flushIntervalMsOrOptions.includeSensitiveSpanAttributes ?? false;
66725
- this.maxBufferSize = normalizeMaxBufferSize(
66726
- flushIntervalMsOrOptions.maxBufferSize
66727
- );
66728
- this.diagnosticsSink = flushIntervalMsOrOptions.diagnosticsSink ?? defaultDiagnosticsSink;
66729
- }
66730
- this.flushTimer = setInterval(() => {
66731
- void this.flush();
66732
- }, this.flushIntervalMs);
66733
- this.flushTimer.unref();
66734
- }
66735
- static {
66736
- __name(this, "LogToSpanProcessor");
66737
- }
66738
- buffer = [];
66739
- flushTimer;
66740
- inFlightExport;
66741
- flushIntervalMs;
66742
- cachedSessionId;
66743
- cachedTraceId;
66744
- includeSensitiveSpanAttributes;
66745
- maxBufferSize;
66746
- diagnosticsSink;
66747
- lastBufferOverflowWarningMs;
66748
- droppedSpansSinceLastBufferWarning = 0;
66749
- totalDroppedSpans = 0;
66750
- isShutdown = false;
66751
- onEmit(logRecord) {
66752
- if (this.isShutdown) {
66753
- return;
66754
- }
66755
- const name = deriveSpanName(logRecord);
66756
- const startTime = logRecord.hrTime;
66757
- const attributes = {};
66758
- if (logRecord.attributes) {
66759
- for (const [key, value] of Object.entries(logRecord.attributes)) {
66760
- if (value !== void 0 && value !== null && (this.includeSensitiveSpanAttributes || !SENSITIVE_ATTRIBUTE_KEYS.has(key))) {
66761
- attributes[key] = typeof value === "object" ? safeStringify(value) : value;
66762
- }
66763
- }
66764
- }
66765
- attributes["log.bridge"] = true;
66766
- if (logRecord.severityNumber !== void 0) {
66767
- attributes["log.severity_number"] = logRecord.severityNumber;
66768
- }
66769
- if (logRecord.severityText) {
66770
- attributes["log.severity_text"] = logRecord.severityText;
66771
- }
66772
- let endTime = startTime;
66773
- const durationMs = logRecord.attributes?.["duration_ms"];
66774
- if (typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs > 0) {
66775
- const [secs, nanos] = startTime;
66776
- const durationNanos = durationMs * 1e6;
66777
- const endNanos = nanos + durationNanos;
66778
- endTime = [secs + Math.floor(endNanos / 1e9), endNanos % 1e9];
66779
- }
66780
- const parentSpanContext = getValidParentSpanContext(logRecord.spanContext);
66781
- const sessionId = logRecord.attributes?.["session.id"] || getCurrentSessionId();
66782
- let traceId;
66783
- if (parentSpanContext) {
66784
- traceId = parentSpanContext.traceId;
66785
- } else if (sessionId) {
66786
- const sid = String(sessionId);
66787
- if (sid !== this.cachedSessionId) {
66788
- this.cachedSessionId = sid;
66789
- this.cachedTraceId = deriveTraceId(sid);
66790
- }
66791
- traceId = this.cachedTraceId;
66792
- } else {
66793
- traceId = randomHexString(32);
66794
- }
66795
- const spanId = randomSpanId();
66796
- this.buffer.push({
66797
- name,
66798
- kind: SpanKind.INTERNAL,
66799
- spanContext: /* @__PURE__ */ __name(() => ({
66800
- traceId,
66801
- spanId,
66802
- traceFlags: parentSpanContext?.traceFlags ?? TraceFlags.SAMPLED
66803
- }), "spanContext"),
66804
- startTime,
66805
- endTime,
66806
- duration: hrTimeDiff(startTime, endTime),
66807
- attributes,
66808
- status: deriveSpanStatus(logRecord.attributes),
66809
- events: [],
66810
- links: [],
66811
- resource: logRecord.resource ?? (0, import_resources.resourceFromAttributes)({}),
66812
- instrumentationScope: logRecord.instrumentationScope ?? {
66813
- name: SERVICE_NAME,
66814
- version: ""
66815
- },
66816
- ended: true,
66817
- parentSpanContext,
66818
- droppedAttributesCount: 0,
66819
- droppedEventsCount: 0,
66820
- droppedLinksCount: 0,
66821
- recordException: /* @__PURE__ */ __name(() => {
66822
- }, "recordException")
66823
- });
66824
- if (this.buffer.length > this.maxBufferSize) {
66825
- const droppedSpanCount = this.buffer.length - this.maxBufferSize;
66826
- this.buffer.splice(0, droppedSpanCount);
66827
- this.warnBufferOverflow(droppedSpanCount);
66828
- }
66829
- }
66830
- warnBufferOverflow(droppedSpanCount) {
66831
- this.droppedSpansSinceLastBufferWarning += droppedSpanCount;
66832
- this.totalDroppedSpans += droppedSpanCount;
66833
- const now = Date.now();
66834
- if (this.lastBufferOverflowWarningMs !== void 0 && now - this.lastBufferOverflowWarningMs < BUFFER_OVERFLOW_WARNING_INTERVAL_MS) {
66835
- return;
66836
- }
66837
- this.emitBufferOverflowWarning(now);
66838
- }
66839
- emitBufferOverflowWarning(now = Date.now()) {
66840
- if (this.droppedSpansSinceLastBufferWarning === 0) {
66841
- return;
66842
- }
66843
- const droppedSinceLastWarning = this.droppedSpansSinceLastBufferWarning;
66844
- this.droppedSpansSinceLastBufferWarning = 0;
66845
- this.lastBufferOverflowWarningMs = now;
66846
- this.emitDiagnostic(
66847
- `[LogToSpan] buffer exceeded max size (${this.maxBufferSize}); dropped ${droppedSinceLastWarning} oldest span(s) since last warning, ${this.totalDroppedSpans} total`
66848
- );
66849
- }
66850
- /**
66851
- * Route a diagnostic message to the configured sink, swallowing any sink
66852
- * error so a misbehaving sink can never interrupt telemetry ingestion.
66853
- *
66854
- * Tradeoff: when the sink itself is broken (e.g. file-logger failing on
66855
- * EACCES), bridge-specific diagnostics go dark. We accept that — the host
66856
- * surfaces overall logging health via `isDebugLoggingDegraded()`, and
66857
- * falling back to stderr here would re-introduce the TUI-pollution this
66858
- * sink injection was added to prevent.
66859
- */
66860
- emitDiagnostic(message) {
66861
- try {
66862
- this.diagnosticsSink(message);
66863
- } catch {
66864
- }
66865
- }
66866
- flush() {
66867
- if (this.inFlightExport) return this.inFlightExport;
66868
- if (this.buffer.length === 0) return Promise.resolve();
66869
- const spans = this.buffer.splice(0);
66870
- const exportPromise = new Promise((resolve2) => {
66871
- const timeout = setTimeout(() => {
66872
- this.emitDiagnostic(
66873
- `[LogToSpan] export timeout after ${EXPORT_TIMEOUT_MS}ms (${spans.length} span(s))`
66874
- );
66875
- resolve2();
66876
- }, EXPORT_TIMEOUT_MS);
66877
- timeout.unref();
66878
- try {
66879
- this.spanExporter.export(
66880
- spans,
66881
- (result) => {
66882
- clearTimeout(timeout);
66883
- if (result.code !== 0) {
66884
- this.emitDiagnostic(
66885
- `[LogToSpan] export failed: code=${result.code} ${formatExportError(result.error)}`
66886
- );
66887
- }
66888
- resolve2();
66889
- }
66890
- );
66891
- } catch (err) {
66892
- clearTimeout(timeout);
66893
- const detail = err instanceof Error ? formatExportError(err) : `error=${JSON.stringify(String(err))}`;
66894
- this.emitDiagnostic(`[LogToSpan] export threw: ${detail}`);
66895
- resolve2();
66896
- }
66897
- });
66898
- this.inFlightExport = exportPromise.finally(() => {
66899
- this.inFlightExport = void 0;
66900
- });
66901
- return this.inFlightExport;
66902
- }
66903
- async shutdown() {
66904
- if (this.isShutdown) {
66905
- return;
66906
- }
66907
- this.isShutdown = true;
66908
- if (this.flushTimer) {
66909
- clearInterval(this.flushTimer);
66910
- this.flushTimer = void 0;
66911
- }
66912
- if (this.inFlightExport) {
66913
- await this.inFlightExport;
66914
- }
66915
- await this.flush();
66916
- this.emitBufferOverflowWarning();
66917
- await this.spanExporter.shutdown();
66918
- }
66919
- async forceFlush() {
66920
- if (this.isShutdown) {
66921
- return;
66922
- }
66923
- if (this.inFlightExport) {
66924
- await this.inFlightExport;
66925
- }
66926
- await this.flush();
66927
- await this.spanExporter.forceFlush?.();
66928
- }
66929
- };
66930
- function normalizeMaxBufferSize(value) {
66931
- if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
66932
- return DEFAULT_MAX_BUFFER_SIZE;
66933
- }
66934
- return Math.floor(value);
66935
- }
66936
- __name(normalizeMaxBufferSize, "normalizeMaxBufferSize");
66937
- function deriveSpanName(logRecord) {
66938
- const eventName = logRecord.attributes?.["event.name"] ?? logRecord.eventName;
66939
- if (typeof eventName === "string" && eventName.trim().length > 0) {
66940
- return sanitizeSpanName(eventName);
66941
- }
66942
- return DEFAULT_LOG_SPAN_NAME;
66943
- }
66944
- __name(deriveSpanName, "deriveSpanName");
66945
- function sanitizeSpanName(body) {
66946
- const rawName = String(body ?? "unknown");
66947
- return rawName.length > MAX_SPAN_NAME_LENGTH ? `${rawName.slice(0, MAX_SPAN_NAME_LENGTH)}...` : rawName;
66948
- }
66949
- __name(sanitizeSpanName, "sanitizeSpanName");
66950
- function getValidParentSpanContext(spanContext) {
66951
- if (!spanContext || !isSpanContextValid(spanContext)) {
66952
- return void 0;
66953
- }
66954
- return spanContext;
66955
- }
66956
- __name(getValidParentSpanContext, "getValidParentSpanContext");
66957
- function safeStringify(value) {
66958
- try {
66959
- return JSON.stringify(value);
66960
- } catch {
66961
- return "[unserializable]";
66962
- }
66963
- }
66964
- __name(safeStringify, "safeStringify");
66965
- function deriveSpanStatus(attrs) {
66966
- if (!attrs) return { code: SpanStatusCode.OK };
66967
- if (!!attrs["error"] || !!attrs["error.message"] || !!attrs["error_message"] || !!attrs["error_type"]) {
66968
- return {
66969
- code: SpanStatusCode.ERROR,
66970
- message: LOG_EVENT_ERROR_STATUS_MESSAGE
66971
- };
66972
- }
66973
- return { code: SpanStatusCode.OK };
66974
- }
66975
- __name(deriveSpanStatus, "deriveSpanStatus");
66976
- function formatExportError(err) {
66977
- if (!err) return 'error="unknown"';
66978
- const extra = err;
66979
- const msg = err.message || err.name || "unknown";
66980
- const parts = [`error=${JSON.stringify(msg)}`];
66981
- if (typeof extra.code === "number") parts.push(`httpCode=${extra.code}`);
66982
- if (typeof extra.data === "string" && extra.data.length > 0) {
66983
- parts.push(`data=${JSON.stringify(extra.data.slice(0, 200))}`);
66984
- }
66985
- return parts.join(" ");
66986
- }
66987
- __name(formatExportError, "formatExportError");
66988
- function hrTimeDiff(start, end) {
66989
- let secs = end[0] - start[0];
66990
- let nanos = end[1] - start[1];
66991
- if (nanos < 0) {
66992
- secs -= 1;
66993
- nanos += 1e9;
66994
- }
66995
- return [secs, nanos];
66996
- }
66997
- __name(hrTimeDiff, "hrTimeDiff");
66998
-
66999
- // packages/core/src/telemetry/tracer.ts
67000
- init_esbuild_shims();
67001
- init_esm();
67002
- var tracer = trace.getTracer(SERVICE_NAME);
67003
- var debugLogger7 = createDebugLogger("OTEL_TRACER");
67004
- var TELEMETRY_WARNING_INTERVAL_MS = 3e4;
67005
- var API_CALL_FAILED_SPAN_STATUS_MESSAGE = "API call failed";
67006
- var API_CALL_ABORTED_SPAN_STATUS_MESSAGE = "API call aborted";
67007
- var lastTelemetryWarningMs;
67008
- var suppressedTelemetryWarnings = 0;
67009
- function warnTelemetryOperationFailed(operation, error) {
67010
- const now = Date.now();
67011
- if (lastTelemetryWarningMs !== void 0 && now - lastTelemetryWarningMs < TELEMETRY_WARNING_INTERVAL_MS) {
67012
- suppressedTelemetryWarnings += 1;
67013
- return;
67014
- }
67015
- const suppressedSuffix = suppressedTelemetryWarnings > 0 ? `; suppressed ${suppressedTelemetryWarnings} similar warning(s)` : "";
67016
- suppressedTelemetryWarnings = 0;
67017
- lastTelemetryWarningMs = now;
67018
- try {
67019
- debugLogger7.warn(
67020
- `OTel span ${operation} failed: ${error instanceof Error ? error.message : String(error)}${suppressedSuffix}`
67021
- );
67022
- } catch {
67023
- }
67024
- }
67025
- __name(warnTelemetryOperationFailed, "warnTelemetryOperationFailed");
67026
- function safeSetStatus(span, status) {
67027
- try {
67028
- span.setStatus(status);
67029
- } catch (error) {
67030
- warnTelemetryOperationFailed("setStatus", error);
67031
- }
67032
- }
67033
- __name(safeSetStatus, "safeSetStatus");
67034
- function shouldForceSampled() {
67035
- const sampler = process.env["OTEL_TRACES_SAMPLER"]?.trim().toLowerCase() ?? "";
67036
- if (!sampler || sampler.startsWith("parentbased_")) {
67037
- if (sampler.includes("always_off")) return false;
67038
- return true;
67039
- }
67040
- return sampler === "always_on";
67041
- }
67042
- __name(shouldForceSampled, "shouldForceSampled");
67043
- function createSessionRootContext(sessionId) {
67044
- const traceId = deriveTraceId(sessionId);
67045
- const spanId = randomSpanId();
67046
- const rootSpan = trace.wrapSpanContext({
67047
- traceId,
67048
- spanId,
67049
- traceFlags: shouldForceSampled() ? TraceFlags.SAMPLED : TraceFlags.NONE,
67050
- isRemote: false
67051
- });
67052
- return trace.setSpan(ROOT_CONTEXT, rootSpan);
67053
- }
67054
- __name(createSessionRootContext, "createSessionRootContext");
67055
-
67056
66776
  // packages/core/src/telemetry/session-tracing.ts
67057
66777
  init_esbuild_shims();
67058
66778
  init_esm();
@@ -67200,7 +66920,7 @@ function clearDetailedSpanState() {
67200
66920
  __name(clearDetailedSpanState, "clearDetailedSpanState");
67201
66921
 
67202
66922
  // packages/core/src/telemetry/session-tracing.ts
67203
- var debugLogger8 = createDebugLogger("SESSION_TRACING");
66923
+ var debugLogger7 = createDebugLogger("SESSION_TRACING");
67204
66924
  function resolveParentContext(parent) {
67205
66925
  if (parent) {
67206
66926
  return trace.setSpan(context.active(), parent.span);
@@ -67219,54 +66939,85 @@ var NOOP_SPAN = trace.wrapSpanContext({
67219
66939
  });
67220
66940
  var interactionContext = new AsyncLocalStorage3();
67221
66941
  var toolContext = new AsyncLocalStorage3();
66942
+ var subagentContext = new AsyncLocalStorage3();
66943
+ function isInNativeSubagentSpan() {
66944
+ const ctx = subagentContext.getStore();
66945
+ return ctx !== void 0 && !ctx.ended;
66946
+ }
66947
+ __name(isInNativeSubagentSpan, "isInNativeSubagentSpan");
67222
66948
  var activeSpans = /* @__PURE__ */ new Map();
67223
66949
  var strongSpans = /* @__PURE__ */ new Map();
67224
66950
  var interactionSequence = 0;
67225
66951
  var lastInteractionCtx;
67226
66952
  var cleanupIntervalStarted = false;
67227
- var SPAN_TTL_MS = 30 * 60 * 1e3;
66953
+ var SPAN_TTL_MS_DEFAULT = 30 * 60 * 1e3;
66954
+ var SPAN_TTL_MS_LONG = 4 * 60 * 60 * 1e3;
66955
+ var LONG_TTL_SUBAGENT_KINDS = /* @__PURE__ */ new Set([
66956
+ "fork",
66957
+ "background"
66958
+ ]);
66959
+ function ttlFor(ctx) {
66960
+ if (ctx.type === "subagent") {
66961
+ const kind = ctx.attributes["qwen-code.subagent.invocation_kind"];
66962
+ if (typeof kind === "string" && LONG_TTL_SUBAGENT_KINDS.has(kind)) {
66963
+ return SPAN_TTL_MS_LONG;
66964
+ }
66965
+ }
66966
+ return SPAN_TTL_MS_DEFAULT;
66967
+ }
66968
+ __name(ttlFor, "ttlFor");
67228
66969
  function sweepStaleSpans(now) {
67229
- const cutoff = now - SPAN_TTL_MS;
67230
66970
  for (const [spanId, weakRef] of activeSpans) {
67231
66971
  const ctx = weakRef.deref();
67232
66972
  if (ctx === void 0) {
67233
66973
  activeSpans.delete(spanId);
67234
66974
  strongSpans.delete(spanId);
67235
- } else if (ctx.startTime < cutoff) {
67236
- if (!ctx.ended) {
67237
- ctx.ended = true;
67238
- const ageMs = now - ctx.startTime;
67239
- const toolName = ctx.attributes["tool.name"];
67240
- const callId = ctx.attributes["tool.call_id"];
67241
- try {
67242
- ctx.span.setAttributes({
67243
- "qwen-code.span.ttl_expired": true,
67244
- "qwen-code.span.duration_ms": ageMs,
67245
- ...ctx.type === "tool.blocked_on_user" ? {
67246
- decision: "aborted",
67247
- source: "system"
67248
- } : {}
67249
- });
67250
- } catch (error) {
67251
- debugLogger8.warn(
67252
- `Failed to stamp TTL attrs on stale span ${spanId}: ${error instanceof Error ? error.message : String(error)}`
67253
- );
67254
- }
67255
- const ctxLabel = toolName && callId ? `${ctx.type} (tool.name=${toolName}, tool.call_id=${callId})` : ctx.type;
67256
- debugLogger8.warn(
67257
- `Stale ${ctxLabel} span ended by TTL safety net (age=${ageMs}ms, spanId=${spanId})`
66975
+ continue;
66976
+ }
66977
+ if (now - ctx.startTime < ttlFor(ctx)) continue;
66978
+ if (!ctx.ended) {
66979
+ ctx.ended = true;
66980
+ const ageMs = now - ctx.startTime;
66981
+ const toolName = ctx.attributes["tool.name"];
66982
+ const callId = ctx.attributes["tool.call_id"];
66983
+ try {
66984
+ ctx.span.setAttributes({
66985
+ "qwen-code.span.ttl_expired": true,
66986
+ "qwen-code.span.duration_ms": ageMs,
66987
+ ...ctx.type === "tool.blocked_on_user" ? {
66988
+ decision: "aborted",
66989
+ source: "system"
66990
+ } : {},
66991
+ ...ctx.type === "subagent" ? {
66992
+ "qwen-code.subagent.status": "aborted",
66993
+ "qwen-code.subagent.terminate_reason": "ttl_swept",
66994
+ // Mirror the subagent-specific duration_ms key that
66995
+ // endSubagentSpan stamps so dashboards querying that
66996
+ // namespace see TTL-swept spans too (they currently
66997
+ // only get the generic qwen-code.span.duration_ms
66998
+ // above). wenshao @ #4410.
66999
+ "qwen-code.subagent.duration_ms": ageMs
67000
+ } : {}
67001
+ });
67002
+ } catch (error) {
67003
+ debugLogger7.warn(
67004
+ `Failed to stamp TTL attrs on stale span ${spanId}: ${error instanceof Error ? error.message : String(error)}`
67005
+ );
67006
+ }
67007
+ const ctxLabel = toolName && callId ? `${ctx.type} (tool.name=${toolName}, tool.call_id=${callId})` : ctx.type;
67008
+ debugLogger7.warn(
67009
+ `Stale ${ctxLabel} span ended by TTL safety net (age=${ageMs}ms, spanId=${spanId})`
67010
+ );
67011
+ try {
67012
+ ctx.span.end();
67013
+ } catch (error) {
67014
+ debugLogger7.warn(
67015
+ `Failed to end stale span ${spanId}: ${error instanceof Error ? error.message : String(error)}`
67258
67016
  );
67259
- try {
67260
- ctx.span.end();
67261
- } catch (error) {
67262
- debugLogger8.warn(
67263
- `Failed to end stale span ${spanId}: ${error instanceof Error ? error.message : String(error)}`
67264
- );
67265
- }
67266
67017
  }
67267
- activeSpans.delete(spanId);
67268
- strongSpans.delete(spanId);
67269
67018
  }
67019
+ activeSpans.delete(spanId);
67020
+ strongSpans.delete(spanId);
67270
67021
  }
67271
67022
  }
67272
67023
  __name(sweepStaleSpans, "sweepStaleSpans");
@@ -67329,7 +67080,13 @@ function startInteractionSpan(config, options) {
67329
67080
  __name(startInteractionSpan, "startInteractionSpan");
67330
67081
  function endInteractionSpan(status, metadata) {
67331
67082
  const spanCtx = interactionContext.getStore() ?? lastInteractionCtx;
67332
- if (!spanCtx || spanCtx.ended) return;
67083
+ if (!spanCtx) return;
67084
+ if (spanCtx.ended) {
67085
+ debugLogger7.debug(
67086
+ `endInteractionSpan: span ${getSpanId(spanCtx.span)} already ended (possible TTL sweep race)`
67087
+ );
67088
+ return;
67089
+ }
67333
67090
  spanCtx.ended = true;
67334
67091
  lastInteractionCtx = void 0;
67335
67092
  const duration = Date.now() - spanCtx.startTime;
@@ -67356,12 +67113,12 @@ function startLLMRequestSpan(model, promptId) {
67356
67113
  if (!isTelemetrySdkInitialized()) {
67357
67114
  return NOOP_SPAN;
67358
67115
  }
67359
- const parentCtx = interactionContext.getStore();
67116
+ const parentCtx = subagentContext.getStore() ?? interactionContext.getStore();
67360
67117
  const ctx = resolveParentContext(parentCtx);
67361
67118
  const attributes = {
67362
67119
  "qwen-code.model": model,
67363
67120
  "qwen-code.prompt_id": promptId,
67364
- "llm_request.context": parentCtx ? "interaction" : "standalone",
67121
+ "llm_request.context": subagentContext.getStore() ? "subagent" : interactionContext.getStore() ? "interaction" : "standalone",
67365
67122
  // Dual-emit OTel GenAI semantic convention (Stable). Private name
67366
67123
  // (qwen-code.model) remains authoritative; gen_ai.* is a compat layer
67367
67124
  // for spec-aware backends. See docs/design/telemetry-llm-request-timing-design.md (D8).
@@ -67387,7 +67144,13 @@ __name(startLLMRequestSpan, "startLLMRequestSpan");
67387
67144
  function endLLMRequestSpan(span, metadata) {
67388
67145
  const spanId = getSpanId(span);
67389
67146
  const spanCtx = activeSpans.get(spanId)?.deref();
67390
- if (!spanCtx || spanCtx.ended) return;
67147
+ if (!spanCtx) return;
67148
+ if (spanCtx.ended) {
67149
+ debugLogger7.debug(
67150
+ `endLLMRequestSpan: span ${spanId} already ended (possible TTL sweep race)`
67151
+ );
67152
+ return;
67153
+ }
67391
67154
  spanCtx.ended = true;
67392
67155
  try {
67393
67156
  const duration = metadata?.durationMs ?? Date.now() - spanCtx.startTime;
@@ -67419,10 +67182,7 @@ function endLLMRequestSpan(span, metadata) {
67419
67182
  endAttributes["retry_total_delay_ms"] = metadata.retryTotalDelayMs;
67420
67183
  }
67421
67184
  if (metadata.ttftMs !== void 0) {
67422
- const samplingMs = Math.max(
67423
- 0,
67424
- duration - metadata.ttftMs - (metadata.requestSetupMs ?? 0)
67425
- );
67185
+ const samplingMs = Math.max(0, duration - metadata.ttftMs);
67426
67186
  endAttributes["sampling_ms"] = samplingMs;
67427
67187
  if (samplingMs > 0 && metadata.outputTokens !== void 0) {
67428
67188
  endAttributes["output_tokens_per_second"] = Math.round(metadata.outputTokens / (samplingMs / 1e3) * 100) / 100;
@@ -67442,14 +67202,14 @@ function endLLMRequestSpan(span, metadata) {
67442
67202
  });
67443
67203
  }
67444
67204
  } catch (error) {
67445
- debugLogger8.warn(
67205
+ debugLogger7.warn(
67446
67206
  `Failed to update LLM request span attributes/status: ${error instanceof Error ? error.message : String(error)}`
67447
67207
  );
67448
67208
  }
67449
67209
  try {
67450
67210
  spanCtx.span.end();
67451
67211
  } catch (error) {
67452
- debugLogger8.warn(
67212
+ debugLogger7.warn(
67453
67213
  `Failed to end LLM request span: ${error instanceof Error ? error.message : String(error)}`
67454
67214
  );
67455
67215
  }
@@ -67461,7 +67221,7 @@ function startToolSpan(toolName, attrs) {
67461
67221
  if (!isTelemetrySdkInitialized()) {
67462
67222
  return NOOP_SPAN;
67463
67223
  }
67464
- const parentCtx = interactionContext.getStore();
67224
+ const parentCtx = subagentContext.getStore() ?? interactionContext.getStore();
67465
67225
  const ctx = resolveParentContext(parentCtx);
67466
67226
  const attributes = {
67467
67227
  "tool.name": toolName,
@@ -67495,7 +67255,13 @@ __name(runInToolSpanContext, "runInToolSpanContext");
67495
67255
  function endToolSpan(span, metadata) {
67496
67256
  const spanId = getSpanId(span);
67497
67257
  const spanCtx = activeSpans.get(spanId)?.deref();
67498
- if (!spanCtx || spanCtx.ended) return;
67258
+ if (!spanCtx) return;
67259
+ if (spanCtx.ended) {
67260
+ debugLogger7.debug(
67261
+ `endToolSpan: span ${spanId} already ended (possible TTL sweep race)`
67262
+ );
67263
+ return;
67264
+ }
67499
67265
  spanCtx.ended = true;
67500
67266
  try {
67501
67267
  const duration = Date.now() - spanCtx.startTime;
@@ -67518,14 +67284,14 @@ function endToolSpan(span, metadata) {
67518
67284
  }
67519
67285
  }
67520
67286
  } catch (error) {
67521
- debugLogger8.warn(
67287
+ debugLogger7.warn(
67522
67288
  `Failed to update tool span attributes/status: ${error instanceof Error ? error.message : String(error)}`
67523
67289
  );
67524
67290
  }
67525
67291
  try {
67526
67292
  spanCtx.span.end();
67527
67293
  } catch (error) {
67528
- debugLogger8.warn(
67294
+ debugLogger7.warn(
67529
67295
  `Failed to end tool span: ${error instanceof Error ? error.message : String(error)}`
67530
67296
  );
67531
67297
  }
@@ -67539,7 +67305,7 @@ function startToolExecutionSpan() {
67539
67305
  }
67540
67306
  const parentCtx = toolContext.getStore();
67541
67307
  if (!parentCtx) {
67542
- debugLogger8.warn(
67308
+ debugLogger7.warn(
67543
67309
  "startToolExecutionSpan called outside runInToolSpanContext \u2014 span will not be parented to tool span"
67544
67310
  );
67545
67311
  }
@@ -67564,7 +67330,13 @@ __name(startToolExecutionSpan, "startToolExecutionSpan");
67564
67330
  function endToolExecutionSpan(span, metadata) {
67565
67331
  const spanId = getSpanId(span);
67566
67332
  const spanCtx = activeSpans.get(spanId)?.deref();
67567
- if (!spanCtx || spanCtx.ended) return;
67333
+ if (!spanCtx) return;
67334
+ if (spanCtx.ended) {
67335
+ debugLogger7.debug(
67336
+ `endToolExecutionSpan: span ${spanId} already ended (possible TTL sweep race)`
67337
+ );
67338
+ return;
67339
+ }
67568
67340
  spanCtx.ended = true;
67569
67341
  try {
67570
67342
  const duration = Date.now() - spanCtx.startTime;
@@ -67587,14 +67359,14 @@ function endToolExecutionSpan(span, metadata) {
67587
67359
  }
67588
67360
  }
67589
67361
  } catch (error) {
67590
- debugLogger8.warn(
67362
+ debugLogger7.warn(
67591
67363
  `Failed to update tool execution span attributes/status: ${error instanceof Error ? error.message : String(error)}`
67592
67364
  );
67593
67365
  }
67594
67366
  try {
67595
67367
  spanCtx.span.end();
67596
67368
  } catch (error) {
67597
- debugLogger8.warn(
67369
+ debugLogger7.warn(
67598
67370
  `Failed to end tool execution span: ${error instanceof Error ? error.message : String(error)}`
67599
67371
  );
67600
67372
  }
@@ -67610,7 +67382,7 @@ function startToolBlockedOnUserSpan(toolSpan, attrs) {
67610
67382
  const parentSpanId = getSpanId(toolSpan);
67611
67383
  const parentSpanCtx = activeSpans.get(parentSpanId)?.deref();
67612
67384
  if (!parentSpanCtx) {
67613
- debugLogger8.debug(
67385
+ debugLogger7.debug(
67614
67386
  "startToolBlockedOnUserSpan: tool span not in activeSpans (already ended?) \u2014 using resolveParentContext fallback"
67615
67387
  );
67616
67388
  }
@@ -67638,7 +67410,13 @@ __name(startToolBlockedOnUserSpan, "startToolBlockedOnUserSpan");
67638
67410
  function endToolBlockedOnUserSpan(span, metadata) {
67639
67411
  const spanId = getSpanId(span);
67640
67412
  const spanCtx = activeSpans.get(spanId)?.deref();
67641
- if (!spanCtx || spanCtx.ended) return;
67413
+ if (!spanCtx) return;
67414
+ if (spanCtx.ended) {
67415
+ debugLogger7.debug(
67416
+ `endToolBlockedOnUserSpan: span ${spanId} already ended (possible TTL sweep race)`
67417
+ );
67418
+ return;
67419
+ }
67642
67420
  spanCtx.ended = true;
67643
67421
  try {
67644
67422
  const duration = Date.now() - spanCtx.startTime;
@@ -67649,14 +67427,14 @@ function endToolBlockedOnUserSpan(span, metadata) {
67649
67427
  endAttributes["source"] = metadata.source;
67650
67428
  spanCtx.span.setAttributes(endAttributes);
67651
67429
  } catch (error) {
67652
- debugLogger8.warn(
67430
+ debugLogger7.warn(
67653
67431
  `Failed to update blocked_on_user span attributes: ${error instanceof Error ? error.message : String(error)}`
67654
67432
  );
67655
67433
  }
67656
67434
  try {
67657
67435
  spanCtx.span.end();
67658
67436
  } catch (error) {
67659
- debugLogger8.warn(
67437
+ debugLogger7.warn(
67660
67438
  `Failed to end blocked_on_user span: ${error instanceof Error ? error.message : String(error)}`
67661
67439
  );
67662
67440
  }
@@ -67669,7 +67447,7 @@ function startHookSpan(opts) {
67669
67447
  return NOOP_SPAN;
67670
67448
  }
67671
67449
  ensureCleanupInterval();
67672
- const parentCtx = toolContext.getStore() ?? interactionContext.getStore() ?? void 0;
67450
+ const parentCtx = toolContext.getStore() ?? subagentContext.getStore() ?? interactionContext.getStore() ?? void 0;
67673
67451
  const ctx = resolveParentContext(parentCtx);
67674
67452
  const attributes = {
67675
67453
  hook_event: opts.hookEvent,
@@ -67698,7 +67476,13 @@ __name(startHookSpan, "startHookSpan");
67698
67476
  function endHookSpan(span, metadata) {
67699
67477
  const spanId = getSpanId(span);
67700
67478
  const spanCtx = activeSpans.get(spanId)?.deref();
67701
- if (!spanCtx || spanCtx.ended) return;
67479
+ if (!spanCtx) return;
67480
+ if (spanCtx.ended) {
67481
+ debugLogger7.debug(
67482
+ `endHookSpan: span ${spanId} already ended (possible TTL sweep race)`
67483
+ );
67484
+ return;
67485
+ }
67702
67486
  spanCtx.ended = true;
67703
67487
  try {
67704
67488
  const duration = Date.now() - spanCtx.startTime;
@@ -67731,14 +67515,14 @@ function endHookSpan(span, metadata) {
67731
67515
  });
67732
67516
  }
67733
67517
  } catch (error) {
67734
- debugLogger8.warn(
67518
+ debugLogger7.warn(
67735
67519
  `Failed to update hook span attributes/status: ${error instanceof Error ? error.message : String(error)}`
67736
67520
  );
67737
67521
  }
67738
67522
  try {
67739
67523
  spanCtx.span.end();
67740
67524
  } catch (error) {
67741
- debugLogger8.warn(
67525
+ debugLogger7.warn(
67742
67526
  `Failed to end hook span: ${error instanceof Error ? error.message : String(error)}`
67743
67527
  );
67744
67528
  }
@@ -67746,6 +67530,139 @@ function endHookSpan(span, metadata) {
67746
67530
  strongSpans.delete(spanId);
67747
67531
  }
67748
67532
  __name(endHookSpan, "endHookSpan");
67533
+ function startSubagentSpan(opts) {
67534
+ if (!isTelemetrySdkInitialized()) return NOOP_SPAN;
67535
+ ensureCleanupInterval();
67536
+ const attributes = {
67537
+ // Spec-aligned (OTel GenAI Agent Spans, Development status).
67538
+ "gen_ai.operation.name": "invoke_agent",
67539
+ "gen_ai.provider.name": SERVICE_NAME,
67540
+ "gen_ai.agent.id": opts.agentId,
67541
+ "gen_ai.agent.name": opts.subagentName,
67542
+ "gen_ai.conversation.id": opts.sessionId,
67543
+ // Vendor (qwen-code-specific). Dual-emit id/name so dashboards already
67544
+ // querying spec keys still work.
67545
+ "qwen-code.subagent.id": opts.agentId,
67546
+ "qwen-code.subagent.name": opts.subagentName,
67547
+ "qwen-code.subagent.invocation_kind": opts.invocationKind,
67548
+ "qwen-code.subagent.is_built_in": opts.isBuiltIn,
67549
+ "qwen-code.subagent.depth": opts.depth
67550
+ };
67551
+ if (opts.modelOverride !== void 0) {
67552
+ attributes["gen_ai.request.model"] = opts.modelOverride;
67553
+ }
67554
+ if (opts.parentAgentId !== void 0) {
67555
+ attributes["qwen-code.subagent.parent_agent_id"] = opts.parentAgentId;
67556
+ }
67557
+ if (opts.invokingRequestId !== void 0) {
67558
+ attributes["qwen-code.subagent.invoking_request_id"] = opts.invokingRequestId;
67559
+ }
67560
+ const tracer2 = getTracer();
67561
+ let span;
67562
+ if (opts.invocationKind === "foreground") {
67563
+ span = tracer2.startSpan(SPAN_SUBAGENT, {
67564
+ kind: SpanKind.INTERNAL,
67565
+ attributes
67566
+ });
67567
+ } else {
67568
+ span = tracer2.startSpan(SPAN_SUBAGENT, {
67569
+ kind: SpanKind.INTERNAL,
67570
+ attributes,
67571
+ root: true,
67572
+ links: opts.invokerSpanContext ? [
67573
+ {
67574
+ context: opts.invokerSpanContext,
67575
+ attributes: { "qwen-code.link.kind": "invoker" }
67576
+ }
67577
+ ] : void 0
67578
+ });
67579
+ }
67580
+ const spanId = getSpanId(span);
67581
+ const spanContextObj = {
67582
+ span,
67583
+ startTime: Date.now(),
67584
+ attributes,
67585
+ type: "subagent"
67586
+ };
67587
+ activeSpans.set(spanId, new WeakRef(spanContextObj));
67588
+ strongSpans.set(spanId, spanContextObj);
67589
+ return span;
67590
+ }
67591
+ __name(startSubagentSpan, "startSubagentSpan");
67592
+ function runInSubagentSpanContext(span, fn) {
67593
+ const spanId = getSpanId(span);
67594
+ const spanCtx = activeSpans.get(spanId)?.deref();
67595
+ if (!spanCtx) return fn();
67596
+ const otelCtxWithSpan = trace.setSpan(context.active(), span);
67597
+ return subagentContext.run(
67598
+ spanCtx,
67599
+ () => toolContext.run(void 0, () => context.with(otelCtxWithSpan, fn))
67600
+ );
67601
+ }
67602
+ __name(runInSubagentSpanContext, "runInSubagentSpanContext");
67603
+ function endSubagentSpan(span, metadata) {
67604
+ const spanId = getSpanId(span);
67605
+ const spanCtx = activeSpans.get(spanId)?.deref();
67606
+ if (!spanCtx) {
67607
+ if (isTelemetrySdkInitialized()) {
67608
+ debugLogger7.warn(
67609
+ `endSubagentSpan: span ${spanId} not found in activeSpans (already swept?) \u2014 intended status=${metadata.status}, reason=${metadata.terminateReason ?? "none"}`
67610
+ );
67611
+ }
67612
+ return;
67613
+ }
67614
+ if (spanCtx.ended) {
67615
+ debugLogger7.warn(
67616
+ `endSubagentSpan: span ${spanId} already ended \u2014 intended status=${metadata.status}, reason=${metadata.terminateReason ?? "none"} (possible TTL sweep race)`
67617
+ );
67618
+ return;
67619
+ }
67620
+ spanCtx.ended = true;
67621
+ try {
67622
+ const duration = Date.now() - spanCtx.startTime;
67623
+ const endAttributes = {
67624
+ duration_ms: duration,
67625
+ "qwen-code.subagent.duration_ms": duration,
67626
+ "qwen-code.subagent.status": metadata.status
67627
+ };
67628
+ if (metadata.terminateReason !== void 0) {
67629
+ endAttributes["qwen-code.subagent.terminate_reason"] = metadata.terminateReason;
67630
+ }
67631
+ if (metadata.resultSummaryPresent !== void 0) {
67632
+ endAttributes["qwen-code.subagent.result_summary_present"] = metadata.resultSummaryPresent;
67633
+ }
67634
+ if (metadata.error !== void 0) {
67635
+ const truncated = truncateSpanError(metadata.error);
67636
+ endAttributes["exception.message"] = truncated;
67637
+ }
67638
+ if (metadata.errorType !== void 0) {
67639
+ endAttributes["error.type"] = metadata.errorType;
67640
+ }
67641
+ spanCtx.span.setAttributes(endAttributes);
67642
+ if (metadata.status === "completed") {
67643
+ spanCtx.span.setStatus({ code: SpanStatusCode.OK });
67644
+ } else if (metadata.status === "failed") {
67645
+ spanCtx.span.setStatus({
67646
+ code: SpanStatusCode.ERROR,
67647
+ message: metadata.error ? truncateSpanError(metadata.error) : "subagent failed"
67648
+ });
67649
+ }
67650
+ } catch (error) {
67651
+ debugLogger7.warn(
67652
+ `Failed to update subagent span attributes/status: ${error instanceof Error ? error.message : String(error)}`
67653
+ );
67654
+ }
67655
+ try {
67656
+ spanCtx.span.end();
67657
+ } catch (error) {
67658
+ debugLogger7.warn(
67659
+ `Failed to end subagent span: ${error instanceof Error ? error.message : String(error)}`
67660
+ );
67661
+ }
67662
+ activeSpans.delete(spanId);
67663
+ strongSpans.delete(spanId);
67664
+ }
67665
+ __name(endSubagentSpan, "endSubagentSpan");
67749
67666
  function getActiveInteractionSpan() {
67750
67667
  const ctx = interactionContext.getStore() ?? lastInteractionCtx;
67751
67668
  if (!ctx || ctx.ended) return void 0;
@@ -67753,6 +67670,372 @@ function getActiveInteractionSpan() {
67753
67670
  }
67754
67671
  __name(getActiveInteractionSpan, "getActiveInteractionSpan");
67755
67672
 
67673
+ // packages/core/src/telemetry/log-to-span-processor.ts
67674
+ var BRIDGE_SKIP_EVENT_NAMES = /* @__PURE__ */ new Set([EVENT_SUBAGENT_EXECUTION]);
67675
+ var EXPORT_TIMEOUT_MS = 3e4;
67676
+ var DEFAULT_MAX_BUFFER_SIZE = 1e4;
67677
+ var BUFFER_OVERFLOW_WARNING_INTERVAL_MS = 3e4;
67678
+ var LOG_EVENT_ERROR_STATUS_MESSAGE = "Log event recorded error";
67679
+ var DEFAULT_LOG_SPAN_NAME = "log.event";
67680
+ var MAX_SPAN_NAME_LENGTH = 128;
67681
+ var SENSITIVE_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
67682
+ "error",
67683
+ "error.message",
67684
+ "error_message",
67685
+ "prompt",
67686
+ "function_args",
67687
+ "response_text"
67688
+ ]);
67689
+ var defaultDiagnosticsSink = /* @__PURE__ */ __name((message) => {
67690
+ process.stderr.write(`${message}
67691
+ `);
67692
+ }, "defaultDiagnosticsSink");
67693
+ var LogToSpanProcessor = class {
67694
+ constructor(spanExporter, flushIntervalMsOrOptions = 5e3, maxBufferSize = DEFAULT_MAX_BUFFER_SIZE) {
67695
+ this.spanExporter = spanExporter;
67696
+ if (typeof flushIntervalMsOrOptions === "number") {
67697
+ this.flushIntervalMs = flushIntervalMsOrOptions;
67698
+ this.includeSensitiveSpanAttributes = false;
67699
+ this.maxBufferSize = normalizeMaxBufferSize(maxBufferSize);
67700
+ this.diagnosticsSink = defaultDiagnosticsSink;
67701
+ } else {
67702
+ this.flushIntervalMs = flushIntervalMsOrOptions.flushIntervalMs ?? 5e3;
67703
+ this.includeSensitiveSpanAttributes = flushIntervalMsOrOptions.includeSensitiveSpanAttributes ?? false;
67704
+ this.maxBufferSize = normalizeMaxBufferSize(
67705
+ flushIntervalMsOrOptions.maxBufferSize
67706
+ );
67707
+ this.diagnosticsSink = flushIntervalMsOrOptions.diagnosticsSink ?? defaultDiagnosticsSink;
67708
+ }
67709
+ this.flushTimer = setInterval(() => {
67710
+ void this.flush();
67711
+ }, this.flushIntervalMs);
67712
+ this.flushTimer.unref();
67713
+ }
67714
+ static {
67715
+ __name(this, "LogToSpanProcessor");
67716
+ }
67717
+ buffer = [];
67718
+ flushTimer;
67719
+ inFlightExport;
67720
+ flushIntervalMs;
67721
+ cachedSessionId;
67722
+ cachedTraceId;
67723
+ includeSensitiveSpanAttributes;
67724
+ maxBufferSize;
67725
+ diagnosticsSink;
67726
+ lastBufferOverflowWarningMs;
67727
+ droppedSpansSinceLastBufferWarning = 0;
67728
+ totalDroppedSpans = 0;
67729
+ isShutdown = false;
67730
+ onEmit(logRecord) {
67731
+ if (this.isShutdown) {
67732
+ return;
67733
+ }
67734
+ const eventName = logRecord.attributes?.["event.name"];
67735
+ if (typeof eventName === "string" && BRIDGE_SKIP_EVENT_NAMES.has(eventName) && isInNativeSubagentSpan()) {
67736
+ return;
67737
+ }
67738
+ const name = deriveSpanName(logRecord);
67739
+ const startTime = logRecord.hrTime;
67740
+ const attributes = {};
67741
+ if (logRecord.attributes) {
67742
+ for (const [key, value] of Object.entries(logRecord.attributes)) {
67743
+ if (value !== void 0 && value !== null && (this.includeSensitiveSpanAttributes || !SENSITIVE_ATTRIBUTE_KEYS.has(key))) {
67744
+ attributes[key] = typeof value === "object" ? safeStringify(value) : value;
67745
+ }
67746
+ }
67747
+ }
67748
+ attributes["log.bridge"] = true;
67749
+ if (logRecord.severityNumber !== void 0) {
67750
+ attributes["log.severity_number"] = logRecord.severityNumber;
67751
+ }
67752
+ if (logRecord.severityText) {
67753
+ attributes["log.severity_text"] = logRecord.severityText;
67754
+ }
67755
+ let endTime = startTime;
67756
+ const durationMs = logRecord.attributes?.["duration_ms"];
67757
+ if (typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs > 0) {
67758
+ const [secs, nanos] = startTime;
67759
+ const durationNanos = durationMs * 1e6;
67760
+ const endNanos = nanos + durationNanos;
67761
+ endTime = [secs + Math.floor(endNanos / 1e9), endNanos % 1e9];
67762
+ }
67763
+ const parentSpanContext = getValidParentSpanContext(logRecord.spanContext);
67764
+ const sessionId = logRecord.attributes?.["session.id"] || getCurrentSessionId();
67765
+ let traceId;
67766
+ if (parentSpanContext) {
67767
+ traceId = parentSpanContext.traceId;
67768
+ } else if (sessionId) {
67769
+ const sid = String(sessionId);
67770
+ if (sid !== this.cachedSessionId) {
67771
+ this.cachedSessionId = sid;
67772
+ this.cachedTraceId = deriveTraceId(sid);
67773
+ }
67774
+ traceId = this.cachedTraceId;
67775
+ } else {
67776
+ traceId = randomHexString(32);
67777
+ }
67778
+ const spanId = randomSpanId();
67779
+ this.buffer.push({
67780
+ name,
67781
+ kind: SpanKind.INTERNAL,
67782
+ spanContext: /* @__PURE__ */ __name(() => ({
67783
+ traceId,
67784
+ spanId,
67785
+ traceFlags: parentSpanContext?.traceFlags ?? TraceFlags.SAMPLED
67786
+ }), "spanContext"),
67787
+ startTime,
67788
+ endTime,
67789
+ duration: hrTimeDiff(startTime, endTime),
67790
+ attributes,
67791
+ status: deriveSpanStatus(logRecord.attributes),
67792
+ events: [],
67793
+ links: [],
67794
+ resource: logRecord.resource ?? (0, import_resources.resourceFromAttributes)({}),
67795
+ instrumentationScope: logRecord.instrumentationScope ?? {
67796
+ name: SERVICE_NAME,
67797
+ version: ""
67798
+ },
67799
+ ended: true,
67800
+ parentSpanContext,
67801
+ droppedAttributesCount: 0,
67802
+ droppedEventsCount: 0,
67803
+ droppedLinksCount: 0,
67804
+ recordException: /* @__PURE__ */ __name(() => {
67805
+ }, "recordException")
67806
+ });
67807
+ if (this.buffer.length > this.maxBufferSize) {
67808
+ const droppedSpanCount = this.buffer.length - this.maxBufferSize;
67809
+ this.buffer.splice(0, droppedSpanCount);
67810
+ this.warnBufferOverflow(droppedSpanCount);
67811
+ }
67812
+ }
67813
+ warnBufferOverflow(droppedSpanCount) {
67814
+ this.droppedSpansSinceLastBufferWarning += droppedSpanCount;
67815
+ this.totalDroppedSpans += droppedSpanCount;
67816
+ const now = Date.now();
67817
+ if (this.lastBufferOverflowWarningMs !== void 0 && now - this.lastBufferOverflowWarningMs < BUFFER_OVERFLOW_WARNING_INTERVAL_MS) {
67818
+ return;
67819
+ }
67820
+ this.emitBufferOverflowWarning(now);
67821
+ }
67822
+ emitBufferOverflowWarning(now = Date.now()) {
67823
+ if (this.droppedSpansSinceLastBufferWarning === 0) {
67824
+ return;
67825
+ }
67826
+ const droppedSinceLastWarning = this.droppedSpansSinceLastBufferWarning;
67827
+ this.droppedSpansSinceLastBufferWarning = 0;
67828
+ this.lastBufferOverflowWarningMs = now;
67829
+ this.emitDiagnostic(
67830
+ `[LogToSpan] buffer exceeded max size (${this.maxBufferSize}); dropped ${droppedSinceLastWarning} oldest span(s) since last warning, ${this.totalDroppedSpans} total`
67831
+ );
67832
+ }
67833
+ /**
67834
+ * Route a diagnostic message to the configured sink, swallowing any sink
67835
+ * error so a misbehaving sink can never interrupt telemetry ingestion.
67836
+ *
67837
+ * Tradeoff: when the sink itself is broken (e.g. file-logger failing on
67838
+ * EACCES), bridge-specific diagnostics go dark. We accept that — the host
67839
+ * surfaces overall logging health via `isDebugLoggingDegraded()`, and
67840
+ * falling back to stderr here would re-introduce the TUI-pollution this
67841
+ * sink injection was added to prevent.
67842
+ */
67843
+ emitDiagnostic(message) {
67844
+ try {
67845
+ this.diagnosticsSink(message);
67846
+ } catch {
67847
+ }
67848
+ }
67849
+ flush() {
67850
+ if (this.inFlightExport) return this.inFlightExport;
67851
+ if (this.buffer.length === 0) return Promise.resolve();
67852
+ const spans = this.buffer.splice(0);
67853
+ const exportPromise = new Promise((resolve2) => {
67854
+ const timeout = setTimeout(() => {
67855
+ this.emitDiagnostic(
67856
+ `[LogToSpan] export timeout after ${EXPORT_TIMEOUT_MS}ms (${spans.length} span(s))`
67857
+ );
67858
+ resolve2();
67859
+ }, EXPORT_TIMEOUT_MS);
67860
+ timeout.unref();
67861
+ try {
67862
+ this.spanExporter.export(
67863
+ spans,
67864
+ (result) => {
67865
+ clearTimeout(timeout);
67866
+ if (result.code !== 0) {
67867
+ this.emitDiagnostic(
67868
+ `[LogToSpan] export failed: code=${result.code} ${formatExportError(result.error)}`
67869
+ );
67870
+ }
67871
+ resolve2();
67872
+ }
67873
+ );
67874
+ } catch (err) {
67875
+ clearTimeout(timeout);
67876
+ const detail = err instanceof Error ? formatExportError(err) : `error=${JSON.stringify(String(err))}`;
67877
+ this.emitDiagnostic(`[LogToSpan] export threw: ${detail}`);
67878
+ resolve2();
67879
+ }
67880
+ });
67881
+ this.inFlightExport = exportPromise.finally(() => {
67882
+ this.inFlightExport = void 0;
67883
+ });
67884
+ return this.inFlightExport;
67885
+ }
67886
+ async shutdown() {
67887
+ if (this.isShutdown) {
67888
+ return;
67889
+ }
67890
+ this.isShutdown = true;
67891
+ if (this.flushTimer) {
67892
+ clearInterval(this.flushTimer);
67893
+ this.flushTimer = void 0;
67894
+ }
67895
+ if (this.inFlightExport) {
67896
+ await this.inFlightExport;
67897
+ }
67898
+ await this.flush();
67899
+ this.emitBufferOverflowWarning();
67900
+ await this.spanExporter.shutdown();
67901
+ }
67902
+ async forceFlush() {
67903
+ if (this.isShutdown) {
67904
+ return;
67905
+ }
67906
+ if (this.inFlightExport) {
67907
+ await this.inFlightExport;
67908
+ }
67909
+ await this.flush();
67910
+ await this.spanExporter.forceFlush?.();
67911
+ }
67912
+ };
67913
+ function normalizeMaxBufferSize(value) {
67914
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
67915
+ return DEFAULT_MAX_BUFFER_SIZE;
67916
+ }
67917
+ return Math.floor(value);
67918
+ }
67919
+ __name(normalizeMaxBufferSize, "normalizeMaxBufferSize");
67920
+ function deriveSpanName(logRecord) {
67921
+ const eventName = logRecord.attributes?.["event.name"] ?? logRecord.eventName;
67922
+ if (typeof eventName === "string" && eventName.trim().length > 0) {
67923
+ return sanitizeSpanName(eventName);
67924
+ }
67925
+ return DEFAULT_LOG_SPAN_NAME;
67926
+ }
67927
+ __name(deriveSpanName, "deriveSpanName");
67928
+ function sanitizeSpanName(body) {
67929
+ const rawName = String(body ?? "unknown");
67930
+ return rawName.length > MAX_SPAN_NAME_LENGTH ? `${rawName.slice(0, MAX_SPAN_NAME_LENGTH)}...` : rawName;
67931
+ }
67932
+ __name(sanitizeSpanName, "sanitizeSpanName");
67933
+ function getValidParentSpanContext(spanContext) {
67934
+ if (!spanContext || !isSpanContextValid(spanContext)) {
67935
+ return void 0;
67936
+ }
67937
+ return spanContext;
67938
+ }
67939
+ __name(getValidParentSpanContext, "getValidParentSpanContext");
67940
+ function safeStringify(value) {
67941
+ try {
67942
+ return JSON.stringify(value);
67943
+ } catch {
67944
+ return "[unserializable]";
67945
+ }
67946
+ }
67947
+ __name(safeStringify, "safeStringify");
67948
+ function deriveSpanStatus(attrs) {
67949
+ if (!attrs) return { code: SpanStatusCode.OK };
67950
+ if (!!attrs["error"] || !!attrs["error.message"] || !!attrs["error_message"] || !!attrs["error_type"]) {
67951
+ return {
67952
+ code: SpanStatusCode.ERROR,
67953
+ message: LOG_EVENT_ERROR_STATUS_MESSAGE
67954
+ };
67955
+ }
67956
+ return { code: SpanStatusCode.OK };
67957
+ }
67958
+ __name(deriveSpanStatus, "deriveSpanStatus");
67959
+ function formatExportError(err) {
67960
+ if (!err) return 'error="unknown"';
67961
+ const extra = err;
67962
+ const msg = err.message || err.name || "unknown";
67963
+ const parts = [`error=${JSON.stringify(msg)}`];
67964
+ if (typeof extra.code === "number") parts.push(`httpCode=${extra.code}`);
67965
+ if (typeof extra.data === "string" && extra.data.length > 0) {
67966
+ parts.push(`data=${JSON.stringify(extra.data.slice(0, 200))}`);
67967
+ }
67968
+ return parts.join(" ");
67969
+ }
67970
+ __name(formatExportError, "formatExportError");
67971
+ function hrTimeDiff(start, end) {
67972
+ let secs = end[0] - start[0];
67973
+ let nanos = end[1] - start[1];
67974
+ if (nanos < 0) {
67975
+ secs -= 1;
67976
+ nanos += 1e9;
67977
+ }
67978
+ return [secs, nanos];
67979
+ }
67980
+ __name(hrTimeDiff, "hrTimeDiff");
67981
+
67982
+ // packages/core/src/telemetry/tracer.ts
67983
+ init_esbuild_shims();
67984
+ init_esm();
67985
+ var tracer = trace.getTracer(SERVICE_NAME);
67986
+ var debugLogger8 = createDebugLogger("OTEL_TRACER");
67987
+ var TELEMETRY_WARNING_INTERVAL_MS = 3e4;
67988
+ var API_CALL_FAILED_SPAN_STATUS_MESSAGE = "API call failed";
67989
+ var API_CALL_ABORTED_SPAN_STATUS_MESSAGE = "API call aborted";
67990
+ var lastTelemetryWarningMs;
67991
+ var suppressedTelemetryWarnings = 0;
67992
+ function warnTelemetryOperationFailed(operation, error) {
67993
+ const now = Date.now();
67994
+ if (lastTelemetryWarningMs !== void 0 && now - lastTelemetryWarningMs < TELEMETRY_WARNING_INTERVAL_MS) {
67995
+ suppressedTelemetryWarnings += 1;
67996
+ return;
67997
+ }
67998
+ const suppressedSuffix = suppressedTelemetryWarnings > 0 ? `; suppressed ${suppressedTelemetryWarnings} similar warning(s)` : "";
67999
+ suppressedTelemetryWarnings = 0;
68000
+ lastTelemetryWarningMs = now;
68001
+ try {
68002
+ debugLogger8.warn(
68003
+ `OTel span ${operation} failed: ${error instanceof Error ? error.message : String(error)}${suppressedSuffix}`
68004
+ );
68005
+ } catch {
68006
+ }
68007
+ }
68008
+ __name(warnTelemetryOperationFailed, "warnTelemetryOperationFailed");
68009
+ function safeSetStatus(span, status) {
68010
+ try {
68011
+ span.setStatus(status);
68012
+ } catch (error) {
68013
+ warnTelemetryOperationFailed("setStatus", error);
68014
+ }
68015
+ }
68016
+ __name(safeSetStatus, "safeSetStatus");
68017
+ function shouldForceSampled() {
68018
+ const sampler = process.env["OTEL_TRACES_SAMPLER"]?.trim().toLowerCase() ?? "";
68019
+ if (!sampler || sampler.startsWith("parentbased_")) {
68020
+ if (sampler.includes("always_off")) return false;
68021
+ return true;
68022
+ }
68023
+ return sampler === "always_on";
68024
+ }
68025
+ __name(shouldForceSampled, "shouldForceSampled");
68026
+ function createSessionRootContext(sessionId) {
68027
+ const traceId = deriveTraceId(sessionId);
68028
+ const spanId = randomSpanId();
68029
+ const rootSpan = trace.wrapSpanContext({
68030
+ traceId,
68031
+ spanId,
68032
+ traceFlags: shouldForceSampled() ? TraceFlags.SAMPLED : TraceFlags.NONE,
68033
+ isRemote: false
68034
+ });
68035
+ return trace.setSpan(ROOT_CONTEXT, rootSpan);
68036
+ }
68037
+ __name(createSessionRootContext, "createSessionRootContext");
68038
+
67756
68039
  // packages/core/src/telemetry/sdk.ts
67757
68040
  function createTelemetryDiagLogger() {
67758
68041
  const debugLogger12 = createDebugLogger("OTEL");
@@ -68540,7 +68823,21 @@ function isUserVisiblePart(part) {
68540
68823
  }
68541
68824
  __name(isUserVisiblePart, "isUserVisiblePart");
68542
68825
 
68826
+ // packages/core/src/utils/retryContext.ts
68827
+ init_esbuild_shims();
68828
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
68829
+ var retryContext = new AsyncLocalStorage4();
68830
+
68543
68831
  // packages/core/src/core/loggingContentGenerator/loggingContentGenerator.ts
68832
+ function snapshotRetryMetadata() {
68833
+ const ctx = retryContext.getStore();
68834
+ return {
68835
+ attempt: ctx?.attempt ?? 1,
68836
+ requestSetupMs: ctx?.requestSetupMs,
68837
+ retryTotalDelayMs: ctx?.retryTotalDelayMs
68838
+ };
68839
+ }
68840
+ __name(snapshotRetryMetadata, "snapshotRetryMetadata");
68544
68841
  var debugLogger9 = createDebugLogger("LOGGING_CONTENT_GENERATOR");
68545
68842
  var MAX_RESPONSE_TEXT_LENGTH = 4096;
68546
68843
  var RESPONSE_TEXT_TRUNCATION_SUFFIX = "...[truncated]";
@@ -68638,6 +68935,7 @@ var LoggingContentGenerator = class {
68638
68935
  }
68639
68936
  }
68640
68937
  async generateContent(req, userPromptId) {
68938
+ const retrySnapshot = snapshotRetryMetadata();
68641
68939
  const llmSpan = startLLMRequestSpan(req.model, userPromptId);
68642
68940
  try {
68643
68941
  llmSpan.setAttribute("llm_request.stream", false);
@@ -68705,7 +69003,8 @@ var LoggingContentGenerator = class {
68705
69003
  inputTokens: response.usageMetadata?.promptTokenCount,
68706
69004
  outputTokens: response.usageMetadata?.candidatesTokenCount,
68707
69005
  cachedInputTokens: response.usageMetadata?.cachedContentTokenCount,
68708
- durationMs: Date.now() - startTime
69006
+ durationMs: Date.now() - startTime,
69007
+ ...retrySnapshot
68709
69008
  });
68710
69009
  return response;
68711
69010
  } catch (error) {
@@ -68714,7 +69013,8 @@ var LoggingContentGenerator = class {
68714
69013
  endLLMRequestSpan(llmSpan, {
68715
69014
  success: false,
68716
69015
  durationMs,
68717
- error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE
69016
+ error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE,
69017
+ ...retrySnapshot
68718
69018
  });
68719
69019
  await context.with(spanContext, async () => {
68720
69020
  this.safelyLogApiError("", durationMs, error, req.model, userPromptId);
@@ -68733,6 +69033,7 @@ var LoggingContentGenerator = class {
68733
69033
  }
68734
69034
  }
68735
69035
  async generateContentStream(req, userPromptId) {
69036
+ const retrySnapshot = snapshotRetryMetadata();
68736
69037
  const llmSpan = startLLMRequestSpan(req.model, userPromptId);
68737
69038
  try {
68738
69039
  llmSpan.setAttribute("llm_request.stream", true);
@@ -68782,7 +69083,8 @@ var LoggingContentGenerator = class {
68782
69083
  endLLMRequestSpan(llmSpan, {
68783
69084
  success: false,
68784
69085
  durationMs,
68785
- error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE
69086
+ error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE,
69087
+ ...retrySnapshot
68786
69088
  });
68787
69089
  try {
68788
69090
  await this.safelyLogOpenAIInteraction(
@@ -68814,7 +69116,8 @@ var LoggingContentGenerator = class {
68814
69116
  resolvedRequest,
68815
69117
  llmSpan,
68816
69118
  spanContext,
68817
- req.config?.abortSignal
69119
+ req.config?.abortSignal,
69120
+ retrySnapshot
68818
69121
  )
68819
69122
  );
68820
69123
  }
@@ -68828,7 +69131,7 @@ var LoggingContentGenerator = class {
68828
69131
  resolve: /* @__PURE__ */ __name(async (req) => this.openaiLogger ? captured ?? await this.buildOpenAIRequestForLogging(req) : void 0, "resolve")
68829
69132
  };
68830
69133
  }
68831
- async *loggingStreamWrapper(stream, startTime, userPromptId, model, openaiRequest, span, spanContext, abortSignal) {
69134
+ async *loggingStreamWrapper(stream, startTime, userPromptId, model, openaiRequest, span, spanContext, abortSignal, retrySnapshot) {
68832
69135
  const isInternal = isInternalPromptId(userPromptId);
68833
69136
  const shouldCollectResponses = !isInternal || !!this.openaiLogger;
68834
69137
  const responses = [];
@@ -68852,7 +69155,8 @@ var LoggingContentGenerator = class {
68852
69155
  endLLMRequestSpan(span, {
68853
69156
  success: false,
68854
69157
  durationMs: Date.now() - startTime,
68855
- error: "Stream span timed out (idle)"
69158
+ error: "Stream span timed out (idle)",
69159
+ ...retrySnapshot
68856
69160
  });
68857
69161
  spanEndedByTimeout = true;
68858
69162
  }, STREAM_IDLE_TIMEOUT_MS);
@@ -68945,7 +69249,8 @@ var LoggingContentGenerator = class {
68945
69249
  cachedInputTokens: lastUsageMetadata?.cachedContentTokenCount,
68946
69250
  ttftMs,
68947
69251
  durationMs: Date.now() - startTime,
68948
- error: errorOccurred ? aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE : void 0
69252
+ error: errorOccurred ? aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE : void 0,
69253
+ ...retrySnapshot
68949
69254
  });
68950
69255
  }
68951
69256
  }
@@ -69335,9 +69640,10 @@ var MODALITY_PATTERNS = [
69335
69640
  // -------------------
69336
69641
  // Alibaba / Qwen
69337
69642
  // -------------------
69338
- // Qwen3.5-Plus, Qwen3.6-Plus: image + video support
69643
+ // Qwen Plus models: image + video support (Max models are text-only)
69339
69644
  [/^qwen3\.5-plus/, { image: true, video: true }],
69340
69645
  [/^qwen3\.6-plus/, { image: true, video: true }],
69646
+ [/^qwen3\.7-plus/, { image: true, video: true }],
69341
69647
  [/^coder-model$/, { image: true, video: true }],
69342
69648
  // Qwen VL (vision-language) models: image + video
69343
69649
  [/^qwen-vl-/, { image: true, video: true }],
@@ -69379,6 +69685,20 @@ function defaultModalities(model) {
69379
69685
  }
69380
69686
  __name(defaultModalities, "defaultModalities");
69381
69687
 
69688
+ // packages/core/src/utils/runtimeModelPrefix.ts
69689
+ init_esbuild_shims();
69690
+ var RUNTIME_SNAPSHOT_PREFIX = "$runtime|";
69691
+ function stripRuntimeSnapshotPrefix(modelId) {
69692
+ let id = modelId;
69693
+ while (id.startsWith(RUNTIME_SNAPSHOT_PREFIX)) {
69694
+ const stripped = id.split("|").slice(2).join("|");
69695
+ if (!stripped) break;
69696
+ id = stripped;
69697
+ }
69698
+ return id;
69699
+ }
69700
+ __name(stripRuntimeSnapshotPrefix, "stripRuntimeSnapshotPrefix");
69701
+
69382
69702
  // packages/core/src/models/modelRegistry.ts
69383
69703
  init_esbuild_shims();
69384
69704
 
@@ -69836,6 +70156,17 @@ var ModelsConfig = class _ModelsConfig {
69836
70156
  getResolvedModel(authType, modelId) {
69837
70157
  return this.modelRegistry.getModel(authType, modelId);
69838
70158
  }
70159
+ /**
70160
+ * Get the display name for a model by its id.
70161
+ * Looks up the model in the registry using the current authType and returns
70162
+ * its resolved name. Falls back to the raw model id when the model is not
70163
+ * found in the registry (e.g. runtime models or unknown models).
70164
+ */
70165
+ getModelDisplayName(modelId) {
70166
+ if (!this.currentAuthType) return modelId;
70167
+ const resolved = this.modelRegistry.getModel(this.currentAuthType, modelId);
70168
+ return resolved?.name ?? modelId;
70169
+ }
69839
70170
  /**
69840
70171
  * Set model programmatically (e.g., VLM auto-switch, fallback).
69841
70172
  * Supports both registry models and raw model IDs.
@@ -69960,11 +70291,6 @@ var ModelsConfig = class _ModelsConfig {
69960
70291
  throw error;
69961
70292
  }
69962
70293
  }
69963
- /**
69964
- * Prefix used to identify RuntimeModelSnapshot IDs.
69965
- * Chosen to avoid conflicts with real model IDs which may contain `-` or `:`.
69966
- */
69967
- static RUNTIME_SNAPSHOT_PREFIX = "$runtime|";
69968
70294
  /**
69969
70295
  * Build a RuntimeModelSnapshot ID from authType and modelId.
69970
70296
  * The format is: `$runtime|${authType}|${modelId}`
@@ -69977,7 +70303,7 @@ var ModelsConfig = class _ModelsConfig {
69977
70303
  * @returns The snapshot ID in format `$runtime|${authType}|${modelId}`
69978
70304
  */
69979
70305
  buildRuntimeModelSnapshotId(authType, modelId) {
69980
- return `${_ModelsConfig.RUNTIME_SNAPSHOT_PREFIX}${authType}|${modelId}`;
70306
+ return `${RUNTIME_SNAPSHOT_PREFIX}${authType}|${modelId}`;
69981
70307
  }
69982
70308
  /**
69983
70309
  * Extract RuntimeModelSnapshot ID from modelId if it's a runtime model reference.
@@ -69994,7 +70320,7 @@ var ModelsConfig = class _ModelsConfig {
69994
70320
  * @returns The RuntimeModelSnapshot ID if found, undefined otherwise
69995
70321
  */
69996
70322
  extractRuntimeModelSnapshotId(modelId) {
69997
- if (modelId.startsWith(_ModelsConfig.RUNTIME_SNAPSHOT_PREFIX)) {
70323
+ if (modelId.startsWith(RUNTIME_SNAPSHOT_PREFIX)) {
69998
70324
  if (this.runtimeModelSnapshots.has(modelId)) {
69999
70325
  return modelId;
70000
70326
  }
@@ -70305,6 +70631,10 @@ var ModelsConfig = class _ModelsConfig {
70305
70631
  const isUnchanged = previousAuthType === authType && this._generationConfig.model === modelId && !isProviderChanged;
70306
70632
  const savedApiKey = isUnchanged ? this._generationConfig.apiKey : void 0;
70307
70633
  const savedApiKeySource = isUnchanged ? this.generationConfigSources["apiKey"] ? { ...this.generationConfigSources["apiKey"] } : void 0 : void 0;
70634
+ const baseUrlSource2 = this.generationConfigSources["baseUrl"];
70635
+ const shouldPreserveResolvedBaseUrl = isUnchanged && !!this._generationConfig.baseUrl && (baseUrlSource2?.kind === "cli" || baseUrlSource2?.kind === "env" || baseUrlSource2?.kind === "settings");
70636
+ const savedBaseUrl = shouldPreserveResolvedBaseUrl ? this._generationConfig.baseUrl : void 0;
70637
+ const savedBaseUrlSource = shouldPreserveResolvedBaseUrl ? baseUrlSource2 ? { ...baseUrlSource2 } : void 0 : void 0;
70308
70638
  this.applyResolvedModelDefaults(resolved);
70309
70639
  if (isUnchanged && !this._generationConfig.apiKey && savedApiKey) {
70310
70640
  this._generationConfig.apiKey = savedApiKey;
@@ -70312,6 +70642,12 @@ var ModelsConfig = class _ModelsConfig {
70312
70642
  this.generationConfigSources["apiKey"] = savedApiKeySource;
70313
70643
  }
70314
70644
  }
70645
+ if (savedBaseUrl) {
70646
+ this._generationConfig.baseUrl = savedBaseUrl;
70647
+ if (savedBaseUrlSource) {
70648
+ this.generationConfigSources["baseUrl"] = savedBaseUrlSource;
70649
+ }
70650
+ }
70315
70651
  this.strictModelProviderSelection = true;
70316
70652
  this.activeRuntimeModelSnapshotId = void 0;
70317
70653
  return;
@@ -70675,6 +71011,17 @@ function createContentGeneratorConfig(config, authType, generationConfig) {
70675
71011
  ).config;
70676
71012
  }
70677
71013
  __name(createContentGeneratorConfig, "createContentGeneratorConfig");
71014
+ function getModuleNotFoundError(error) {
71015
+ let current = error;
71016
+ while (current instanceof Error) {
71017
+ if ("code" in current && current.code === "ERR_MODULE_NOT_FOUND") {
71018
+ return current;
71019
+ }
71020
+ current = current.cause;
71021
+ }
71022
+ return void 0;
71023
+ }
71024
+ __name(getModuleNotFoundError, "getModuleNotFoundError");
70678
71025
  async function createContentGenerator(generatorConfig, config, isInitialAuth) {
70679
71026
  const validation = validateModelConfig(generatorConfig, false);
70680
71027
  if (!validation.valid) {
@@ -70685,37 +71032,50 @@ async function createContentGenerator(generatorConfig, config, isInitialAuth) {
70685
71032
  throw new Error("ContentGeneratorConfig must have an authType");
70686
71033
  }
70687
71034
  let baseGenerator;
70688
- if (authType === "openai" /* USE_OPENAI */) {
70689
- const { createOpenAIContentGenerator } = await import("./openaiContentGenerator-N3O3MYIT.js");
70690
- baseGenerator = createOpenAIContentGenerator(generatorConfig, config);
70691
- } else if (authType === "qwen-oauth" /* QWEN_OAUTH */) {
70692
- const { getQwenOAuthClient: getQwenOauthClient } = await import("./qwenOAuth2-LKXG7XVO.js");
70693
- const { QwenContentGenerator } = await import("./qwenContentGenerator-DEOIWKVH.js");
70694
- try {
70695
- const qwenClient = await getQwenOauthClient(
70696
- config,
70697
- isInitialAuth ? { requireCachedCredentials: true } : void 0
70698
- );
70699
- baseGenerator = new QwenContentGenerator(
70700
- qwenClient,
70701
- generatorConfig,
70702
- config
71035
+ try {
71036
+ if (authType === "openai" /* USE_OPENAI */) {
71037
+ const { createOpenAIContentGenerator } = await import("./openaiContentGenerator-4QNV3CHM.js");
71038
+ baseGenerator = createOpenAIContentGenerator(generatorConfig, config);
71039
+ } else if (authType === "qwen-oauth" /* QWEN_OAUTH */) {
71040
+ const { getQwenOAuthClient: getQwenOauthClient } = await import("./qwenOAuth2-KRJT35QH.js");
71041
+ const { QwenContentGenerator } = await import("./qwenContentGenerator-3XOCEMQO.js");
71042
+ try {
71043
+ const qwenClient = await getQwenOauthClient(
71044
+ config,
71045
+ isInitialAuth ? { requireCachedCredentials: true } : void 0
71046
+ );
71047
+ baseGenerator = new QwenContentGenerator(
71048
+ qwenClient,
71049
+ generatorConfig,
71050
+ config
71051
+ );
71052
+ } catch (error) {
71053
+ if (getModuleNotFoundError(error)) {
71054
+ throw error;
71055
+ }
71056
+ throw new Error(error instanceof Error ? error.message : String(error));
71057
+ }
71058
+ } else if (authType === "anthropic" /* USE_ANTHROPIC */) {
71059
+ const { createAnthropicContentGenerator } = await import("./anthropicContentGenerator-4QBVSFSJ.js");
71060
+ baseGenerator = createAnthropicContentGenerator(generatorConfig, config);
71061
+ } else if (authType === "gemini" /* USE_GEMINI */ || authType === "vertex-ai" /* USE_VERTEX_AI */) {
71062
+ const { createGeminiContentGenerator } = await import("./geminiContentGenerator-CR2WGARL.js");
71063
+ baseGenerator = createGeminiContentGenerator(generatorConfig, config);
71064
+ } else {
71065
+ throw new Error(
71066
+ `Error creating contentGenerator: Unsupported authType: ${authType}`
70703
71067
  );
70704
- } catch (error) {
71068
+ }
71069
+ } catch (error) {
71070
+ const moduleNotFoundError = getModuleNotFoundError(error);
71071
+ if (moduleNotFoundError) {
70705
71072
  throw new Error(
70706
- `${error instanceof Error ? error.message : String(error)}`
71073
+ `Qwen Code was updated in the background and needs to be restarted.
71074
+ Please exit and restart Qwen Code to use the '${authType}' provider.`,
71075
+ { cause: moduleNotFoundError }
70707
71076
  );
70708
71077
  }
70709
- } else if (authType === "anthropic" /* USE_ANTHROPIC */) {
70710
- const { createAnthropicContentGenerator } = await import("./anthropicContentGenerator-M45RXZVS.js");
70711
- baseGenerator = createAnthropicContentGenerator(generatorConfig, config);
70712
- } else if (authType === "gemini" /* USE_GEMINI */ || authType === "vertex-ai" /* USE_VERTEX_AI */) {
70713
- const { createGeminiContentGenerator } = await import("./geminiContentGenerator-3LR7MKCQ.js");
70714
- baseGenerator = createGeminiContentGenerator(generatorConfig, config);
70715
- } else {
70716
- throw new Error(
70717
- `Error creating contentGenerator: Unsupported authType: ${authType}`
70718
- );
71078
+ throw error;
70719
71079
  }
70720
71080
  return new LoggingContentGenerator(baseGenerator, config, generatorConfig);
70721
71081
  }
@@ -71413,6 +71773,23 @@ var QwenLogger = class _QwenLogger {
71413
71773
  this.enqueueLogEvent(rumEvent);
71414
71774
  this.flushIfNeeded();
71415
71775
  }
71776
+ // Phase 4b — HTTP-status retry from retryWithBackoff (429/5xx). Distinct from
71777
+ // logContentRetryEvent which is fired by geminiChat's content-recovery loop.
71778
+ logApiRetryEvent(event) {
71779
+ const rumEvent = this.createActionEvent("misc", "api_retry", {
71780
+ properties: {
71781
+ model: event.model,
71782
+ prompt_id: event.prompt_id ?? "",
71783
+ attempt_number: event.attempt_number,
71784
+ error_type: event.error_type ?? "unknown",
71785
+ status_code: event.status_code !== void 0 ? String(event.status_code) : "",
71786
+ retry_delay_ms: event.retry_delay_ms,
71787
+ subagent_name: event.subagent_name ?? ""
71788
+ }
71789
+ });
71790
+ this.enqueueLogEvent(rumEvent);
71791
+ this.flushIfNeeded();
71792
+ }
71416
71793
  // arena events
71417
71794
  logArenaSessionStartedEvent(event) {
71418
71795
  const rumEvent = this.createActionEvent("arena", "arena_session_started", {
@@ -72018,6 +72395,23 @@ function logContentRetryFailure(config, event) {
72018
72395
  recordContentRetryFailure(config);
72019
72396
  }
72020
72397
  __name(logContentRetryFailure, "logContentRetryFailure");
72398
+ function logApiRetry(config, event) {
72399
+ QwenLogger.getInstance(config)?.logApiRetryEvent(event);
72400
+ if (!isTelemetrySdkInitialized()) return;
72401
+ const attributes = {
72402
+ ...getCommonAttributes(config),
72403
+ ...event,
72404
+ "event.name": EVENT_API_RETRY
72405
+ };
72406
+ const logger = import_api_logs.logs.getLogger(SERVICE_NAME);
72407
+ const logRecord = {
72408
+ body: `API retry attempt ${event.attempt_number} for ${event.model} (status ${event.status_code ?? "unknown"}).`,
72409
+ attributes
72410
+ };
72411
+ logger.emit(logRecord);
72412
+ recordApiRetry(config, { model: event.model });
72413
+ }
72414
+ __name(logApiRetry, "logApiRetry");
72021
72415
  function logSubagentExecution(config, event) {
72022
72416
  QwenLogger.getInstance(config)?.logSubagentExecutionEvent(event);
72023
72417
  if (!isTelemetrySdkInitialized()) return;
@@ -72506,10 +72900,11 @@ var ReadFileToolInvocation = class extends BaseToolInvocation {
72506
72900
  ...this.config.storage.getUserSkillsDirs(),
72507
72901
  Storage.getUserExtensionsDir()
72508
72902
  ];
72509
- if (workspaceContext.isPathWithinWorkspace(filePath) || isSubpaths(allowedRoots, filePath) || // isAutoMemPath uses the narrower managed auto-memory root for this
72510
- // project not the broad getMemoryBaseDir() — to avoid exposing
72511
- // sensitive ~/.qwen files such as settings.json or OAuth credentials.
72512
- isAutoMemPath(filePath, this.config.getTargetDir())) {
72903
+ if (workspaceContext.isPathWithinWorkspace(filePath) || isSubpaths(allowedRoots, filePath) || // isAnyAutoMemPath narrows to the managed auto-memory roots
72904
+ // (per-project + user-level under ~/.qwen/memories/) — never the
72905
+ // broad getMemoryBaseDir() to avoid exposing sensitive ~/.qwen
72906
+ // files such as settings.json or OAuth credentials.
72907
+ isAnyAutoMemPath(filePath, this.config.getTargetDir())) {
72513
72908
  return "allow";
72514
72909
  }
72515
72910
  return "ask";
@@ -72517,7 +72912,7 @@ var ReadFileToolInvocation = class extends BaseToolInvocation {
72517
72912
  async execute() {
72518
72913
  const absPath = path7.resolve(this.params.file_path);
72519
72914
  const projectRoot = this.config.getTargetDir();
72520
- const isAutoMem = isAutoMemPath(absPath, projectRoot);
72915
+ const isAutoMem = isAnyAutoMemPath(absPath, projectRoot);
72521
72916
  const cacheEnabled = !this.config.getFileReadCacheDisabled();
72522
72917
  const useFastPath = cacheEnabled && !isAutoMem;
72523
72918
  const cache = this.config.getFileReadCache();
@@ -72736,6 +73131,7 @@ export {
72736
73131
  subagentNameContext,
72737
73132
  UiTelemetryService,
72738
73133
  uiTelemetryService,
73134
+ safeJsonStringify,
72739
73135
  require_safer,
72740
73136
  iconvEncode,
72741
73137
  iconvEncodingExists,
@@ -72802,6 +73198,7 @@ export {
72802
73198
  recordInvalidChunk,
72803
73199
  recordContentRetry,
72804
73200
  recordContentRetryFailure,
73201
+ recordApiRetry,
72805
73202
  recordStartupPerformance,
72806
73203
  recordMemoryUsage,
72807
73204
  recordCpuUsage,
@@ -72823,7 +73220,6 @@ export {
72823
73220
  SemanticAttributes,
72824
73221
  sanitizeHookName,
72825
73222
  QwenLogger,
72826
- safeSetStatus,
72827
73223
  truncateContent,
72828
73224
  addUserPromptAttributes,
72829
73225
  addSystemPromptAttributes,
@@ -72846,7 +73242,11 @@ export {
72846
73242
  endToolBlockedOnUserSpan,
72847
73243
  startHookSpan,
72848
73244
  endHookSpan,
73245
+ startSubagentSpan,
73246
+ runInSubagentSpanContext,
73247
+ endSubagentSpan,
72849
73248
  getActiveInteractionSpan,
73249
+ safeSetStatus,
72850
73250
  isTelemetrySdkInitialized,
72851
73251
  initializeTelemetry,
72852
73252
  refreshSessionContext,
@@ -72873,6 +73273,7 @@ export {
72873
73273
  logKittySequenceOverflow,
72874
73274
  logContentRetry,
72875
73275
  logContentRetryFailure,
73276
+ logApiRetry,
72876
73277
  logSubagentExecution,
72877
73278
  logModelSlashCommand,
72878
73279
  logHookCall,
@@ -72922,6 +73323,7 @@ export {
72922
73323
  KittySequenceOverflowEvent,
72923
73324
  FileOperationEvent,
72924
73325
  ContentRetryEvent,
73326
+ ApiRetryEvent,
72925
73327
  ContentRetryFailureEvent,
72926
73328
  ExtensionInstallEvent,
72927
73329
  ToolOutputTruncatedEvent,
@@ -72956,7 +73358,10 @@ export {
72956
73358
  TelemetryTarget,
72957
73359
  DEFAULT_TELEMETRY_TARGET,
72958
73360
  DEFAULT_OTLP_ENDPOINT,
73361
+ retryContext,
72959
73362
  defaultModalities,
73363
+ RUNTIME_SNAPSHOT_PREFIX,
73364
+ stripRuntimeSnapshotPrefix,
72960
73365
  MODEL_GENERATION_CONFIG_FIELDS,
72961
73366
  AUTH_ENV_MAPPINGS,
72962
73367
  DEFAULT_MODELS,