@cydm/pie 1.0.28 → 1.0.30

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.
package/dist/cli.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  cleanupBashOutputArtifacts,
6
6
  createCliHostCapabilities,
7
7
  createCliWebResearchHealthStore,
8
+ formatSize,
8
9
  getAgentDir,
9
10
  getBuiltinDir,
10
11
  getConfigDir,
@@ -16,8 +17,9 @@ import {
16
17
  getSessionsDir,
17
18
  getSettingsPath,
18
19
  getThemesDir,
19
- migrateConfigFromAgentDir
20
- } from "./chunks/chunk-BDDSZSHX.js";
20
+ migrateConfigFromAgentDir,
21
+ truncateHeadTail
22
+ } from "./chunks/chunk-PLJQYVFC.js";
21
23
  import {
22
24
  AGENTS_CONTEXT_FILE_NAME,
23
25
  AgentSessionController,
@@ -67,7 +69,7 @@ import {
67
69
  setExtensionEnabledInSettings,
68
70
  shouldPreserveExecutionStateForUserText,
69
71
  supersedeExecutionState
70
- } from "./chunks/chunk-L63BJMTT.js";
72
+ } from "./chunks/chunk-BOFCKEV5.js";
71
73
  import "./chunks/chunk-4B42ZU4B.js";
72
74
  import {
73
75
  Deref,
@@ -45727,45 +45729,6 @@ var ModelRegistry = class {
45727
45729
  // src/core/settings-manager.ts
45728
45730
  import * as fs3 from "fs";
45729
45731
  import * as path3 from "path";
45730
-
45731
- // src/tool-set.ts
45732
- var DEFAULT_TOOL_SET = "lean";
45733
- var LEAN_CODING_TOOL_NAMES = [
45734
- "read_file",
45735
- "edit_file",
45736
- "write_file",
45737
- "bash"
45738
- ];
45739
- var CLI_DEFAULT_TOOL_NAMES = /* @__PURE__ */ new Set([
45740
- "read_file",
45741
- "write_file",
45742
- "edit_file",
45743
- "list_dir",
45744
- "grep_text",
45745
- "find_files",
45746
- "bash",
45747
- "web_research",
45748
- "web_search",
45749
- "web_fetch",
45750
- "code_intel"
45751
- ]);
45752
- var LEAN_CODING_TOOL_NAME_SET = new Set(LEAN_CODING_TOOL_NAMES);
45753
- function normalizeDefaultToolSet(value) {
45754
- return value === "full" ? "full" : DEFAULT_TOOL_SET;
45755
- }
45756
- function selectDefaultTools(tools, defaultSet) {
45757
- if (defaultSet === "full") {
45758
- return [...tools];
45759
- }
45760
- return tools.filter(
45761
- (tool) => !CLI_DEFAULT_TOOL_NAMES.has(tool.name) || LEAN_CODING_TOOL_NAME_SET.has(tool.name)
45762
- );
45763
- }
45764
- function formatDefaultToolSet(defaultSet) {
45765
- return defaultSet === "full" ? "Full" : "Lean";
45766
- }
45767
-
45768
- // src/core/settings-manager.ts
45769
45732
  var SettingsManager = class {
45770
45733
  settingsPath;
45771
45734
  legacyConfigPath;
@@ -45854,16 +45817,6 @@ var SettingsManager = class {
45854
45817
  }
45855
45818
  return "auto";
45856
45819
  }
45857
- getDefaultToolSet() {
45858
- return normalizeDefaultToolSet(this.settings.tools?.defaultSet);
45859
- }
45860
- setDefaultToolSet(defaultSet) {
45861
- this.settings.tools = {
45862
- ...this.settings.tools,
45863
- defaultSet
45864
- };
45865
- this.writeSettings();
45866
- }
45867
45820
  // ==========================================================================
45868
45821
  // Extension enablement (user ~/.pie/settings.json + project ./.pie/settings.json)
45869
45822
  // ==========================================================================
@@ -46312,7 +46265,7 @@ Default mode:
46312
46265
  - File tools read and write inside the current workspace.
46313
46266
  - ~/.pie is allowlisted for Pie configuration and session support.
46314
46267
  - Shell commands run from the workspace and return structured output, timeout, and truncation details.
46315
- - web_search is read-only and uses provider-native search; it does not grant bash/curl web scraping permission.
46268
+ - web_research is read-only, uses provider-native web/search/fetch capabilities, and does not grant bash/curl web scraping permission.
46316
46269
  - Protected paths from extensions can block reads/writes even when tools are present.
46317
46270
 
46318
46271
  Plan mode:
@@ -47018,6 +46971,7 @@ var CommandTree = class {
47018
46971
  if (isLast) {
47019
46972
  node.description = info.description;
47020
46973
  node.handler = info.handler;
46974
+ node.hidden = info.hidden === true;
47021
46975
  if (!node.children || node.children.length === 0) {
47022
46976
  node.isCategory = false;
47023
46977
  }
@@ -47042,7 +46996,7 @@ var CommandTree = class {
47042
46996
  */
47043
46997
  getChildren(path30) {
47044
46998
  const node = this.find(path30);
47045
- return node?.children || [];
46999
+ return (node?.children || []).filter((child) => !child.hidden);
47046
47000
  }
47047
47001
  /**
47048
47002
  * Check if a path exists (as category or command)
@@ -47063,6 +47017,7 @@ var CommandTree = class {
47063
47017
  search(prefix) {
47064
47018
  const results = [];
47065
47019
  const traverse = (node, currentPath) => {
47020
+ if (node.hidden) return;
47066
47021
  const newPath = node.name ? [...currentPath, node.name] : currentPath;
47067
47022
  const pathStr = newPath.join("/");
47068
47023
  if (node.name && pathStr.startsWith(prefix)) {
@@ -47087,6 +47042,7 @@ var CommandTree = class {
47087
47042
  searchByName(namePrefix) {
47088
47043
  const results = [];
47089
47044
  const traverse = (node, currentPath) => {
47045
+ if (node.hidden) return;
47090
47046
  const newPath = node.name ? [...currentPath, node.name] : currentPath;
47091
47047
  const pathStr = newPath.join("/");
47092
47048
  if (node.name && node.name.toLowerCase().startsWith(namePrefix.toLowerCase())) {
@@ -47110,6 +47066,7 @@ var CommandTree = class {
47110
47066
  getAllPaths() {
47111
47067
  const paths = [];
47112
47068
  const traverse = (node, currentPath) => {
47069
+ if (node.hidden) return;
47113
47070
  const newPath = node.name ? [...currentPath, node.name] : currentPath;
47114
47071
  if (node.name) {
47115
47072
  paths.push(newPath.join("/"));
@@ -47180,12 +47137,14 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
47180
47137
  name: finalName,
47181
47138
  description: command.description,
47182
47139
  handler: command.handler,
47183
- path: cmdPath
47140
+ path: cmdPath,
47141
+ hidden: command.hidden === true
47184
47142
  };
47185
47143
  extension.commands.set(finalName, registeredCmd);
47186
47144
  commandTree.register(cmdPath, {
47187
47145
  description: command.description,
47188
- handler: command.handler
47146
+ handler: command.handler,
47147
+ hidden: command.hidden === true
47189
47148
  });
47190
47149
  },
47191
47150
  registerShortcut(key, shortcut) {
@@ -50187,6 +50146,18 @@ var SelectList = class {
50187
50146
  this.filteredItems = this.items.filter((item) => item.value.toLowerCase().startsWith(filter.toLowerCase()));
50188
50147
  this.selectedIndex = 0;
50189
50148
  }
50149
+ getVisibleRange() {
50150
+ const startIndex = Math.max(
50151
+ 0,
50152
+ Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible)
50153
+ );
50154
+ const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
50155
+ return { startIndex, endIndex };
50156
+ }
50157
+ getVisibleItems() {
50158
+ const { startIndex, endIndex } = this.getVisibleRange();
50159
+ return this.filteredItems.slice(startIndex, endIndex);
50160
+ }
50190
50161
  setSelectedIndex(index) {
50191
50162
  this.selectedIndex = Math.max(0, Math.min(index, this.filteredItems.length - 1));
50192
50163
  }
@@ -50198,11 +50169,7 @@ var SelectList = class {
50198
50169
  lines.push(this.theme.noMatch(" No matching commands"));
50199
50170
  return lines;
50200
50171
  }
50201
- const startIndex = Math.max(
50202
- 0,
50203
- Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible)
50204
- );
50205
- const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
50172
+ const { startIndex, endIndex } = this.getVisibleRange();
50206
50173
  for (let i = startIndex; i < endIndex; i++) {
50207
50174
  const item = this.filteredItems[i];
50208
50175
  if (!item) continue;
@@ -50215,19 +50182,20 @@ var SelectList = class {
50215
50182
  if (descriptionSingleLine && width > 40) {
50216
50183
  const maxValueWidth = Math.min(30, width - prefixWidth - 4);
50217
50184
  const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
50218
- const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
50219
- const descriptionStart = prefixWidth + truncatedValue.length + spacing.length;
50185
+ const valueWidth = visibleWidth(truncatedValue);
50186
+ const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
50187
+ const descriptionStart = prefixWidth + valueWidth + spacing.length;
50220
50188
  const remainingWidth = width - descriptionStart - 2;
50221
50189
  if (remainingWidth > 10) {
50222
50190
  const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
50223
- line = this.theme.selectedText(`\u2192 ${truncatedValue}${spacing}${truncatedDesc}`);
50191
+ line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncatedValue}${spacing}${truncatedDesc}`), width, "");
50224
50192
  } else {
50225
50193
  const maxWidth = width - prefixWidth - 2;
50226
- line = this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`);
50194
+ line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
50227
50195
  }
50228
50196
  } else {
50229
50197
  const maxWidth = width - prefixWidth - 2;
50230
- line = this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`);
50198
+ line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
50231
50199
  }
50232
50200
  } else {
50233
50201
  const displayValue = item.label || item.value;
@@ -50235,23 +50203,24 @@ var SelectList = class {
50235
50203
  if (descriptionSingleLine && width > 40) {
50236
50204
  const maxValueWidth = Math.min(30, width - prefix.length - 4);
50237
50205
  const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
50238
- const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
50239
- const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
50206
+ const valueWidth = visibleWidth(truncatedValue);
50207
+ const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
50208
+ const descriptionStart = prefix.length + valueWidth + spacing.length;
50240
50209
  const remainingWidth = width - descriptionStart - 2;
50241
50210
  if (remainingWidth > 10) {
50242
50211
  const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
50243
50212
  const descText = this.theme.description(spacing + truncatedDesc);
50244
- line = prefix + truncatedValue + descText;
50213
+ line = truncateToWidth(prefix + truncatedValue + descText, width, "");
50245
50214
  } else {
50246
50215
  const maxWidth = width - prefix.length - 2;
50247
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
50216
+ line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
50248
50217
  }
50249
50218
  } else {
50250
50219
  const maxWidth = width - prefix.length - 2;
50251
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
50220
+ line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
50252
50221
  }
50253
50222
  }
50254
- lines.push(line);
50223
+ lines.push(truncateToWidth(line, width, ""));
50255
50224
  }
50256
50225
  if (startIndex > 0 || endIndex < this.filteredItems.length) {
50257
50226
  const scrollText = ` (${this.selectedIndex + 1}/${this.filteredItems.length})`;
@@ -56683,7 +56652,7 @@ var FileManagerError = class extends Error {
56683
56652
  code;
56684
56653
  details;
56685
56654
  locale;
56686
- constructor(code, details, locale = "zh") {
56655
+ constructor(code, details, locale = "en") {
56687
56656
  const messages = FileErrorMessages[code];
56688
56657
  super(messages[locale]);
56689
56658
  this.name = "FileManagerError";
@@ -60273,34 +60242,6 @@ var SettingsSelectorComponent = class extends Container {
60273
60242
  }
60274
60243
  )
60275
60244
  },
60276
- {
60277
- id: "tools",
60278
- label: "Tools",
60279
- description: "Default model-visible tool set",
60280
- currentValue: config.defaultToolSet,
60281
- submenu: (currentValue, done) => new SelectSubmenu(
60282
- "Default Tools",
60283
- "Choose which built-in tools are visible in new coding sessions",
60284
- [
60285
- {
60286
- value: "lean",
60287
- label: "Lean",
60288
- description: "read_file, edit_file, write_file, bash"
60289
- },
60290
- {
60291
- value: "full",
60292
- label: "Full",
60293
- description: "All built-in tools, including search, web, and code intel"
60294
- }
60295
- ],
60296
- currentValue,
60297
- (value) => {
60298
- callbacks.onDefaultToolSetChange(value);
60299
- done(value);
60300
- },
60301
- () => done()
60302
- )
60303
- },
60304
60245
  {
60305
60246
  id: "extensions",
60306
60247
  label: "Extensions",
@@ -61276,7 +61217,8 @@ var SessionSelectorComponent = class extends Container {
61276
61217
  items;
61277
61218
  refreshAttempted = /* @__PURE__ */ new Set();
61278
61219
  refreshInFlight = false;
61279
- pendingRefreshId;
61220
+ refreshQueue = [];
61221
+ refreshQueued = /* @__PURE__ */ new Set();
61280
61222
  refreshTimer;
61281
61223
  destroyed = false;
61282
61224
  constructor(sessions, callbacks, options = {}) {
@@ -61310,16 +61252,15 @@ var SessionSelectorComponent = class extends Container {
61310
61252
  this.clearRefreshTimer();
61311
61253
  this.callbacks.onCancel();
61312
61254
  };
61313
- this.selectList.onSelectionChange = (item) => {
61314
- this.scheduleRefresh(item.value);
61255
+ this.selectList.onSelectionChange = () => {
61256
+ this.scheduleVisibleRefreshes();
61315
61257
  };
61316
61258
  this.addChild(this.selectList);
61317
61259
  this.addChild(new Spacer(1));
61318
61260
  this.addChild(
61319
61261
  new Text(theme.fg("dim", " \u2191\u2193 to navigate \xB7 \u2190\u2192 to page \xB7 Enter to select \xB7 Esc to cancel"), 0, 0)
61320
61262
  );
61321
- const selected = this.selectList.getSelectedItem();
61322
- if (selected) this.scheduleRefresh(selected.value);
61263
+ this.scheduleVisibleRefreshes();
61323
61264
  }
61324
61265
  handleInput(data) {
61325
61266
  this.selectList.handleInput(data);
@@ -61341,9 +61282,14 @@ var SessionSelectorComponent = class extends Container {
61341
61282
  this.refreshTimer = void 0;
61342
61283
  }
61343
61284
  }
61344
- scheduleRefresh(sessionId) {
61345
- if (!this.options.refreshMetadata || this.destroyed || this.refreshAttempted.has(sessionId)) return;
61346
- this.pendingRefreshId = sessionId;
61285
+ scheduleVisibleRefreshes() {
61286
+ if (!this.options.refreshMetadata || this.destroyed) return;
61287
+ for (const item of this.selectList.getVisibleItems()) {
61288
+ if (this.refreshAttempted.has(item.value) || this.refreshQueued.has(item.value)) continue;
61289
+ this.refreshQueue.push(item.value);
61290
+ this.refreshQueued.add(item.value);
61291
+ }
61292
+ if (this.refreshQueue.length === 0) return;
61347
61293
  this.clearRefreshTimer();
61348
61294
  this.refreshTimer = setTimeout(() => {
61349
61295
  this.refreshTimer = void 0;
@@ -61353,9 +61299,9 @@ var SessionSelectorComponent = class extends Container {
61353
61299
  async runPendingRefresh() {
61354
61300
  if (this.destroyed || !this.options.refreshMetadata) return;
61355
61301
  if (this.refreshInFlight) return;
61356
- const sessionId = this.pendingRefreshId;
61357
- this.pendingRefreshId = void 0;
61302
+ const sessionId = this.refreshQueue.shift();
61358
61303
  if (!sessionId || this.refreshAttempted.has(sessionId)) return;
61304
+ this.refreshQueued.delete(sessionId);
61359
61305
  this.refreshAttempted.add(sessionId);
61360
61306
  this.refreshInFlight = true;
61361
61307
  try {
@@ -61366,7 +61312,7 @@ var SessionSelectorComponent = class extends Container {
61366
61312
  } catch {
61367
61313
  } finally {
61368
61314
  this.refreshInFlight = false;
61369
- if (this.pendingRefreshId && !this.destroyed) {
61315
+ if (this.refreshQueue.length > 0 && !this.destroyed) {
61370
61316
  void this.runPendingRefresh();
61371
61317
  }
61372
61318
  }
@@ -62460,7 +62406,7 @@ function renderExecutionWidgetLines(steps, activeTheme = theme) {
62460
62406
  }
62461
62407
 
62462
62408
  // src/components/tool-execution.ts
62463
- function formatSize(bytes) {
62409
+ function formatSize2(bytes) {
62464
62410
  if (bytes < 1024) return `${bytes}B`;
62465
62411
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
62466
62412
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
@@ -62590,7 +62536,7 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
62590
62536
  if (truncation.firstLineExceedsLimit) {
62591
62537
  text += "\n" + theme.fg(
62592
62538
  "warning",
62593
- `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`
62539
+ `[First line exceeds ${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`
62594
62540
  );
62595
62541
  } else if (truncation.truncatedBy === "lines") {
62596
62542
  text += "\n" + theme.fg(
@@ -62600,7 +62546,7 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
62600
62546
  } else {
62601
62547
  text += "\n" + theme.fg(
62602
62548
  "warning",
62603
- `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`
62549
+ `[Truncated: ${truncation.outputLines} lines shown (${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`
62604
62550
  );
62605
62551
  }
62606
62552
  }
@@ -62748,7 +62694,7 @@ ${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
62748
62694
  warnings.push(`${entryLimit} entries limit`);
62749
62695
  }
62750
62696
  if (truncation?.truncated) {
62751
- warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62697
+ warnings.push(`${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62752
62698
  }
62753
62699
  text += `
62754
62700
  ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
@@ -62786,7 +62732,7 @@ ${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
62786
62732
  warnings.push(`${resultLimit} results limit`);
62787
62733
  }
62788
62734
  if (truncation?.truncated) {
62789
- warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62735
+ warnings.push(`${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62790
62736
  }
62791
62737
  text += `
62792
62738
  ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
@@ -62829,7 +62775,7 @@ ${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
62829
62775
  warnings.push(`${matchLimit} matches limit`);
62830
62776
  }
62831
62777
  if (truncation?.truncated) {
62832
- warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62778
+ warnings.push(`${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
62833
62779
  }
62834
62780
  if (linesTruncated) {
62835
62781
  warnings.push("some lines truncated");
@@ -62869,7 +62815,7 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
62869
62815
  warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);
62870
62816
  } else {
62871
62817
  warnings.push(
62872
- `Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`
62818
+ `Truncated: ${truncation.outputLines} lines shown (${formatSize2(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`
62873
62819
  );
62874
62820
  }
62875
62821
  }
@@ -63688,8 +63634,7 @@ function showSettingsSelector(host) {
63688
63634
  availableThemes: getAvailableThemes(),
63689
63635
  currentModel: currentModelId,
63690
63636
  availableModels,
63691
- yoloMode: host.yoloMode,
63692
- defaultToolSet: host.options.settingsManager.getDefaultToolSet()
63637
+ yoloMode: host.yoloMode
63693
63638
  },
63694
63639
  {
63695
63640
  onThinkingLevelChange: (level) => {
@@ -63718,10 +63663,6 @@ function showSettingsSelector(host) {
63718
63663
  host.showError(`Failed to switch model: ${err}`);
63719
63664
  }
63720
63665
  },
63721
- onDefaultToolSetChange: (defaultToolSet) => {
63722
- host.options.settingsManager.setDefaultToolSet(defaultToolSet);
63723
- host.showStatus(`Default tools: ${formatDefaultToolSet(defaultToolSet)} (restart Pie to apply)`);
63724
- },
63725
63666
  onYoloToggle: async () => {
63726
63667
  await host.handleYoloCommand();
63727
63668
  done();
@@ -64223,10 +64164,6 @@ function registerBuiltinCommands(host) {
64223
64164
  description: "Change theme",
64224
64165
  handler: () => host.showSettingsSelector()
64225
64166
  });
64226
- commandTree.register(["settings", "tools"], {
64227
- description: "Choose the default model-visible tool set",
64228
- handler: () => host.showSettingsSelector()
64229
- });
64230
64167
  commandTree.register(["settings", "thinking"], {
64231
64168
  description: "Set thinking level (off/minimal/low/medium/high/xhigh)",
64232
64169
  handler: (_2, args) => host.handleThinkingCommand(args)
@@ -64811,7 +64748,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64811
64748
  const expanded = host.expandSkillCommand(skillText);
64812
64749
  if (expanded !== skillText) {
64813
64750
  if (host.submitLock) {
64814
- host.queueMessage(expanded, "steer");
64751
+ host.queueMessage(expanded, "followUp", { deliverWhileStreaming: false });
64815
64752
  return;
64816
64753
  }
64817
64754
  host.setSubmitLock(true);
@@ -64842,7 +64779,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64842
64779
  if (text.startsWith("/tools/subagent")) {
64843
64780
  const args = text.slice("/tools/subagent".length).trim();
64844
64781
  if (host.submitLock) {
64845
- host.queueMessage(text, "steer");
64782
+ host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64846
64783
  return;
64847
64784
  }
64848
64785
  host.editor.setText("");
@@ -64861,7 +64798,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64861
64798
  host.showStatus("Wait for the current response to finish before compacting");
64862
64799
  return;
64863
64800
  }
64864
- host.queueMessage(text, "steer");
64801
+ host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64865
64802
  return;
64866
64803
  }
64867
64804
  host.editor.setText("");
@@ -64891,6 +64828,11 @@ function setupInteractiveEditorSubmitHandler(host) {
64891
64828
  }
64892
64829
  return;
64893
64830
  }
64831
+ if (exactMatch?.isCategory && !exactMatch.handler) {
64832
+ host.showHierarchicalMenu(firstPartSegments);
64833
+ host.editor.setText("");
64834
+ return;
64835
+ }
64894
64836
  const pathStr = text.slice(1);
64895
64837
  const segments = pathStr.split("/").filter(Boolean);
64896
64838
  let node = null;
@@ -64912,7 +64854,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64912
64854
  host.showStatus("Wait for the current response to finish before compacting");
64913
64855
  return;
64914
64856
  }
64915
- host.queueMessage(text, "steer");
64857
+ host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64916
64858
  return;
64917
64859
  }
64918
64860
  host.editor.setText("");
@@ -64953,7 +64895,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64953
64895
  for (const [name, command] of ext.commands) {
64954
64896
  if (command.path?.join("/") === fullPath) {
64955
64897
  if (host.submitLock) {
64956
- host.queueMessage(text, "steer");
64898
+ host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64957
64899
  return;
64958
64900
  }
64959
64901
  host.editor.setText("");
@@ -64999,15 +64941,16 @@ function setupInteractiveEditorSubmitHandler(host) {
64999
64941
  }
65000
64942
  }
65001
64943
  if (host.mentionHandler?.hasPendingMentionWork()) {
65002
- host.queueMessage(text, "steer", {
64944
+ host.queueMessage(text, "followUp", {
65003
64945
  clearEditor: false,
65004
- statusMessage: "\u6587\u4EF6\u5904\u7406\u4E2D\uFF0C\u6D88\u606F\u5DF2\u6392\u961F\uFF0C\u6DFB\u52A0\u5B8C\u6210\u540E\u81EA\u52A8\u53D1\u9001"
64946
+ statusMessage: "Files are still processing. Message queued and will send when attachments are ready.",
64947
+ deliverWhileStreaming: false
65005
64948
  });
65006
64949
  host.agentSessionController?.requestQueueDispatch();
65007
64950
  return;
65008
64951
  }
65009
64952
  if (host.submitLock) {
65010
- host.queueMessage(text, "steer");
64953
+ host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
65011
64954
  return;
65012
64955
  }
65013
64956
  host.setSubmitLock(true);
@@ -65037,9 +64980,10 @@ function setupInteractiveEditorSubmitHandler(host) {
65037
64980
  host.setSubmitLock(false);
65038
64981
  host.isProcessing = false;
65039
64982
  host.footer.setState({ status: "ready" });
65040
- host.queueMessage(text, "steer", {
64983
+ host.queueMessage(text, "followUp", {
65041
64984
  clearEditor: false,
65042
- statusMessage: `\u6587\u4EF6\u5904\u7406\u4E2D: ${processingFiles.join(", ")}\uFF0C\u5DF2\u6392\u961F\uFF0C\u5904\u7406\u5B8C\u6210\u540E\u81EA\u52A8\u53D1\u9001`
64985
+ statusMessage: `Files still processing: ${processingFiles.join(", ")}. Message queued and will send when attachments are ready.`,
64986
+ deliverWhileStreaming: false
65043
64987
  });
65044
64988
  host.agentSessionController?.requestQueueDispatch();
65045
64989
  return;
@@ -65279,7 +65223,7 @@ var FilePickerComponent = class extends Container {
65279
65223
  if (this.query) {
65280
65224
  this.addChild(new Text(theme.fg("dim", `@ ${this.query}`), 1, 0));
65281
65225
  } else {
65282
- this.addChild(new Text(theme.fg("dim", "@ \u9009\u62E9\u6587\u4EF6..."), 1, 0));
65226
+ this.addChild(new Text(theme.fg("dim", "@ Select a file..."), 1, 0));
65283
65227
  }
65284
65228
  this.addChild(new Text(theme.fg("border", "\u2500".repeat(40)), 1, 0));
65285
65229
  const maxOptions = 8;
@@ -65304,16 +65248,16 @@ var FilePickerComponent = class extends Container {
65304
65248
  new Text(
65305
65249
  theme.fg(
65306
65250
  "dim",
65307
- ` ${this.selectedIndex + 1}/${this.options.length} \xB7 \u663E\u793A ${this.scrollOffset + 1}-${visibleEnd}`
65251
+ ` ${this.selectedIndex + 1}/${this.options.length} \xB7 showing ${this.scrollOffset + 1}-${visibleEnd}`
65308
65252
  ),
65309
65253
  1,
65310
65254
  0
65311
65255
  )
65312
65256
  );
65313
65257
  }
65314
- this.addChild(new Text(theme.fg("dim", "\u2191\u2193 \u9009\u62E9 \xB7 \u2190 \u8FD4\u56DE / \u2192 \u8FDB\u5165 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88"), 1, 0));
65258
+ this.addChild(new Text(theme.fg("dim", "\u2191\u2193 Select \xB7 \u2190 Back / \u2192 Open \xB7 Enter Confirm \xB7 Esc Cancel"), 1, 0));
65315
65259
  } else {
65316
- this.addChild(new Text(theme.fg("dim", " \u65E0\u5339\u914D\u6587\u4EF6"), 1, 0));
65260
+ this.addChild(new Text(theme.fg("dim", " No matching files"), 1, 0));
65317
65261
  }
65318
65262
  }
65319
65263
  };
@@ -65346,11 +65290,11 @@ var FileCommands = class {
65346
65290
  purpose: parsed.purpose,
65347
65291
  onProgress: (progress, stage) => {
65348
65292
  const stageNames = {
65349
- analyzing: "\u5206\u6790\u4E2D",
65350
- preprocessing: "\u9884\u5904\u7406",
65351
- uploading: "\u4E0A\u4F20\u4E2D",
65352
- processing: "\u5904\u7406\u4E2D",
65353
- complete: "\u5B8C\u6210"
65293
+ analyzing: "Analyzing",
65294
+ preprocessing: "Preprocessing",
65295
+ uploading: "Uploading",
65296
+ processing: "Processing",
65297
+ complete: "Complete"
65354
65298
  };
65355
65299
  this.context.showStatus(`${stageNames[stage] || stage}... ${progress}%`);
65356
65300
  }
@@ -65417,11 +65361,11 @@ var FileCommands = class {
65417
65361
  optimize: parsed.options,
65418
65362
  onProgress: (progress, stage) => {
65419
65363
  const stageNames = {
65420
- analyzing: "\u5206\u6790\u89C6\u9891",
65421
- preprocessing: "\u9884\u5904\u7406",
65422
- uploading: "\u4E0A\u4F20\u4E2D",
65423
- processing: "\u5E73\u53F0\u5904\u7406\u4E2D",
65424
- complete: "\u5B8C\u6210"
65364
+ analyzing: "Analyzing video",
65365
+ preprocessing: "Preprocessing",
65366
+ uploading: "Uploading",
65367
+ processing: "Processing",
65368
+ complete: "Complete"
65425
65369
  };
65426
65370
  this.context.showStatus(`${stageNames[stage] || stage}... ${progress}%`);
65427
65371
  }
@@ -65976,7 +65920,7 @@ var MentionHandler = class {
65976
65920
  this.fileManager.ensureSessionTracking(option.fileId);
65977
65921
  const mention = this.formatMention(option.name, option.fileId);
65978
65922
  this.onInsertMention(mention, queryToken);
65979
- this.onStatus?.(`\u5DF2\u6DFB\u52A0\u6587\u4EF6 ${option.name}\uFF08\u5DF2\u4E0A\u4F20\u5230 ${this.fileManager.getPlatformDisplayName()}\uFF09`);
65923
+ this.onStatus?.(`Added ${option.name} (already uploaded to ${this.fileManager.getPlatformDisplayName()})`);
65980
65924
  } else if (option.type === "upload" && option.path) {
65981
65925
  this.pendingUploadCount += 1;
65982
65926
  const pendingMention = this.formatPendingMention(option.name);
@@ -65986,15 +65930,15 @@ var MentionHandler = class {
65986
65930
  if (option.cacheStatus === "uploaded") {
65987
65931
  this.pushPendingStatus(
65988
65932
  pendingStatusKey,
65989
- `\u51C6\u5907\u6DFB\u52A0 ${option.name}\uFF08\u5C06\u590D\u7528 ${this.fileManager.getPlatformDisplayName()} \u5DF2\u4E0A\u4F20\u6587\u4EF6\uFF09...`
65933
+ `Preparing ${option.name} (reusing upload from ${this.fileManager.getPlatformDisplayName()})...`
65990
65934
  );
65991
65935
  } else if (option.cacheStatus === "cached") {
65992
65936
  this.pushPendingStatus(
65993
65937
  pendingStatusKey,
65994
- `\u51C6\u5907\u6DFB\u52A0 ${option.name}\uFF08\u5C06\u590D\u7528\u672C\u5730\u7F13\u5B58\uFF09...`
65938
+ `Preparing ${option.name} (reusing local cache)...`
65995
65939
  );
65996
65940
  } else {
65997
- this.pushPendingStatus(pendingStatusKey, `\u51C6\u5907\u6DFB\u52A0 ${option.name}...`);
65941
+ this.pushPendingStatus(pendingStatusKey, `Preparing ${option.name}...`);
65998
65942
  }
65999
65943
  const mimeType = FileCache.getMimeType(option.path);
66000
65944
  const shouldStageLocally = !mimeType.startsWith("image/") && !mimeType.startsWith("video/");
@@ -66018,33 +65962,33 @@ var MentionHandler = class {
66018
65962
  const mention = this.formatMention(result.name, result.fileId);
66019
65963
  this.onInsertMention(mention, pendingMention);
66020
65964
  this.clearPendingStatus(pendingStatusKey);
66021
- this.onStatus?.(shouldStageLocally ? `\u5DF2\u6DFB\u52A0\u672C\u5730\u6587\u4EF6 ${result.name}` : `\u5DF2\u6DFB\u52A0\u6587\u4EF6 ${result.name}`);
65965
+ this.onStatus?.(shouldStageLocally ? `Added local file ${result.name}` : `Added ${result.name}`);
66022
65966
  } else {
66023
65967
  this.onInsertMention("", pendingMention);
66024
65968
  this.clearPendingStatus(pendingStatusKey);
66025
- this.onError?.("\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
65969
+ this.onError?.("File upload failed. Please try again.");
66026
65970
  }
66027
65971
  } catch (err) {
66028
65972
  this.onInsertMention("", pendingMention);
66029
65973
  this.clearPendingStatus(pendingStatusKey);
66030
65974
  const errorMessage3 = err instanceof Error ? err.message : String(err);
66031
65975
  if (errorMessage3.includes("PLATFORM_NOT_SUPPORTED")) {
66032
- this.onError?.("\u5F53\u524D AI \u6A21\u578B\u4E0D\u652F\u6301\u6587\u4EF6\u4E0A\u4F20");
65976
+ this.onError?.("The current AI model does not support file uploads.");
66033
65977
  } else if (errorMessage3.includes("ENOENT")) {
66034
- this.onError?.("\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u8BBF\u95EE");
65978
+ this.onError?.("File does not exist or cannot be accessed.");
66035
65979
  } else if (errorMessage3.includes("EACCES") || errorMessage3.includes("PERMISSION")) {
66036
- this.onError?.("\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u8BE5\u6587\u4EF6");
65980
+ this.onError?.("Permission denied while accessing the file.");
66037
65981
  } else if (errorMessage3.includes("network") || errorMessage3.includes("ETIMEDOUT") || errorMessage3.includes("ECONNREFUSED")) {
66038
- this.onError?.("\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5\u540E\u91CD\u8BD5");
65982
+ this.onError?.("Network error. Check the connection and try again.");
66039
65983
  } else {
66040
- this.onError?.(`\u4E0A\u4F20\u5931\u8D25: ${errorMessage3}`);
65984
+ this.onError?.(`Upload failed: ${errorMessage3}`);
66041
65985
  }
66042
65986
  } finally {
66043
65987
  this.clearPendingStatus(pendingStatusKey);
66044
65988
  this.pendingUploadCount = Math.max(0, this.pendingUploadCount - 1);
66045
65989
  }
66046
65990
  } else {
66047
- this.onError?.("\u65E0\u6548\u7684\u6587\u4EF6\u9009\u9879");
65991
+ this.onError?.("Invalid file option.");
66048
65992
  }
66049
65993
  this.browsingDirectory = void 0;
66050
65994
  this.onHidePicker();
@@ -66186,10 +66130,10 @@ var MentionHandler = class {
66186
66130
  const seenNames = /* @__PURE__ */ new Set();
66187
66131
  options.push({
66188
66132
  type: "browse",
66189
- name: "\u6D4F\u89C8\u6587\u4EF6\u7CFB\u7EDF...",
66133
+ name: "Browse filesystem...",
66190
66134
  path: process.cwd(),
66191
66135
  icon: "\u{1F4C2}",
66192
- meta: "\u8DF3\u51FA\u5F53\u524D\u76EE\u5F55\u9009\u62E9\u6587\u4EF6"
66136
+ meta: "Choose a file outside the current directory"
66193
66137
  });
66194
66138
  try {
66195
66139
  const sessionFiles = this.fileManager.getSessionFiles();
@@ -66197,7 +66141,7 @@ var MentionHandler = class {
66197
66141
  if (!query || file.name.toLowerCase().includes(query.toLowerCase())) {
66198
66142
  if (seenNames.has(file.name.toLowerCase())) continue;
66199
66143
  seenNames.add(file.name.toLowerCase());
66200
- const statusText = file.status === "ready" ? "\u5DF2\u4E0A\u4F20" : file.status === "uploading" ? "\u4E0A\u4F20\u4E2D" : file.status === "expired" ? "\u5DF2\u8FC7\u671F" : file.status;
66144
+ const statusText = file.status === "ready" ? "uploaded" : file.status === "uploading" ? "uploading" : file.status === "expired" ? "expired" : file.status;
66201
66145
  options.push({
66202
66146
  type: "cached",
66203
66147
  name: file.name,
@@ -66221,7 +66165,7 @@ var MentionHandler = class {
66221
66165
  path: file.path,
66222
66166
  icon: getFileTypeIcon(file.type),
66223
66167
  cacheStatus: file.cacheStatus,
66224
- meta: `${this.formatCacheMeta(file.cacheStatus)}\u5F53\u524D\u76EE\u5F55 \u2022 ${formatBytes(file.size)}`
66168
+ meta: `${this.formatCacheMeta(file.cacheStatus)}current directory \u2022 ${formatBytes(file.size)}`
66225
66169
  });
66226
66170
  }
66227
66171
  } catch (err) {
@@ -66244,7 +66188,7 @@ var MentionHandler = class {
66244
66188
  hash: file.hash,
66245
66189
  fileId,
66246
66190
  icon: getFileTypeIcon(file.type),
66247
- meta: `\u7F13\u5B58 \u2022 ${formatBytes(file.size)}`
66191
+ meta: `cache \u2022 ${formatBytes(file.size)}`
66248
66192
  });
66249
66193
  if (options.length >= 10) break;
66250
66194
  }
@@ -66265,7 +66209,7 @@ var MentionHandler = class {
66265
66209
  name,
66266
66210
  path: resolvedPath,
66267
66211
  icon: "\u2B06\uFE0F",
66268
- meta: `${formatBytes(stats.size)} \u2022 \u70B9\u51FB\u4E0A\u4F20`
66212
+ meta: `${formatBytes(stats.size)} \u2022 click to upload`
66269
66213
  });
66270
66214
  }
66271
66215
  }
@@ -66290,7 +66234,7 @@ var MentionHandler = class {
66290
66234
  name: "..",
66291
66235
  path: path26.dirname(currentDir),
66292
66236
  icon: "\u21A9",
66293
- meta: "\u8FD4\u56DE\u4E0A\u7EA7\u76EE\u5F55"
66237
+ meta: "Parent directory"
66294
66238
  });
66295
66239
  }
66296
66240
  for (const directory of entries.directories) {
@@ -66299,7 +66243,7 @@ var MentionHandler = class {
66299
66243
  name: directory.name,
66300
66244
  path: directory.path,
66301
66245
  icon: "\u{1F4C1}",
66302
- meta: "\u76EE\u5F55"
66246
+ meta: "Directory"
66303
66247
  });
66304
66248
  }
66305
66249
  for (const file of entries.files) {
@@ -66314,7 +66258,7 @@ var MentionHandler = class {
66314
66258
  }
66315
66259
  return {
66316
66260
  options,
66317
- queryLabel: `\u6D4F\u89C8 ${displayDir}${filter ? ` \xB7 ${filter}` : ""}`
66261
+ queryLabel: `Browse ${displayDir}${filter ? ` \xB7 ${filter}` : ""}`
66318
66262
  };
66319
66263
  }
66320
66264
  getBrowserDirectory(query = this.currentQuery) {
@@ -66331,24 +66275,24 @@ var MentionHandler = class {
66331
66275
  const normalizedPlatform = normalizeFileManagerPlatform(platform2);
66332
66276
  const fileInfo = this.findFileByFileId(fileId);
66333
66277
  if (!fileInfo) {
66334
- return { reason: "\u6587\u4EF6\u4E0D\u53EF\u7528" };
66278
+ return { reason: "File unavailable" };
66335
66279
  }
66336
66280
  if (fileInfo.platform === "local") {
66337
- return { fileInfo, reason: "\u4EC5\u672C\u5730\u53EF\u590D\u7528" };
66281
+ return { fileInfo, reason: "Reusable locally only" };
66338
66282
  }
66339
66283
  if (fileInfo.platform !== normalizedPlatform) {
66340
- return { fileInfo, reason: "\u5F53\u524D\u5E73\u53F0\u4E0D\u53EF\u590D\u7528" };
66284
+ return { fileInfo, reason: "Not reusable on the current platform" };
66341
66285
  }
66342
66286
  const fileStatus = await this.fileManager.getFileStatus(fileId);
66343
66287
  if (!fileStatus) {
66344
- return { fileInfo, reason: "\u6587\u4EF6\u4E0D\u53EF\u7528" };
66288
+ return { fileInfo, reason: "File unavailable" };
66345
66289
  }
66346
66290
  if (fileStatus.status === "active" || fileStatus.status === "ready") {
66347
66291
  return { fileInfo, fileId, status: "ready", reason: "ok" };
66348
66292
  }
66349
66293
  if (fileStatus.status === "processing" || fileStatus.status === "uploading") {
66350
66294
  if (fileInfo.mimeType.startsWith("video/")) {
66351
- return { fileInfo, fileId, status: "uploading", reason: "\u89C6\u9891\u5904\u7406\u4E2D" };
66295
+ return { fileInfo, fileId, status: "uploading", reason: "Video is still processing" };
66352
66296
  }
66353
66297
  return { fileInfo, fileId, status: "ready", reason: "ok" };
66354
66298
  }
@@ -66357,12 +66301,12 @@ var MentionHandler = class {
66357
66301
  if (refreshed.success && refreshed.fileId) {
66358
66302
  return { fileInfo, fileId: refreshed.fileId, status: "ready", reason: "ok" };
66359
66303
  }
66360
- return { fileInfo, reason: "\u6587\u4EF6\u5DF2\u8FC7\u671F" };
66304
+ return { fileInfo, reason: "File expired" };
66361
66305
  }
66362
66306
  if (fileStatus.unsupportedPlatform) {
66363
- return { fileInfo, reason: "\u5F53\u524D\u5E73\u53F0\u4E0D\u53EF\u590D\u7528" };
66307
+ return { fileInfo, reason: "Not reusable on the current platform" };
66364
66308
  }
66365
- return { fileInfo, reason: "\u6587\u4EF6\u4E0D\u53EF\u7528" };
66309
+ return { fileInfo, reason: "File unavailable" };
66366
66310
  }
66367
66311
  formatMention(name, fileId) {
66368
66312
  return `@[${name}](file:${fileId}) `;
@@ -66372,20 +66316,20 @@ var MentionHandler = class {
66372
66316
  }
66373
66317
  formatUploadProgress(name, progress, stage) {
66374
66318
  const stageNames = {
66375
- analyzing: "\u5206\u6790\u4E2D",
66376
- preprocessing: "\u9884\u5904\u7406\u4E2D",
66377
- uploading: "\u4E0A\u4F20\u4E2D",
66378
- processing: "\u5E73\u53F0\u5904\u7406\u4E2D",
66379
- complete: "\u5B8C\u6210"
66319
+ analyzing: "Analyzing",
66320
+ preprocessing: "Preprocessing",
66321
+ uploading: "Uploading",
66322
+ processing: "Processing",
66323
+ complete: "Complete"
66380
66324
  };
66381
66325
  return `${stageNames[stage]} ${name}... ${Math.max(0, Math.min(100, Math.round(progress)))}%`;
66382
66326
  }
66383
66327
  formatCacheMeta(cacheStatus) {
66384
66328
  if (cacheStatus === "uploaded") {
66385
- return `\u66FE\u4E0A\u4F20\u5230${this.fileManager.getPlatformDisplayName()} \u2022 `;
66329
+ return `uploaded to ${this.fileManager.getPlatformDisplayName()} \u2022 `;
66386
66330
  }
66387
66331
  if (cacheStatus === "cached") {
66388
- return "\u4EC5\u672C\u5730\u53EF\u590D\u7528 \u2022 ";
66332
+ return "local cache only \u2022 ";
66389
66333
  }
66390
66334
  return "";
66391
66335
  }
@@ -66849,7 +66793,8 @@ function queueMessage(host, text, mode, options = {}) {
66849
66793
  streamingBehavior: mode,
66850
66794
  displayText: text,
66851
66795
  dedupeKey: options.dedupeKey,
66852
- clearEditor
66796
+ clearEditor,
66797
+ deliverWhileStreaming: options.deliverWhileStreaming ?? mode === "steer"
66853
66798
  }
66854
66799
  ).catch((error) => {
66855
66800
  host.showError(`Queue error: ${error instanceof Error ? error.message : String(error)}`);
@@ -67073,52 +67018,15 @@ var TodoWidgetComponent = class extends Container {
67073
67018
 
67074
67019
  // src/agent-guidelines.ts
67075
67020
  function buildCodingAgentGuidelinesSection(tools = []) {
67076
- const toolNames = new Set(tools.map((tool) => tool.name));
67077
- const hasRead = toolNames.has("read_file");
67078
- const hasWrite = toolNames.has("write_file");
67079
- const hasEdit = toolNames.has("edit_file");
67080
- const hasGrep = toolNames.has("grep_text");
67081
- const hasFind = toolNames.has("find_files");
67082
- const hasBash = toolNames.has("bash");
67083
- const hasWebResearch = toolNames.has("web_research");
67084
- const hasWebSearch = toolNames.has("web_search");
67085
- const hasWebFetch = toolNames.has("web_fetch");
67086
- const hasCodeIntel = toolNames.has("code_intel");
67087
- const hasTodo = toolNames.has("manage_todo_list");
67021
+ void tools;
67088
67022
  const guidelines = [
67089
- "Complete coding tasks by making the needed file changes; do not stop at analysis."
67023
+ "Handle coding tasks by analyzing, planning, or making changes as the available tools and user request allow; do not stop at analysis when execution is expected.",
67024
+ "Work in the current workspace, preserve user changes, and keep edits focused.",
67025
+ "Inspect the relevant code before changing it. Use file tools for workspace writes; do not use shell redirection or heredocs to bypass write_file/edit_file guards.",
67026
+ "Run the most relevant existing test, build, or check after file changes when practical.",
67027
+ "If a command fails or times out, change the approach instead of repeating the same command.",
67028
+ "Finish with a concise summary of changes, validation, and any remaining risk."
67090
67029
  ];
67091
- if (hasRead && hasEdit) {
67092
- guidelines.push("Read the current file before edit_file; use precise replacements and batch related edits when possible.");
67093
- }
67094
- if (hasGrep || hasFind) {
67095
- guidelines.push("Use targeted search to locate files, then read only the ranges needed for the edit.");
67096
- }
67097
- if (hasRead && !hasEdit) {
67098
- guidelines.push("Read only the relevant ranges; avoid repeating unchanged reads.");
67099
- }
67100
- if (hasWrite) {
67101
- guidelines.push("Use write_file for new files or true complete rewrites; prefer edit_file for targeted changes.");
67102
- }
67103
- if (hasBash) {
67104
- if (hasWrite || hasEdit) {
67105
- guidelines.push("Use file tools for file writes; do not use shell redirection or heredocs to bypass write_file/edit_file guards.");
67106
- }
67107
- guidelines.push("Use bash for tests, builds, and inspection commands; if a command fails or times out, change the approach instead of repeating it.");
67108
- }
67109
- if (hasWebResearch || hasWebSearch || hasWebFetch) {
67110
- guidelines.push("Use web tools only when current or external public information is required.");
67111
- }
67112
- if (hasCodeIntel) {
67113
- guidelines.push("Use code_intel when type, diagnostic, definition, or reference information would materially reduce code-reading churn.");
67114
- }
67115
- if (hasTodo) {
67116
- guidelines.push("Use manage_todo_list only for genuinely multi-step work, and mark items done only after the work is complete.");
67117
- }
67118
- guidelines.push(
67119
- "Run the relevant existing test or build after changes; if it passes, stop and report the result.",
67120
- "Keep task-relative paths relative to the current working directory."
67121
- );
67122
67030
  return `## Guidelines
67123
67031
 
67124
67032
  ${guidelines.map((guideline, index) => `${index + 1}. ${guideline}`).join("\n")}`;
@@ -67531,7 +67439,7 @@ function recoverFromInvalidFileReferenceError(host, errorMessage3) {
67531
67439
  const fileId = url.slice("ms://".length);
67532
67440
  if (!invalidFileIds.has(fileId)) return [block];
67533
67441
  messageChanged = true;
67534
- return [{ type: "text", text: " [\u6587\u4EF6\u5F15\u7528\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6587\u4EF6] " }];
67442
+ return [{ type: "text", text: " [File reference expired. Please attach the file again.] " }];
67535
67443
  });
67536
67444
  if (!messageChanged) return message;
67537
67445
  changed = true;
@@ -67539,7 +67447,7 @@ function recoverFromInvalidFileReferenceError(host, errorMessage3) {
67539
67447
  });
67540
67448
  if (!changed) return;
67541
67449
  host.replaceAgentMessagesAndMarkSynced(sanitizedMessages, { updateSession: true });
67542
- host.showStatus("\u68C0\u6D4B\u5230\u5931\u6548\u6587\u4EF6\u5F15\u7528\uFF0C\u5DF2\u4ECE\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u79FB\u9664\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6587\u4EF6");
67450
+ host.showStatus("Removed expired file references from this session context. Please attach the file again.");
67543
67451
  }
67544
67452
 
67545
67453
  // src/components/hierarchical-selector.ts
@@ -68321,6 +68229,80 @@ function buildDirectShellCommand(command) {
68321
68229
  }
68322
68230
  return { file: "bash", args: ["-lc", command], prompt: "$" };
68323
68231
  }
68232
+ var DIRECT_OUTPUT_MAX_LINES = 400;
68233
+ var DIRECT_OUTPUT_MAX_BYTES = 16 * 1024;
68234
+ var DIRECT_CAPTURE_PREFIX_BYTES = 512 * 1024;
68235
+ var DIRECT_CAPTURE_TAIL_BYTES = 512 * 1024;
68236
+ function takeUtf8Prefix(text, maxBytes) {
68237
+ const bytes = Buffer.from(text, "utf8");
68238
+ if (bytes.length <= maxBytes) return text;
68239
+ return bytes.subarray(0, maxBytes).toString("utf8").replace(/\uFFFD+$/g, "");
68240
+ }
68241
+ function takeUtf8Suffix(text, maxBytes) {
68242
+ const bytes = Buffer.from(text, "utf8");
68243
+ if (bytes.length <= maxBytes) return text;
68244
+ return bytes.subarray(Math.max(0, bytes.length - maxBytes)).toString("utf8").replace(/^\uFFFD+/g, "");
68245
+ }
68246
+ var DirectBashOutputCollector = class {
68247
+ prefix = "";
68248
+ tail = "";
68249
+ totalBytes = 0;
68250
+ overflowed = false;
68251
+ append(text) {
68252
+ if (!text) return;
68253
+ const bytes = Buffer.byteLength(text, "utf8");
68254
+ this.totalBytes += bytes;
68255
+ if (!this.overflowed) {
68256
+ const next = this.prefix + text;
68257
+ if (Buffer.byteLength(next, "utf8") <= DIRECT_CAPTURE_PREFIX_BYTES + DIRECT_CAPTURE_TAIL_BYTES) {
68258
+ this.prefix = next;
68259
+ return;
68260
+ }
68261
+ this.overflowed = true;
68262
+ this.prefix = takeUtf8Prefix(next, DIRECT_CAPTURE_PREFIX_BYTES);
68263
+ this.tail = takeUtf8Suffix(next, DIRECT_CAPTURE_TAIL_BYTES);
68264
+ return;
68265
+ }
68266
+ this.tail = takeUtf8Suffix(this.tail + text, DIRECT_CAPTURE_TAIL_BYTES);
68267
+ }
68268
+ format() {
68269
+ if (this.totalBytes === 0) {
68270
+ return {
68271
+ text: "[command completed with no output]",
68272
+ empty: true,
68273
+ truncated: false,
68274
+ totalBytes: 0,
68275
+ totalLines: 0
68276
+ };
68277
+ }
68278
+ const materialized = this.overflowed ? `${this.prefix}
68279
+ ... [direct bash capture omitted ${formatSize(Math.max(0, this.totalBytes - Buffer.byteLength(this.prefix, "utf8") - Buffer.byteLength(this.tail, "utf8")))} from the middle] ...
68280
+ ${this.tail}` : this.prefix;
68281
+ const truncated = truncateHeadTail(materialized, {
68282
+ maxLines: DIRECT_OUTPUT_MAX_LINES,
68283
+ maxBytes: DIRECT_OUTPUT_MAX_BYTES
68284
+ });
68285
+ const suffix = truncated.truncated ? `
68286
+
68287
+ [direct bash output truncated: showing ${truncated.outputLines}/${truncated.totalLines} lines, ${formatSize(truncated.outputBytes)}/${formatSize(this.totalBytes)}]` : "";
68288
+ return {
68289
+ text: `${truncated.content}${suffix}`,
68290
+ empty: false,
68291
+ truncated: truncated.truncated || this.overflowed,
68292
+ totalBytes: this.totalBytes,
68293
+ totalLines: truncated.totalLines
68294
+ };
68295
+ }
68296
+ };
68297
+ function renderOutputText(outputContainer, text, color = "dim") {
68298
+ const lines = text.split("\n");
68299
+ for (let i = 0; i < lines.length; i += 1) {
68300
+ const line = lines[i];
68301
+ if (line || i < lines.length - 1) {
68302
+ outputContainer.addChild(new Text(theme.fg(color, line), 1, 0));
68303
+ }
68304
+ }
68305
+ }
68324
68306
  async function handleDirectBash(host, command) {
68325
68307
  host.chatContainer.addChild(new Spacer(1));
68326
68308
  const shellCommand = buildDirectShellCommand(command);
@@ -68335,31 +68317,20 @@ async function handleDirectBash(host, command) {
68335
68317
  cwd: process.cwd(),
68336
68318
  env: process.env
68337
68319
  });
68320
+ const output = new DirectBashOutputCollector();
68338
68321
  child.stdout.on("data", (data) => {
68339
- const text = data.toString();
68340
- const lines = text.split("\n");
68341
- for (const line of lines) {
68342
- if (line || lines.indexOf(line) < lines.length - 1) {
68343
- outputContainer.addChild(new Text(theme.fg("dim", line), 1, 0));
68344
- }
68345
- }
68346
- host.ui.requestRender();
68322
+ output.append(data.toString());
68347
68323
  });
68348
68324
  child.stderr.on("data", (data) => {
68349
- const text = data.toString();
68350
- const lines = text.split("\n");
68351
- for (const line of lines) {
68352
- if (line || lines.indexOf(line) < lines.length - 1) {
68353
- outputContainer.addChild(new Text(theme.fg("error", line), 1, 0));
68354
- }
68355
- }
68356
- host.ui.requestRender();
68325
+ output.append(data.toString());
68357
68326
  });
68358
68327
  return new Promise((resolve5) => {
68359
68328
  let settled = false;
68360
68329
  const finish = (code) => {
68361
68330
  if (settled) return;
68362
68331
  settled = true;
68332
+ const formatted = output.format();
68333
+ renderOutputText(outputContainer, formatted.text, code === 0 ? "dim" : "error");
68363
68334
  if (code !== 0) {
68364
68335
  outputContainer.addChild(new Spacer(1));
68365
68336
  outputContainer.addChild(new Text(theme.fg("error", `[exit ${code ?? "spawn error"}]`), 1, 0));
@@ -68369,7 +68340,7 @@ async function handleDirectBash(host, command) {
68369
68340
  resolve5();
68370
68341
  };
68371
68342
  child.on("error", (error) => {
68372
- outputContainer.addChild(new Text(theme.fg("error", error.message), 1, 0));
68343
+ output.append(error.message);
68373
68344
  finish(null);
68374
68345
  });
68375
68346
  child.on("close", (code) => {
@@ -69134,10 +69105,8 @@ var InteractiveMode = class {
69134
69105
  const rebuilt = this.rebuildSkillAwareTools(completeToolSet);
69135
69106
  const currentTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.currentTools, this.extensionRunner) : rebuilt.currentTools;
69136
69107
  const originalTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.originalTools, this.extensionRunner) : rebuilt.originalTools;
69137
- const defaultToolSet = this.options.settingsManager.getDefaultToolSet();
69138
- const defaultTools = selectDefaultTools(currentTools, defaultToolSet);
69139
69108
  const activeTools = selectToolsForRuntimeMode(
69140
- defaultTools,
69109
+ currentTools,
69141
69110
  this.planModeEnabled ? "plan" : "normal"
69142
69111
  );
69143
69112
  this.agent.setTools(activeTools);
@@ -69219,6 +69188,7 @@ var InteractiveMode = class {
69219
69188
  },
69220
69189
  apiKey: this.options.apiKey,
69221
69190
  sessionId: activeSession?.id,
69191
+ streamFn: this.options.streamFn,
69222
69192
  transformContext: createRuntimeModeTransformContext({
69223
69193
  getState: () => this.getRuntimeModeState(),
69224
69194
  consumeTransition: () => this.consumeRuntimeModeTransition(),
@@ -69703,12 +69673,11 @@ async function composeCliRuntime(params) {
69703
69673
  const allTools = createPolicyEnforcedTools(rawTools, {
69704
69674
  getContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
69705
69675
  });
69706
- const defaultToolSet = settingsManager.getDefaultToolSet();
69707
- const tools = selectDefaultTools(allTools, defaultToolSet);
69676
+ const tools = [...allTools];
69708
69677
  recordCliCompositionStep(compositionTrace, {
69709
69678
  id: "policy_filtering",
69710
69679
  inputSummary: `tools=${rawTools.length}`,
69711
- outputSummary: `${summarizeToolNames(tools)} (defaultSet=${defaultToolSet}; available=${allTools.length})`,
69680
+ outputSummary: summarizeToolNames(tools),
69712
69681
  toolCount: tools.length,
69713
69682
  policyDecisions: rawTools.length === allTools.length ? ["allow:default"] : [`filtered:${rawTools.length - allTools.length}`]
69714
69683
  });
@@ -71201,11 +71170,8 @@ async function runWithJsonEventsConsoleIsolation(fn) {
71201
71170
  }
71202
71171
  }
71203
71172
  async function createCliTestStreamFnFromEnv() {
71204
- if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) {
71205
- return void 0;
71206
- }
71207
- const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-ZNGAUUVH.js");
71208
- return createTestStreamFnFromSequenceEnv();
71173
+ if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
71174
+ return (await import("./chunks/test-stream-A7JSM2UM.js")).createTestStreamFnFromSequenceEnv();
71209
71175
  }
71210
71176
  async function startChat(initialPrompt, testCommand) {
71211
71177
  const rawOutput = process.argv.includes("--raw-output");
@@ -71276,7 +71242,9 @@ async function startChat(initialPrompt, testCommand) {
71276
71242
  process.env.PIE_TUI_ACTIVE = "1";
71277
71243
  const runtimeLogger = initializeCliRuntimeLogger(runtime.sessionId, { mode: "interactive_tui" });
71278
71244
  const restoreConsoleInterception = installInteractiveConsoleInterception(runtimeLogger);
71279
- const interactive = new InteractiveMode(runtime.createInteractiveOptions());
71245
+ const interactiveOptions = runtime.createInteractiveOptions();
71246
+ interactiveOptions.streamFn = await createCliTestStreamFnFromEnv();
71247
+ const interactive = new InteractiveMode(interactiveOptions);
71280
71248
  try {
71281
71249
  await interactive.init();
71282
71250
  if (runtime.initialModel.unconfigured && runtime.initialModel.warning) {