@qwen-code/qwen-code 0.15.0 → 0.15.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 (2) hide show
  1. package/cli.js +75 -49
  2. package/package.json +2 -2
package/cli.js CHANGED
@@ -145656,7 +145656,6 @@ var init_converter = __esm({
145656
145656
  model;
145657
145657
  schemaCompliance;
145658
145658
  modalities;
145659
- streamingToolCallParser = new StreamingToolCallParser();
145660
145659
  constructor(model, schemaCompliance = "auto", modalities = {}) {
145661
145660
  this.model = model;
145662
145661
  this.schemaCompliance = schemaCompliance;
@@ -145676,12 +145675,21 @@ var init_converter = __esm({
145676
145675
  this.modalities = modalities;
145677
145676
  }
145678
145677
  /**
145679
- * Reset streaming tool calls parser for new stream processing
145680
- * This should be called at the beginning of each stream to prevent
145681
- * data pollution from previous incomplete streams
145678
+ * Create fresh per-stream state for processing one OpenAI streaming
145679
+ * response. The returned context is passed into every
145680
+ * `convertOpenAIChunkToGemini` call for that stream, then discarded.
145681
+ *
145682
+ * Previously the tool-call parser lived on the Converter instance and
145683
+ * was shared by every caller of the singleton `Config.contentGenerator`.
145684
+ * Concurrent streams (e.g. two subagents running in parallel after
145685
+ * PR #3463) raced on that shared state: each stream's stream-start
145686
+ * `reset()` wiped the other's partial tool-call buffers, chunks from
145687
+ * different streams landed at the same `index=0` bucket, and
145688
+ * `getCompletedToolCalls()` returned interleaved corrupt JSON that
145689
+ * surfaced upstream as `NO_RESPONSE_TEXT` (issue #3516).
145682
145690
  */
145683
- resetStreamingToolCalls() {
145684
- this.streamingToolCallParser.reset();
145691
+ createStreamContext() {
145692
+ return { toolCallParser: new StreamingToolCallParser() };
145685
145693
  }
145686
145694
  /**
145687
145695
  * Convert Gemini tool parameters to OpenAI JSON Schema format
@@ -146270,9 +146278,15 @@ var init_converter = __esm({
146270
146278
  return response;
146271
146279
  }
146272
146280
  /**
146273
- * Convert OpenAI stream chunk to Gemini format
146281
+ * Convert OpenAI stream chunk to Gemini format.
146282
+ *
146283
+ * `ctx` carries the tool-call parser for this stream. Callers MUST
146284
+ * obtain it from `createStreamContext()` at the start of the stream
146285
+ * and pass the same instance for every chunk of that stream. Concurrent
146286
+ * streams MUST use distinct contexts or their tool-call buffers will
146287
+ * interleave (issue #3516).
146274
146288
  */
146275
- convertOpenAIChunkToGemini(chunk) {
146289
+ convertOpenAIChunkToGemini(chunk, ctx) {
146276
146290
  const choice2 = chunk.choices?.[0];
146277
146291
  const response = new GenerateContentResponse();
146278
146292
  if (choice2) {
@@ -146290,9 +146304,9 @@ var init_converter = __esm({
146290
146304
  for (const toolCall of choice2.delta.tool_calls) {
146291
146305
  const index = toolCall.index ?? 0;
146292
146306
  if (toolCall.function?.arguments) {
146293
- this.streamingToolCallParser.addChunk(index, toolCall.function.arguments, toolCall.id, toolCall.function.name);
146307
+ ctx.toolCallParser.addChunk(index, toolCall.function.arguments, toolCall.id, toolCall.function.name);
146294
146308
  } else {
146295
- this.streamingToolCallParser.addChunk(
146309
+ ctx.toolCallParser.addChunk(
146296
146310
  index,
146297
146311
  "",
146298
146312
  // Empty chunk for metadata-only updates
@@ -146304,8 +146318,8 @@ var init_converter = __esm({
146304
146318
  }
146305
146319
  let toolCallsTruncated = false;
146306
146320
  if (choice2.finish_reason) {
146307
- toolCallsTruncated = this.streamingToolCallParser.hasIncompleteToolCalls();
146308
- const completedToolCalls = this.streamingToolCallParser.getCompletedToolCalls();
146321
+ toolCallsTruncated = ctx.toolCallParser.hasIncompleteToolCalls();
146322
+ const completedToolCalls = ctx.toolCallParser.getCompletedToolCalls();
146309
146323
  for (const toolCall of completedToolCalls) {
146310
146324
  if (toolCall.name) {
146311
146325
  parts2.push({
@@ -146317,7 +146331,6 @@ var init_converter = __esm({
146317
146331
  });
146318
146332
  }
146319
146333
  }
146320
- this.streamingToolCallParser.reset();
146321
146334
  }
146322
146335
  const effectiveFinishReason = toolCallsTruncated && choice2.finish_reason !== "length" ? "length" : choice2.finish_reason;
146323
146336
  const candidate = {
@@ -156670,7 +156683,7 @@ var init_pipeline = __esm({
156670
156683
  */
156671
156684
  async *processStreamWithLogging(stream5, context2, request4) {
156672
156685
  const collectedGeminiResponses = [];
156673
- this.converter.resetStreamingToolCalls();
156686
+ const streamCtx = this.converter.createStreamContext();
156674
156687
  let pendingFinishResponse = null;
156675
156688
  let finishYielded = false;
156676
156689
  try {
@@ -156679,7 +156692,7 @@ var init_pipeline = __esm({
156679
156692
  const errorContent = chunk.choices?.[0]?.delta?.content?.trim() || "Unknown stream error";
156680
156693
  throw new StreamContentError(errorContent);
156681
156694
  }
156682
- const response = this.converter.convertOpenAIChunkToGemini(chunk);
156695
+ const response = this.converter.convertOpenAIChunkToGemini(chunk, streamCtx);
156683
156696
  if (response.candidates?.[0]?.content?.parts?.length === 0 && !response.candidates?.[0]?.finishReason && !response.usageMetadata) {
156684
156697
  continue;
156685
156698
  }
@@ -156710,7 +156723,6 @@ var init_pipeline = __esm({
156710
156723
  }
156711
156724
  context2.duration = Date.now() - context2.startTime;
156712
156725
  } catch (error40) {
156713
- this.converter.resetStreamingToolCalls();
156714
156726
  if (error40 instanceof StreamContentError) {
156715
156727
  throw error40;
156716
156728
  }
@@ -171534,7 +171546,7 @@ __export(geminiContentGenerator_exports, {
171534
171546
  createGeminiContentGenerator: () => createGeminiContentGenerator
171535
171547
  });
171536
171548
  function createGeminiContentGenerator(config2, gcConfig) {
171537
- const version2 = "0.15.0";
171549
+ const version2 = "0.15.1";
171538
171550
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
171539
171551
  const baseHeaders = {
171540
171552
  "User-Agent": userAgent2
@@ -458987,7 +458999,7 @@ __name(getPackageJson, "getPackageJson");
458987
458999
  // packages/cli/src/utils/version.ts
458988
459000
  async function getCliVersion() {
458989
459001
  const pkgJson = await getPackageJson();
458990
- return "0.15.0";
459002
+ return "0.15.1";
458991
459003
  }
458992
459004
  __name(getCliVersion, "getCliVersion");
458993
459005
 
@@ -468031,7 +468043,7 @@ var formatTokenCount = /* @__PURE__ */ __name((count) => {
468031
468043
  }
468032
468044
  return `${Math.floor(count / 1e3)}k`;
468033
468045
  }, "formatTokenCount");
468034
- var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
468046
+ var formatDuration = /* @__PURE__ */ __name((milliseconds, options2) => {
468035
468047
  if (milliseconds <= 0) {
468036
468048
  return "0s";
468037
468049
  }
@@ -468040,7 +468052,11 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
468040
468052
  }
468041
468053
  const totalSeconds = milliseconds / 1e3;
468042
468054
  if (totalSeconds < 60) {
468043
- return `${totalSeconds.toFixed(1)}s`;
468055
+ const formatted = totalSeconds.toFixed(1);
468056
+ if (options2?.hideTrailingZeros && formatted.endsWith(".0")) {
468057
+ return `${formatted.slice(0, -2)}s`;
468058
+ }
468059
+ return `${formatted}s`;
468044
468060
  }
468045
468061
  const hours = Math.floor(totalSeconds / 3600);
468046
468062
  const minutes = Math.floor(totalSeconds % 3600 / 60);
@@ -468065,7 +468081,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
468065
468081
 
468066
468082
  // packages/cli/src/generated/git-commit.ts
468067
468083
  init_esbuild_shims();
468068
- var GIT_COMMIT_INFO = "f2fac208f";
468084
+ var GIT_COMMIT_INFO = "9010c0912";
468069
468085
 
468070
468086
  // packages/cli/src/utils/systemInfo.ts
468071
468087
  async function getNpmVersion() {
@@ -497790,16 +497806,12 @@ var AnsiOutputText = /* @__PURE__ */ __name(({
497790
497806
  var ShellStatsBar = /* @__PURE__ */ __name(({
497791
497807
  totalLines,
497792
497808
  totalBytes,
497793
- timeoutMs,
497794
497809
  displayHeight = DEFAULT_HEIGHT
497795
497810
  }) => {
497796
497811
  const parts2 = [];
497797
497812
  if (totalLines && totalLines > displayHeight) {
497798
497813
  parts2.push(`+${totalLines - displayHeight} lines`);
497799
497814
  }
497800
- if (timeoutMs) {
497801
- parts2.push(`timeout ${formatDuration(timeoutMs)}`);
497802
- }
497803
497815
  if (totalBytes && totalBytes > 0) {
497804
497816
  parts2.push(formatMemoryUsage2(totalBytes));
497805
497817
  }
@@ -505280,21 +505292,10 @@ init_esbuild_shims();
505280
505292
  var import_react64 = __toESM(require_react(), 1);
505281
505293
  init_types22();
505282
505294
  var import_jsx_runtime35 = __toESM(require_jsx_runtime(), 1);
505283
- function formatElapsed(seconds) {
505284
- if (seconds < 60) return `${seconds}s`;
505285
- const minutes = Math.floor(seconds / 60);
505286
- const remainingSeconds = seconds % 60;
505287
- if (minutes < 60) {
505288
- return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
505289
- }
505290
- const hours = Math.floor(minutes / 60);
505291
- const remainingMinutes = minutes % 60;
505292
- return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
505293
- }
505294
- __name(formatElapsed, "formatElapsed");
505295
505295
  var ToolElapsedTime = /* @__PURE__ */ __name(({
505296
505296
  status,
505297
- executionStartTime
505297
+ executionStartTime,
505298
+ timeoutMs
505298
505299
  }) => {
505299
505300
  const [elapsedSeconds, setElapsedSeconds] = (0, import_react64.useState)(0);
505300
505301
  (0, import_react64.useEffect)(() => {
@@ -505308,8 +505309,14 @@ var ToolElapsedTime = /* @__PURE__ */ __name(({
505308
505309
  }, 1e3);
505309
505310
  return () => clearInterval(interval);
505310
505311
  }, [status, executionStartTime]);
505311
- if (status !== "Executing" /* Executing */ || elapsedSeconds < 3) return null;
505312
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Box_default, { flexShrink: 0, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Text3, { color: theme.text.secondary, children: formatElapsed(elapsedSeconds) }) });
505312
+ if (status !== "Executing" /* Executing */) return null;
505313
+ const hasTimeout = timeoutMs != null && timeoutMs > 0;
505314
+ if (!hasTimeout && elapsedSeconds < 3) return null;
505315
+ const elapsedStr = formatDuration(elapsedSeconds * 1e3, {
505316
+ hideTrailingZeros: true
505317
+ });
505318
+ const label = hasTimeout ? `(${elapsedStr} \xB7 timeout ${formatDuration(timeoutMs, { hideTrailingZeros: true })})` : elapsedStr;
505319
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Box_default, { flexShrink: 0, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Text3, { color: theme.text.secondary, children: label }) });
505313
505320
  }, "ToolElapsedTime");
505314
505321
 
505315
505322
  // packages/cli/src/ui/components/messages/ToolMessage.tsx
@@ -505363,8 +505370,7 @@ var useResultDisplayRenderer = /* @__PURE__ */ __name((resultDisplay) => import_
505363
505370
  data: display.ansiOutput,
505364
505371
  stats: {
505365
505372
  totalLines: display.totalLines,
505366
- totalBytes: display.totalBytes,
505367
- timeoutMs: display.timeoutMs
505373
+ totalBytes: display.totalBytes
505368
505374
  }
505369
505375
  };
505370
505376
  }
@@ -505458,6 +505464,12 @@ var ToolMessage = /* @__PURE__ */ __name(({
505458
505464
  setLastUpdateTime(/* @__PURE__ */ new Date());
505459
505465
  }
505460
505466
  }, [resultDisplay]);
505467
+ const shellTimeoutMs = import_react65.default.useMemo(() => {
505468
+ if (typeof resultDisplay === "object" && resultDisplay !== null && "ansiOutput" in resultDisplay) {
505469
+ return resultDisplay.timeoutMs;
505470
+ }
505471
+ return void 0;
505472
+ }, [resultDisplay]);
505461
505473
  import_react65.default.useEffect(() => {
505462
505474
  if (!lastUpdateTime) {
505463
505475
  return;
@@ -505509,7 +505521,8 @@ var ToolMessage = /* @__PURE__ */ __name(({
505509
505521
  ToolElapsedTime,
505510
505522
  {
505511
505523
  status,
505512
- executionStartTime
505524
+ executionStartTime,
505525
+ timeoutMs: shellTimeoutMs
505513
505526
  }
505514
505527
  ),
505515
505528
  emphasis === "high" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TrailingIndicator, {})
@@ -505641,6 +505654,14 @@ function getActiveTool(toolCalls) {
505641
505654
  return toolCalls.find((t5) => t5.status === "Confirming" /* Confirming */) ?? toolCalls.find((t5) => t5.status === "Executing" /* Executing */) ?? toolCalls[toolCalls.length - 1];
505642
505655
  }
505643
505656
  __name(getActiveTool, "getActiveTool");
505657
+ function getShellTimeoutMs(tool) {
505658
+ const display = tool.resultDisplay;
505659
+ if (typeof display === "object" && display !== null && "ansiOutput" in display) {
505660
+ return display.timeoutMs;
505661
+ }
505662
+ return void 0;
505663
+ }
505664
+ __name(getShellTimeoutMs, "getShellTimeoutMs");
505644
505665
  var CompactToolGroupDisplay = /* @__PURE__ */ __name(({ toolCalls, contentWidth }) => {
505645
505666
  if (toolCalls.length === 0) return null;
505646
505667
  const overallStatus = getOverallStatus(toolCalls);
@@ -505680,7 +505701,8 @@ var CompactToolGroupDisplay = /* @__PURE__ */ __name(({ toolCalls, contentWidth
505680
505701
  ToolElapsedTime,
505681
505702
  {
505682
505703
  status: overallStatus,
505683
- executionStartTime: activeTool.executionStartTime
505704
+ executionStartTime: activeTool.executionStartTime,
505705
+ timeoutMs: getShellTimeoutMs(activeTool)
505684
505706
  }
505685
505707
  )
505686
505708
  ] }),
@@ -524187,9 +524209,11 @@ function useResumeCommand(options2) {
524187
524209
  setResumeMatchedSessions(void 0);
524188
524210
  }, []);
524189
524211
  const { config: config2, historyManager, startNewSession, setSessionName, remount } = options2 ?? {};
524212
+ const hasHistoryManager = !!historyManager;
524213
+ const { clearItems, loadHistory } = historyManager || {};
524190
524214
  const handleResume = (0, import_react146.useCallback)(
524191
524215
  async (sessionId) => {
524192
- if (!config2 || !historyManager || !startNewSession) {
524216
+ if (!config2 || !hasHistoryManager || !startNewSession) {
524193
524217
  return;
524194
524218
  }
524195
524219
  closeResumeDialog();
@@ -524203,8 +524227,8 @@ function useResumeCommand(options2) {
524203
524227
  const customTitle = sessionService.getSessionTitle(sessionId);
524204
524228
  setSessionName?.(customTitle ?? null);
524205
524229
  const uiHistoryItems = buildResumedHistoryItems(sessionData, config2);
524206
- historyManager.clearItems();
524207
- historyManager.loadHistory(uiHistoryItems);
524230
+ clearItems?.();
524231
+ loadHistory?.(uiHistoryItems);
524208
524232
  config2.startNewSession(sessionId, sessionData);
524209
524233
  await config2.getGeminiClient()?.initialize?.();
524210
524234
  try {
@@ -524221,7 +524245,9 @@ function useResumeCommand(options2) {
524221
524245
  [
524222
524246
  closeResumeDialog,
524223
524247
  config2,
524224
- historyManager,
524248
+ hasHistoryManager,
524249
+ clearItems,
524250
+ loadHistory,
524225
524251
  startNewSession,
524226
524252
  setSessionName,
524227
524253
  remount
@@ -538367,7 +538393,7 @@ var QwenAgent = class {
538367
538393
  async initialize(args2) {
538368
538394
  this.clientCapabilities = args2.clientCapabilities;
538369
538395
  const authMethods = buildAuthMethods();
538370
- const version2 = "0.15.0";
538396
+ const version2 = "0.15.1";
538371
538397
  return {
538372
538398
  protocolVersion: PROTOCOL_VERSION,
538373
538399
  agentInfo: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwen-code/qwen-code",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "description": "Qwen Code - AI-powered coding assistant",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  "bundled"
22
22
  ],
23
23
  "config": {
24
- "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.15.0"
24
+ "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.15.1"
25
25
  },
26
26
  "dependencies": {},
27
27
  "optionalDependencies": {