@protolabsai/proto 0.33.0 → 0.34.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 +408 -114
  2. package/package.json +2 -2
package/cli.js CHANGED
@@ -169086,7 +169086,7 @@ __export(geminiContentGenerator_exports, {
169086
169086
  createGeminiContentGenerator: () => createGeminiContentGenerator
169087
169087
  });
169088
169088
  function createGeminiContentGenerator(config2, gcConfig) {
169089
- const version2 = "0.33.0";
169089
+ const version2 = "0.34.1";
169090
169090
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
169091
169091
  const baseHeaders = {
169092
169092
  "User-Agent": userAgent2
@@ -181839,11 +181839,11 @@ var init_shellExecutionService = __esm({
181839
181839
  getErrorMessage2 = /* @__PURE__ */ __name((error40) => error40 instanceof Error ? error40.message : String(error40), "getErrorMessage");
181840
181840
  isExpectedPtyReadExitError = /* @__PURE__ */ __name((error40) => {
181841
181841
  const code2 = getErrnoCode(error40);
181842
- if (code2 === "EIO") {
181842
+ if (code2 === "EIO" || code2 === "EAGAIN") {
181843
181843
  return true;
181844
181844
  }
181845
181845
  const message = getErrorMessage2(error40);
181846
- return message.includes("read EIO");
181846
+ return message.includes("read EIO") || message.includes("EAGAIN");
181847
181847
  }, "isExpectedPtyReadExitError");
181848
181848
  isExpectedPtyExitRaceError = /* @__PURE__ */ __name((error40) => {
181849
181849
  const code2 = getErrnoCode(error40);
@@ -187118,7 +187118,7 @@ function toParts(input) {
187118
187118
  }
187119
187119
  return parts2;
187120
187120
  }
187121
- var import_fast_levenshtein, debugLogger32, toolTracer, TRUNCATION_PARAM_GUIDANCE, TRUNCATION_EDIT_REJECTION, createErrorResponse, CoreToolScheduler;
187121
+ var import_fast_levenshtein, debugLogger32, toolTracer, TRUNCATION_PARAM_GUIDANCE, TRUNCATION_EDIT_REJECTION, VALIDATION_RETRY_LOOP_THRESHOLD, RETRY_LOOP_STOP_DIRECTIVE, createErrorResponse, CoreToolScheduler;
187122
187122
  var init_coreToolScheduler = __esm({
187123
187123
  "packages/core/dist/src/core/coreToolScheduler.js"() {
187124
187124
  "use strict";
@@ -187146,6 +187146,8 @@ var init_coreToolScheduler = __esm({
187146
187146
  __name(createFunctionResponsePart, "createFunctionResponsePart");
187147
187147
  __name(convertToFunctionResponse, "convertToFunctionResponse");
187148
187148
  __name(toParts, "toParts");
187149
+ VALIDATION_RETRY_LOOP_THRESHOLD = 3;
187150
+ RETRY_LOOP_STOP_DIRECTIVE = "\n\n\u26A0\uFE0F RETRY LOOP DETECTED: This tool call has failed validation multiple times with the same error. STOP retrying the same approach. Re-examine the tool schema and parameter requirements, then try a fundamentally different approach. If you cannot resolve the validation error, explain the issue to the user instead of retrying.";
187149
187151
  createErrorResponse = /* @__PURE__ */ __name((request3, error40, errorType) => ({
187150
187152
  callId: request3.callId,
187151
187153
  error: error40,
@@ -187177,6 +187179,7 @@ var init_coreToolScheduler = __esm({
187177
187179
  chatRecordingService;
187178
187180
  isFinalizingToolCalls = false;
187179
187181
  isScheduling = false;
187182
+ validationRetryCounts = /* @__PURE__ */ new Map();
187180
187183
  requestQueue = [];
187181
187184
  constructor(options2) {
187182
187185
  this.config = options2.config;
@@ -187199,6 +187202,7 @@ var init_coreToolScheduler = __esm({
187199
187202
  const outcome = currentCall.outcome;
187200
187203
  switch (newStatus) {
187201
187204
  case "success": {
187205
+ this.clearRetryCountsForTool(currentCall.request.name);
187202
187206
  const durationMs = existingStartTime ? Date.now() - existingStartTime : void 0;
187203
187207
  return {
187204
187208
  request: currentCall.request,
@@ -187417,6 +187421,19 @@ var init_coreToolScheduler = __esm({
187417
187421
  }
187418
187422
  return this._schedule(request3, signal);
187419
187423
  }
187424
+ /**
187425
+ * Removes all validation retry counters for the given tool. Keys are
187426
+ * "<toolName>:<errorMessage>", so a plain `Map.delete(toolName)` would not
187427
+ * match anything.
187428
+ */
187429
+ clearRetryCountsForTool(toolName) {
187430
+ const prefix = `${toolName}:`;
187431
+ for (const key of this.validationRetryCounts.keys()) {
187432
+ if (key.startsWith(prefix)) {
187433
+ this.validationRetryCounts.delete(key);
187434
+ }
187435
+ }
187436
+ }
187420
187437
  async _schedule(request3, signal) {
187421
187438
  this.isScheduling = true;
187422
187439
  try {
@@ -187424,6 +187441,17 @@ var init_coreToolScheduler = __esm({
187424
187441
  throw new Error("Cannot schedule new tool calls while other tool calls are actively running (executing or awaiting approval).");
187425
187442
  }
187426
187443
  const requestsToProcess = Array.isArray(request3) ? request3 : [request3];
187444
+ if (this.validationRetryCounts.size > 0) {
187445
+ const prevTools = /* @__PURE__ */ new Set();
187446
+ for (const key of this.validationRetryCounts.keys()) {
187447
+ const sep12 = key.indexOf(":");
187448
+ prevTools.add(sep12 === -1 ? key : key.slice(0, sep12));
187449
+ }
187450
+ const hasPrevFailingTool = requestsToProcess.some((r5) => prevTools.has(r5.name));
187451
+ if (!hasPrevFailingTool) {
187452
+ this.validationRetryCounts.clear();
187453
+ }
187454
+ }
187427
187455
  const newToolCalls = [];
187428
187456
  for (const reqInfo of requestsToProcess) {
187429
187457
  const pm = this.config.getPermissionManager?.();
@@ -187482,16 +187510,26 @@ var init_coreToolScheduler = __esm({
187482
187510
  }
187483
187511
  const invocationOrError = this.buildInvocation(toolInstance, reqInfo.args);
187484
187512
  if (invocationOrError instanceof Error) {
187485
- const error40 = reqInfo.wasOutputTruncated ? new Error(`${invocationOrError.message} ${TRUNCATION_PARAM_GUIDANCE}`) : invocationOrError;
187513
+ const baseError = reqInfo.wasOutputTruncated ? new Error(`${invocationOrError.message} ${TRUNCATION_PARAM_GUIDANCE}`) : invocationOrError;
187514
+ const errorKey = `${reqInfo.name}:${baseError.message}`;
187515
+ const count = (this.validationRetryCounts.get(errorKey) ?? 0) + 1;
187516
+ for (const key of this.validationRetryCounts.keys()) {
187517
+ if (key.startsWith(`${reqInfo.name}:`) && key !== errorKey) {
187518
+ this.validationRetryCounts.delete(key);
187519
+ }
187520
+ }
187521
+ this.validationRetryCounts.set(errorKey, count);
187522
+ const finalError = count >= VALIDATION_RETRY_LOOP_THRESHOLD ? new Error(`${baseError.message}${RETRY_LOOP_STOP_DIRECTIVE}`) : baseError;
187486
187523
  newToolCalls.push({
187487
187524
  status: "error",
187488
187525
  request: reqInfo,
187489
187526
  tool: toolInstance,
187490
- response: createErrorResponse(reqInfo, error40, ToolErrorType.INVALID_TOOL_PARAMS),
187527
+ response: createErrorResponse(reqInfo, finalError, ToolErrorType.INVALID_TOOL_PARAMS),
187491
187528
  durationMs: 0
187492
187529
  });
187493
187530
  continue;
187494
187531
  }
187532
+ this.clearRetryCountsForTool(reqInfo.name);
187495
187533
  if (reqInfo.wasOutputTruncated && toolInstance.kind === Kind.Edit) {
187496
187534
  const truncationError = new Error(TRUNCATION_EDIT_REJECTION);
187497
187535
  newToolCalls.push({
@@ -274659,6 +274697,7 @@ var init_config3 = __esm({
274659
274697
  hooks;
274660
274698
  hookSystem;
274661
274699
  messageBus;
274700
+ modelChangeListeners = /* @__PURE__ */ new Set();
274662
274701
  constructor(params) {
274663
274702
  this.sessionId = params.sessionId ?? randomUUID5();
274664
274703
  this.sessionData = params.sessionData;
@@ -275065,6 +275104,18 @@ var init_config3 = __esm({
275065
275104
  getModel() {
275066
275105
  return this.contentGeneratorConfig?.model || this.modelsConfig.getModel();
275067
275106
  }
275107
+ onModelChange(listener) {
275108
+ this.modelChangeListeners.add(listener);
275109
+ return () => {
275110
+ this.modelChangeListeners.delete(listener);
275111
+ };
275112
+ }
275113
+ notifyModelChangeListeners() {
275114
+ const model = this.getModel();
275115
+ for (const listener of this.modelChangeListeners) {
275116
+ listener(model);
275117
+ }
275118
+ }
275068
275119
  /**
275069
275120
  * Set model programmatically (e.g., VLM auto-switch, fallback).
275070
275121
  * Delegates to ModelsConfig.
@@ -275074,6 +275125,7 @@ var init_config3 = __esm({
275074
275125
  if (this.contentGeneratorConfig) {
275075
275126
  this.contentGeneratorConfig.model = newModel;
275076
275127
  }
275128
+ this.notifyModelChangeListeners();
275077
275129
  }
275078
275130
  /**
275079
275131
  * Handle model change from ModelsConfig.
@@ -275126,6 +275178,7 @@ var init_config3 = __esm({
275126
275178
  */
275127
275179
  async switchModel(authType, modelId) {
275128
275180
  await this.modelsConfig.switchModel(authType, modelId);
275181
+ this.notifyModelChangeListeners();
275129
275182
  }
275130
275183
  getMaxSessionTurns() {
275131
275184
  return this.maxSessionTurns;
@@ -416752,7 +416805,7 @@ __name(getPackageJson, "getPackageJson");
416752
416805
  // packages/cli/src/utils/version.ts
416753
416806
  async function getCliVersion() {
416754
416807
  const pkgJson = await getPackageJson();
416755
- return "0.33.0";
416808
+ return "0.34.1";
416756
416809
  }
416757
416810
  __name(getCliVersion, "getCliVersion");
416758
416811
 
@@ -424763,7 +424816,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
424763
424816
 
424764
424817
  // packages/cli/src/generated/git-commit.ts
424765
424818
  init_esbuild_shims();
424766
- var GIT_COMMIT_INFO = "52c7da728";
424819
+ var GIT_COMMIT_INFO = "bcae944e9";
424767
424820
 
424768
424821
  // packages/cli/src/utils/systemInfo.ts
424769
424822
  async function getNpmVersion() {
@@ -439592,6 +439645,64 @@ var getCachedStringWidth = /* @__PURE__ */ __name((str2) => {
439592
439645
  stringWidthCache.set(str2, width);
439593
439646
  return width;
439594
439647
  }, "getCachedStringWidth");
439648
+ function sliceTextByVisualHeight(text, maxHeight, maxWidth, options2 = {}) {
439649
+ if (maxHeight === void 0) {
439650
+ return { text, hiddenLinesCount: 0 };
439651
+ }
439652
+ const targetMaxHeight = Math.max(
439653
+ Math.round(maxHeight),
439654
+ options2.minHeight ?? 1
439655
+ );
439656
+ const visibleContentHeight = Math.max(
439657
+ 1,
439658
+ targetMaxHeight - (options2.reservedRows ?? 0)
439659
+ );
439660
+ const visualWidth = Math.max(1, Math.floor(maxWidth));
439661
+ const overflowDirection = options2.overflowDirection ?? "top";
439662
+ const visibleLines = [];
439663
+ let visualLineCount = 0;
439664
+ let currentLine = "";
439665
+ let currentLineWidth = 0;
439666
+ const appendVisibleLine = /* @__PURE__ */ __name((line) => {
439667
+ visualLineCount += 1;
439668
+ if (overflowDirection === "bottom") {
439669
+ if (visibleLines.length < visibleContentHeight) {
439670
+ visibleLines.push(line);
439671
+ }
439672
+ return;
439673
+ }
439674
+ visibleLines.push(line);
439675
+ if (visibleLines.length > visibleContentHeight) {
439676
+ visibleLines.shift();
439677
+ }
439678
+ }, "appendVisibleLine");
439679
+ const flushCurrentLine = /* @__PURE__ */ __name(() => {
439680
+ appendVisibleLine(currentLine);
439681
+ currentLine = "";
439682
+ currentLineWidth = 0;
439683
+ }, "flushCurrentLine");
439684
+ for (const char of toCodePoints(text)) {
439685
+ if (char === "\n") {
439686
+ flushCurrentLine();
439687
+ continue;
439688
+ }
439689
+ const charWidth = Math.max(getCachedStringWidth(char), 1);
439690
+ if (currentLineWidth > 0 && currentLineWidth + charWidth > visualWidth) {
439691
+ flushCurrentLine();
439692
+ }
439693
+ currentLine += char;
439694
+ currentLineWidth += charWidth;
439695
+ }
439696
+ flushCurrentLine();
439697
+ if (visualLineCount <= visibleContentHeight) {
439698
+ return { text, hiddenLinesCount: 0 };
439699
+ }
439700
+ return {
439701
+ text: visibleLines.join("\n"),
439702
+ hiddenLinesCount: visualLineCount - visibleContentHeight
439703
+ };
439704
+ }
439705
+ __name(sliceTextByVisualHeight, "sliceTextByVisualHeight");
439595
439706
  var regex2 = ansiRegex();
439596
439707
  function escapeAnsiCtrlCodes(obj) {
439597
439708
  if (typeof obj === "string") {
@@ -461554,25 +461665,82 @@ var getStatusText = /* @__PURE__ */ __name((status) => {
461554
461665
  }
461555
461666
  }, "getStatusText");
461556
461667
  var MAX_TOOL_CALLS = 5;
461668
+ var MAX_VERBOSE_TOOL_CALLS = 12;
461557
461669
  var MAX_TASK_PROMPT_LINES = 5;
461670
+ var DEFAULT_DETAIL_HEIGHT = 18;
461671
+ var RUNNING_FIXED_OVERHEAD = 10;
461672
+ var COMPLETED_FIXED_OVERHEAD = 22;
461673
+ var ROWS_PER_TOOL_CALL = 2;
461674
+ function truncateToVisualWidth(text, maxWidth) {
461675
+ const visualWidth = Math.max(1, Math.floor(maxWidth));
461676
+ const ellipsis = "...";
461677
+ const ellipsisWidth = getCachedStringWidth(ellipsis);
461678
+ let currentWidth = 0;
461679
+ let result = "";
461680
+ for (const char of toCodePoints(text)) {
461681
+ const charWidth = Math.max(getCachedStringWidth(char), 1);
461682
+ if (currentWidth + charWidth > visualWidth) {
461683
+ const availableWidth = Math.max(0, visualWidth - ellipsisWidth);
461684
+ let trimmed2 = "";
461685
+ let trimmedWidth = 0;
461686
+ for (const trimmedChar of toCodePoints(result)) {
461687
+ const trimmedCharWidth = Math.max(getCachedStringWidth(trimmedChar), 1);
461688
+ if (trimmedWidth + trimmedCharWidth > availableWidth) {
461689
+ break;
461690
+ }
461691
+ trimmed2 += trimmedChar;
461692
+ trimmedWidth += trimmedCharWidth;
461693
+ }
461694
+ return trimmed2 + ellipsis;
461695
+ }
461696
+ result += char;
461697
+ currentWidth += charWidth;
461698
+ }
461699
+ return result;
461700
+ }
461701
+ __name(truncateToVisualWidth, "truncateToVisualWidth");
461558
461702
  var AgentExecutionDisplay = /* @__PURE__ */ __name(({
461559
461703
  data,
461560
461704
  availableHeight,
461561
461705
  childWidth,
461562
- config: config2
461706
+ config: config2,
461707
+ isFocused = true
461563
461708
  }) => {
461564
461709
  const [displayMode, setDisplayMode] = import_react62.default.useState("compact");
461710
+ const detailHeight = Math.max(
461711
+ 4,
461712
+ Math.floor(availableHeight ?? DEFAULT_DETAIL_HEIGHT)
461713
+ );
461714
+ const fixedOverhead = data.status === "running" ? RUNNING_FIXED_OVERHEAD : COMPLETED_FIXED_OVERHEAD;
461715
+ const renderableBudget = Math.max(2, detailHeight - fixedOverhead);
461716
+ const promptBudget = Math.max(1, Math.floor(renderableBudget / 3));
461717
+ const toolBudget = Math.max(
461718
+ 1,
461719
+ Math.floor((renderableBudget - promptBudget) / ROWS_PER_TOOL_CALL)
461720
+ );
461721
+ const maxTaskPromptLines = displayMode === "verbose" ? Math.min(8, promptBudget) : Math.min(MAX_TASK_PROMPT_LINES, promptBudget);
461722
+ const maxToolCalls = displayMode === "verbose" ? Math.min(MAX_VERBOSE_TOOL_CALLS, toolBudget) : Math.min(MAX_TOOL_CALLS, toolBudget);
461565
461723
  const agentColor = (0, import_react62.useMemo)(() => {
461566
461724
  const colorOption = COLOR_OPTIONS.find(
461567
461725
  (option2) => option2.name === data.subagentColor
461568
461726
  );
461569
461727
  return colorOption?.value || theme.text.accent;
461570
461728
  }, [data.subagentColor]);
461729
+ const promptChildWidth = Math.max(1, childWidth - 2);
461730
+ const slicedPrompt = (0, import_react62.useMemo)(
461731
+ () => sliceTextByVisualHeight(
461732
+ data.taskPrompt,
461733
+ maxTaskPromptLines,
461734
+ promptChildWidth,
461735
+ { minHeight: 1, overflowDirection: "bottom" }
461736
+ ),
461737
+ [data.taskPrompt, maxTaskPromptLines, promptChildWidth]
461738
+ );
461571
461739
  const footerText = import_react62.default.useMemo(() => {
461572
461740
  if (data.status !== "running") return "";
461573
461741
  if (displayMode === "default") {
461574
- const hasMoreLines = data.taskPrompt.split("\n").length > MAX_TASK_PROMPT_LINES;
461575
- const hasMoreToolCalls = data.toolCalls && data.toolCalls.length > MAX_TOOL_CALLS;
461742
+ const hasMoreLines = slicedPrompt.hiddenLinesCount > 0;
461743
+ const hasMoreToolCalls = data.toolCalls && data.toolCalls.length > maxToolCalls;
461576
461744
  if (hasMoreToolCalls || hasMoreLines) {
461577
461745
  return "Press ctrl+e to show less, ctrl+f to show more.";
461578
461746
  }
@@ -461582,7 +461750,13 @@ var AgentExecutionDisplay = /* @__PURE__ */ __name(({
461582
461750
  return "Press ctrl+f to show less.";
461583
461751
  }
461584
461752
  return "";
461585
- }, [displayMode, data]);
461753
+ }, [
461754
+ displayMode,
461755
+ data.status,
461756
+ data.toolCalls,
461757
+ slicedPrompt.hiddenLinesCount,
461758
+ maxToolCalls
461759
+ ]);
461586
461760
  useKeypress(
461587
461761
  (key) => {
461588
461762
  if (key.ctrl && key.name === "e") {
@@ -461595,7 +461769,7 @@ var AgentExecutionDisplay = /* @__PURE__ */ __name(({
461595
461769
  );
461596
461770
  }
461597
461771
  },
461598
- { isActive: true }
461772
+ { isActive: data.status === "running" && isFocused }
461599
461773
  );
461600
461774
  if (displayMode === "compact") {
461601
461775
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", children: [
@@ -461654,15 +461828,18 @@ var AgentExecutionDisplay = /* @__PURE__ */ __name(({
461654
461828
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
461655
461829
  TaskPromptSection,
461656
461830
  {
461657
- taskPrompt: data.taskPrompt,
461658
- displayMode
461831
+ slicedPrompt,
461832
+ displayMode,
461833
+ maxVisualLines: maxTaskPromptLines
461659
461834
  }
461660
461835
  ),
461661
461836
  data.status === "running" && data.toolCalls && data.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
461662
461837
  ToolCallsList,
461663
461838
  {
461664
461839
  toolCalls: data.toolCalls,
461665
- displayMode
461840
+ displayMode,
461841
+ maxToolCalls,
461842
+ childWidth: childWidth - 2
461666
461843
  }
461667
461844
  ) }),
461668
461845
  data.pendingConfirmation && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
@@ -461676,26 +461853,38 @@ var AgentExecutionDisplay = /* @__PURE__ */ __name(({
461676
461853
  compactMode: true
461677
461854
  }
461678
461855
  ) }),
461679
- (data.status === "completed" || data.status === "failed" || data.status === "cancelled") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ResultsSection, { data, displayMode }),
461856
+ (data.status === "completed" || data.status === "failed" || data.status === "cancelled") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
461857
+ ResultsSection,
461858
+ {
461859
+ data,
461860
+ displayMode,
461861
+ maxToolCalls,
461862
+ childWidth: childWidth - 2
461863
+ }
461864
+ ),
461680
461865
  footerText && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { flexDirection: "row", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color: theme.text.secondary, children: footerText }) })
461681
461866
  ] });
461682
461867
  }, "AgentExecutionDisplay");
461683
- var TaskPromptSection = /* @__PURE__ */ __name(({ taskPrompt, displayMode }) => {
461684
- const lines = taskPrompt.split("\n");
461685
- const shouldTruncate = lines.length > 10;
461686
- const showFull = displayMode === "verbose";
461687
- const displayLines = showFull ? lines : lines.slice(0, MAX_TASK_PROMPT_LINES);
461868
+ var TaskPromptSection = /* @__PURE__ */ __name(({ slicedPrompt, displayMode, maxVisualLines }) => {
461869
+ const shouldTruncate = slicedPrompt.hiddenLinesCount > 0;
461688
461870
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", gap: 1, children: [
461689
461871
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "row", children: [
461690
461872
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color: theme.text.primary, children: "Task Detail: " }),
461691
- shouldTruncate && displayMode === "default" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Text3, { color: theme.text.secondary, children: [
461873
+ shouldTruncate && displayMode !== "compact" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Text3, { color: theme.text.secondary, children: [
461692
461874
  " ",
461693
461875
  "Showing the first ",
461694
- MAX_TASK_PROMPT_LINES,
461695
- " lines."
461876
+ maxVisualLines,
461877
+ " visual lines."
461696
461878
  ] })
461697
461879
  ] }),
461698
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { paddingLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { wrap: "wrap", children: displayLines.join("\n") + (shouldTruncate && !showFull ? "..." : "") }) })
461880
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { paddingLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { wrap: "wrap", children: slicedPrompt.text }) }),
461881
+ slicedPrompt.hiddenLinesCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { paddingLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Text3, { color: theme.text.secondary, wrap: "truncate", children: [
461882
+ "... last ",
461883
+ slicedPrompt.hiddenLinesCount,
461884
+ " task line",
461885
+ slicedPrompt.hiddenLinesCount === 1 ? "" : "s",
461886
+ " hidden ..."
461887
+ ] }) })
461699
461888
  ] });
461700
461889
  }, "TaskPromptSection");
461701
461890
  var StatusDot = /* @__PURE__ */ __name(({ status }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { marginLeft: 1, marginRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color: getStatusColor(status), children: "\u25CF" }) }), "StatusDot");
@@ -461704,29 +461893,37 @@ var StatusIndicator = /* @__PURE__ */ __name(({ status }) => {
461704
461893
  const text = getStatusText(status);
461705
461894
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color, children: text });
461706
461895
  }, "StatusIndicator");
461707
- var ToolCallsList = /* @__PURE__ */ __name(({ toolCalls, displayMode }) => {
461896
+ var ToolCallsList = /* @__PURE__ */ __name(({ toolCalls, displayMode, maxToolCalls, childWidth }) => {
461708
461897
  const calls = toolCalls || [];
461709
- const shouldTruncate = calls.length > MAX_TOOL_CALLS;
461710
- const showAll = displayMode === "verbose";
461711
- const displayCalls = showAll ? calls : calls.slice(-MAX_TOOL_CALLS);
461898
+ const displayLimit = Math.max(1, Math.floor(maxToolCalls));
461899
+ const shouldTruncate = calls.length > displayLimit;
461900
+ const displayCalls = calls.slice(-displayLimit);
461712
461901
  const reversedDisplayCalls = [...displayCalls].reverse();
461713
461902
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", children: [
461714
461903
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "row", marginBottom: 1, children: [
461715
461904
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color: theme.text.primary, children: "Tools:" }),
461716
- shouldTruncate && displayMode === "default" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Text3, { color: theme.text.secondary, children: [
461905
+ shouldTruncate && displayMode !== "compact" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Text3, { color: theme.text.secondary, children: [
461717
461906
  " ",
461718
461907
  "Showing the last ",
461719
- MAX_TOOL_CALLS,
461908
+ displayCalls.length,
461720
461909
  " of ",
461721
461910
  calls.length,
461722
461911
  " tools."
461723
461912
  ] })
461724
461913
  ] }),
461725
- reversedDisplayCalls.map((toolCall, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToolCallItem, { toolCall }, `${toolCall.name}-${index}`))
461914
+ reversedDisplayCalls.map((toolCall, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
461915
+ ToolCallItem,
461916
+ {
461917
+ toolCall,
461918
+ childWidth
461919
+ },
461920
+ `${toolCall.name}-${index}`
461921
+ ))
461726
461922
  ] });
461727
461923
  }, "ToolCallsList");
461728
- var ToolCallItem = /* @__PURE__ */ __name(({ toolCall, compact = false }) => {
461924
+ var ToolCallItem = /* @__PURE__ */ __name(({ toolCall, compact = false, childWidth = 80 }) => {
461729
461925
  const STATUS_INDICATOR_WIDTH2 = 3;
461926
+ const textWidth = Math.max(8, childWidth - STATUS_INDICATOR_WIDTH2 - 1);
461730
461927
  const statusIcon = import_react62.default.useMemo(() => {
461731
461928
  const color = getStatusColor(toolCall.status);
461732
461929
  switch (toolCall.status) {
@@ -461746,13 +461943,13 @@ var ToolCallItem = /* @__PURE__ */ __name(({ toolCall, compact = false }) => {
461746
461943
  const description = import_react62.default.useMemo(() => {
461747
461944
  if (!toolCall.description) return "";
461748
461945
  const firstLine = toolCall.description.split("\n")[0];
461749
- return firstLine.length > 80 ? firstLine.substring(0, 80) + "..." : firstLine;
461750
- }, [toolCall.description]);
461946
+ return truncateToVisualWidth(firstLine, textWidth);
461947
+ }, [toolCall.description, textWidth]);
461751
461948
  const truncatedOutput = import_react62.default.useMemo(() => {
461752
461949
  if (!toolCall.resultDisplay) return "";
461753
461950
  const firstLine = toolCall.resultDisplay.split("\n")[0];
461754
- return firstLine.length > 80 ? firstLine.substring(0, 80) + "..." : firstLine;
461755
- }, [toolCall.resultDisplay]);
461951
+ return truncateToVisualWidth(firstLine, textWidth);
461952
+ }, [toolCall.resultDisplay, textWidth]);
461756
461953
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, marginBottom: 0, children: [
461757
461954
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "row", children: [
461758
461955
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { minWidth: STATUS_INDICATOR_WIDTH2, children: statusIcon }),
@@ -461833,8 +462030,16 @@ var ToolUsageStats = /* @__PURE__ */ __name(({ executionSummary }) => {
461833
462030
  ] })
461834
462031
  ] });
461835
462032
  }, "ToolUsageStats");
461836
- var ResultsSection = /* @__PURE__ */ __name(({ data, displayMode }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", gap: 1, children: [
461837
- data.toolCalls && data.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToolCallsList, { toolCalls: data.toolCalls, displayMode }),
462033
+ var ResultsSection = /* @__PURE__ */ __name(({ data, displayMode, maxToolCalls, childWidth }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", gap: 1, children: [
462034
+ data.toolCalls && data.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
462035
+ ToolCallsList,
462036
+ {
462037
+ toolCalls: data.toolCalls,
462038
+ displayMode,
462039
+ maxToolCalls,
462040
+ childWidth
462041
+ }
462042
+ ),
461838
462043
  data.status === "completed" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { flexDirection: "column", children: [
461839
462044
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Box_default, { flexDirection: "row", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Text3, { color: theme.text.primary, children: "Execution Summary:" }) }),
461840
462045
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ExecutionSummaryDetails, { data, displayMode })
@@ -465133,35 +465338,39 @@ var MainContent = /* @__PURE__ */ __name(() => {
465133
465338
  terminalWidth,
465134
465339
  mainAreaWidth,
465135
465340
  staticAreaMaxItemHeight,
465136
- availableTerminalHeight
465341
+ availableTerminalHeight,
465342
+ historyRemountKey
465137
465343
  } = uiState;
465138
- const staticItems = (0, import_react75.useMemo)(() => [
465139
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(AppHeader, { version: version2 }, "app-header"),
465140
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(DebugModeNotification, {}, "debug-notification"),
465141
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Notifications, {}, "notifications"),
465142
- ...uiState.history.map((h3) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
465143
- HistoryItemDisplayComponent,
465144
- {
465145
- terminalWidth,
465146
- mainAreaWidth,
465147
- availableTerminalHeight: staticAreaMaxItemHeight,
465148
- availableTerminalHeightGemini: MAX_GEMINI_MESSAGE_LINES,
465149
- item: h3,
465150
- isPending: false,
465151
- commands: uiState.slashCommands
465152
- },
465153
- h3.id
465154
- ))
465155
- ], [
465156
- uiState.history,
465157
- uiState.slashCommands,
465158
- version2,
465159
- terminalWidth,
465160
- mainAreaWidth,
465161
- staticAreaMaxItemHeight
465162
- ]);
465344
+ const staticItems = (0, import_react75.useMemo)(
465345
+ () => [
465346
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(AppHeader, { version: version2 }, "app-header"),
465347
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(DebugModeNotification, {}, "debug-notification"),
465348
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Notifications, {}, "notifications"),
465349
+ ...uiState.history.map((h3) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
465350
+ HistoryItemDisplayComponent,
465351
+ {
465352
+ terminalWidth,
465353
+ mainAreaWidth,
465354
+ availableTerminalHeight: staticAreaMaxItemHeight,
465355
+ availableTerminalHeightGemini: MAX_GEMINI_MESSAGE_LINES,
465356
+ item: h3,
465357
+ isPending: false,
465358
+ commands: uiState.slashCommands
465359
+ },
465360
+ h3.id
465361
+ ))
465362
+ ],
465363
+ [
465364
+ uiState.history,
465365
+ uiState.slashCommands,
465366
+ version2,
465367
+ terminalWidth,
465368
+ mainAreaWidth,
465369
+ staticAreaMaxItemHeight
465370
+ ]
465371
+ );
465163
465372
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [
465164
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Static, { items: staticItems, children: (item) => item }, `${uiState.historyRemountKey}`),
465373
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Static, { items: staticItems, children: (item) => item }, `${historyRemountKey}`),
465165
465374
  /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(OverflowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(Box_default, { flexDirection: "column", children: [
465166
465375
  pendingHistoryItems.map((item, i4) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
465167
465376
  HistoryItemDisplayComponent,
@@ -473831,6 +474040,61 @@ __name(RewindPicker, "RewindPicker");
473831
474040
 
473832
474041
  // packages/cli/src/ui/components/DialogManager.tsx
473833
474042
  init_dist4();
474043
+
474044
+ // packages/cli/src/ui/utils/historyMapping.ts
474045
+ init_esbuild_shims();
474046
+ function isRealUserTurn(item) {
474047
+ if (item.type !== "user" || !("text" in item) || !item.text) return false;
474048
+ return !item.text.startsWith("/") && !item.text.startsWith("?");
474049
+ }
474050
+ __name(isRealUserTurn, "isRealUserTurn");
474051
+ var STARTUP_CONTEXT_MODEL_ACK2 = "Got it. Thanks for the context!";
474052
+ function isUserTextContent(content) {
474053
+ if (content.role !== "user") return false;
474054
+ if (!content.parts || content.parts.length === 0) return false;
474055
+ const hasFunctionResponse = content.parts.some(
474056
+ (part) => "functionResponse" in part
474057
+ );
474058
+ if (hasFunctionResponse) return false;
474059
+ return content.parts.some((part) => "text" in part && Boolean(part.text));
474060
+ }
474061
+ __name(isUserTextContent, "isUserTextContent");
474062
+ function hasStartupContext(apiHistory) {
474063
+ if (apiHistory.length < 2) return false;
474064
+ const first2 = apiHistory[0];
474065
+ const second = apiHistory[1];
474066
+ if (first2?.role !== "user" || second?.role !== "model") return false;
474067
+ return second.parts?.some(
474068
+ (part) => "text" in part && part.text === STARTUP_CONTEXT_MODEL_ACK2
474069
+ ) ?? false;
474070
+ }
474071
+ __name(hasStartupContext, "hasStartupContext");
474072
+ function computeApiTruncationIndex(uiHistory, targetUserItemId, apiHistory) {
474073
+ let uiUserTurnCount = 0;
474074
+ for (const item of uiHistory) {
474075
+ if (item.id === targetUserItemId) break;
474076
+ if (isRealUserTurn(item)) {
474077
+ uiUserTurnCount++;
474078
+ }
474079
+ }
474080
+ const startIndex = hasStartupContext(apiHistory) ? 2 : 0;
474081
+ if (uiUserTurnCount === 0) {
474082
+ return startIndex;
474083
+ }
474084
+ let realUserPromptCount = 0;
474085
+ for (let i4 = startIndex; i4 < apiHistory.length; i4++) {
474086
+ if (isUserTextContent(apiHistory[i4])) {
474087
+ realUserPromptCount++;
474088
+ if (realUserPromptCount > uiUserTurnCount) {
474089
+ return i4;
474090
+ }
474091
+ }
474092
+ }
474093
+ return -1;
474094
+ }
474095
+ __name(computeApiTruncationIndex, "computeApiTruncationIndex");
474096
+
474097
+ // packages/cli/src/ui/components/DialogManager.tsx
473834
474098
  var import_jsx_runtime115 = __toESM(require_jsx_runtime(), 1);
473835
474099
  var DialogManager = /* @__PURE__ */ __name(({
473836
474100
  addItem,
@@ -474143,42 +474407,49 @@ var DialogManager = /* @__PURE__ */ __name(({
474143
474407
  }, "getUiHistoryCutIndex");
474144
474408
  const applyConversationRewind = /* @__PURE__ */ __name((promptId) => {
474145
474409
  const cutIdx = getUiHistoryCutIndex(promptId);
474410
+ const targetUserItem = uiState.history[cutIdx];
474146
474411
  const slicedUiHistory = uiState.history.slice(0, cutIdx);
474147
- uiState.historyManager.loadHistory(slicedUiHistory);
474148
- uiActions.refreshStatic();
474412
+ let compressionAbort = false;
474149
474413
  const geminiClient = config2?.getGeminiClient?.();
474150
- if (geminiClient) {
474151
- const userTurnCount = slicedUiHistory.filter(
474152
- (item) => item.type === "user"
474153
- ).length;
474414
+ if (geminiClient && targetUserItem) {
474154
474415
  const llmHistory = geminiClient.getHistory();
474155
- let usersSeen = 0;
474156
- let llmCutIdx = 0;
474157
- for (let i4 = 0; i4 < llmHistory.length; i4++) {
474158
- if (llmHistory[i4].role === "user") {
474159
- usersSeen++;
474160
- if (usersSeen > userTurnCount) {
474161
- llmCutIdx = i4;
474162
- break;
474163
- }
474164
- llmCutIdx = i4 + 1;
474165
- }
474166
- }
474167
- geminiClient.setHistory(
474168
- userTurnCount === 0 ? [] : llmHistory.slice(0, llmCutIdx)
474416
+ const apiCutIdx = computeApiTruncationIndex(
474417
+ uiState.history,
474418
+ targetUserItem.id,
474419
+ llmHistory
474169
474420
  );
474421
+ if (apiCutIdx < 0) {
474422
+ compressionAbort = true;
474423
+ } else {
474424
+ geminiClient.setHistory(llmHistory.slice(0, apiCutIdx));
474425
+ geminiClient.stripThoughtsFromHistory();
474426
+ }
474427
+ }
474428
+ if (!compressionAbort) {
474429
+ uiState.historyManager.loadHistory(slicedUiHistory);
474430
+ uiActions.refreshStatic();
474170
474431
  }
474171
474432
  const checkpoint = checkpointStore.getByPromptId(promptId);
474172
474433
  const originalPrompt = checkpoint?.userPrompt ?? "";
474173
- return { slicedUiHistory, originalPrompt };
474434
+ return { slicedUiHistory, originalPrompt, compressionAbort };
474174
474435
  }, "applyConversationRewind");
474175
474436
  const handleRestoreFilesAndConversation = /* @__PURE__ */ __name((promptId) => {
474176
474437
  try {
474177
474438
  checkpointStore.rewindToCheckpoint(promptId);
474178
474439
  } catch {
474179
474440
  }
474180
- const { slicedUiHistory, originalPrompt } = applyConversationRewind(promptId);
474441
+ const { slicedUiHistory, originalPrompt, compressionAbort } = applyConversationRewind(promptId);
474181
474442
  uiActions.closeRewindDialog();
474443
+ if (compressionAbort) {
474444
+ addItem(
474445
+ {
474446
+ type: "error",
474447
+ text: "Cannot rewind to a turn that was compressed. Try a more recent turn."
474448
+ },
474449
+ Date.now()
474450
+ );
474451
+ return;
474452
+ }
474182
474453
  if (originalPrompt) {
474183
474454
  uiState.buffer.setText(originalPrompt);
474184
474455
  }
@@ -474194,8 +474465,18 @@ var DialogManager = /* @__PURE__ */ __name(({
474194
474465
  );
474195
474466
  }, "handleRestoreFilesAndConversation");
474196
474467
  const handleRestoreConversationOnly = /* @__PURE__ */ __name((promptId) => {
474197
- const { slicedUiHistory, originalPrompt } = applyConversationRewind(promptId);
474468
+ const { slicedUiHistory, originalPrompt, compressionAbort } = applyConversationRewind(promptId);
474198
474469
  uiActions.closeRewindDialog();
474470
+ if (compressionAbort) {
474471
+ addItem(
474472
+ {
474473
+ type: "error",
474474
+ text: "Cannot rewind to a turn that was compressed. Try a more recent turn."
474475
+ },
474476
+ Date.now()
474477
+ );
474478
+ return;
474479
+ }
474199
474480
  if (originalPrompt) {
474200
474481
  uiState.buffer.setText(originalPrompt);
474201
474482
  }
@@ -488304,8 +488585,7 @@ var AppContainer = /* @__PURE__ */ __name((props) => {
488304
488585
  () => setPermissionsDialogOpen(false),
488305
488586
  []
488306
488587
  );
488307
- const getCurrentModel = (0, import_react176.useCallback)(() => config2.getModel(), [config2]);
488308
- const [currentModel, setCurrentModel] = (0, import_react176.useState)(getCurrentModel());
488588
+ const [currentModel, setCurrentModel] = (0, import_react176.useState)(() => config2.getModel());
488309
488589
  const [isConfigInitialized, setConfigInitialized] = (0, import_react176.useState)(false);
488310
488590
  const [userMessages, setUserMessages] = (0, import_react176.useState)([]);
488311
488591
  const { columns: terminalWidth, rows: terminalHeight } = useTerminalSize();
@@ -488334,14 +488614,11 @@ var AppContainer = /* @__PURE__ */ __name((props) => {
488334
488614
  );
488335
488615
  }, [lastFinished, addHistoryItem]);
488336
488616
  (0, import_react176.useEffect)(() => {
488337
- const interval = setInterval(() => {
488338
- const model = getCurrentModel();
488339
- if (model !== currentModel) {
488340
- setCurrentModel(model);
488341
- }
488342
- }, 1e3);
488343
- return () => clearInterval(interval);
488344
- }, [config2, currentModel, getCurrentModel]);
488617
+ const unsubscribe = config2.onModelChange((model) => {
488618
+ setCurrentModel(model);
488619
+ });
488620
+ return unsubscribe;
488621
+ }, [config2]);
488345
488622
  const { inputWidth, suggestionsWidth } = (0, import_react176.useMemo)(() => {
488346
488623
  const { inputWidth: inputWidth2, suggestionsWidth: suggestionsWidth2 } = calculatePromptWidths(terminalWidth);
488347
488624
  return { inputWidth: inputWidth2, suggestionsWidth: suggestionsWidth2 };
@@ -488392,6 +488669,18 @@ var AppContainer = /* @__PURE__ */ __name((props) => {
488392
488669
  stdout3.write("\x1B[?2026l");
488393
488670
  setHistoryRemountKey((prev) => prev + 1);
488394
488671
  }, [setHistoryRemountKey, stdout3]);
488672
+ (0, import_react176.useEffect)(() => {
488673
+ const unsubscribe = config2.onModelChange((model) => {
488674
+ setCurrentModel((prev) => {
488675
+ if (prev === model) {
488676
+ return prev;
488677
+ }
488678
+ refreshStatic();
488679
+ return model;
488680
+ });
488681
+ });
488682
+ return unsubscribe;
488683
+ }, [config2, refreshStatic]);
488395
488684
  const {
488396
488685
  isThemeDialogOpen,
488397
488686
  openThemeDialog,
@@ -488943,24 +489232,11 @@ var AppContainer = /* @__PURE__ */ __name((props) => {
488943
489232
  needsRestart: ideNeedsRestart,
488944
489233
  restartReason: ideTrustRestartReason
488945
489234
  } = useIdeTrustListener();
488946
- const isInitialMount = (0, import_react176.useRef)(true);
488947
489235
  (0, import_react176.useEffect)(() => {
488948
489236
  if (ideNeedsRestart) {
488949
489237
  setShowIdeRestartPrompt(true);
488950
489238
  }
488951
489239
  }, [ideNeedsRestart]);
488952
- (0, import_react176.useEffect)(() => {
488953
- if (isInitialMount.current) {
488954
- isInitialMount.current = false;
488955
- return;
488956
- }
488957
- const handler = setTimeout(() => {
488958
- refreshStatic();
488959
- }, 300);
488960
- return () => {
488961
- clearTimeout(handler);
488962
- };
488963
- }, [terminalWidth, refreshStatic]);
488964
489240
  (0, import_react176.useEffect)(() => {
488965
489241
  const unsubscribe = ideContextStore.subscribe(setIdeContextState);
488966
489242
  setIdeContextState(ideContextStore.get());
@@ -493626,7 +493902,7 @@ var QwenAgent = class {
493626
493902
  async initialize(args2) {
493627
493903
  this.clientCapabilities = args2.clientCapabilities;
493628
493904
  const authMethods = buildAuthMethods();
493629
- const version2 = "0.33.0";
493905
+ const version2 = "0.34.1";
493630
493906
  return {
493631
493907
  protocolVersion: PROTOCOL_VERSION,
493632
493908
  agentInfo: {
@@ -494558,6 +494834,9 @@ var isExpectedPtyRaceError = /* @__PURE__ */ __name((error40) => {
494558
494834
  if (code2 === "EIO" && message.includes("read") || message.includes("read EIO")) {
494559
494835
  return true;
494560
494836
  }
494837
+ if (code2 === "EAGAIN" && message.includes("read") || message.includes("read EAGAIN")) {
494838
+ return true;
494839
+ }
494561
494840
  if (message.includes("ioctl(2) failed, EBADF") || message.includes("Cannot resize a pty that has already exited")) {
494562
494841
  return true;
494563
494842
  }
@@ -494915,6 +495194,21 @@ main().catch((error40) => {
494915
495194
  * /notes — trigger a fresh extraction then display the notes
494916
495195
  * /notes --view — display the current notes without re-extracting
494917
495196
  */
495197
+ /**
495198
+ * @license
495199
+ * Copyright 2026 protoLabs
495200
+ * SPDX-License-Identifier: Apache-2.0
495201
+ *
495202
+ * Adapted from QwenLM/qwen-code PR #3441 to fix our existing rewind feature's
495203
+ * LLM history truncation. The original implementation walked apiHistory by
495204
+ * `role === 'user'` count, which conflated:
495205
+ * 1. Real user prompts (what we want to count)
495206
+ * 2. Tool result entries (`role: 'user'` with `functionResponse` parts)
495207
+ * 3. The startup context pair (env preamble + "Got it" model ack)
495208
+ * 4. UI-only slash command items that never reached the API
495209
+ *
495210
+ * `computeApiTruncationIndex` correctly handles all four cases.
495211
+ */
494918
495212
  /**
494919
495213
  * @license
494920
495214
  * Copyright 2025 Qwen Team
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protolabsai/proto",
3
- "version": "0.33.0",
3
+ "version": "0.34.1",
4
4
  "description": "proto - AI-powered coding agent",
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.33.0"
24
+ "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.34.1"
25
25
  },
26
26
  "dependencies": {},
27
27
  "optionalDependencies": {