@cydm/pie 1.0.47 → 1.0.49

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
@@ -19,7 +19,10 @@ import {
19
19
  getThemesDir,
20
20
  migrateConfigFromAgentDir,
21
21
  truncateHeadTail
22
- } from "./chunks/chunk-U4B6RJ6Z.js";
22
+ } from "./chunks/chunk-J6PEH6ST.js";
23
+ import {
24
+ resolveCliProjectRoot
25
+ } from "./chunks/chunk-WLFOBECN.js";
23
26
  import {
24
27
  AGENTS_CONTEXT_FILE_NAME,
25
28
  AgentSessionController,
@@ -70,7 +73,7 @@ import {
70
73
  setExtensionEnabledInSettings,
71
74
  shouldPreserveExecutionStateForUserText,
72
75
  supersedeExecutionState
73
- } from "./chunks/chunk-IJMP3JTX.js";
76
+ } from "./chunks/chunk-7RYOIXA2.js";
74
77
  import "./chunks/chunk-FKAO25XH.js";
75
78
  import {
76
79
  Deref,
@@ -108,9 +111,6 @@ import {
108
111
  sortToolModelCandidatesByCapability,
109
112
  type_exports
110
113
  } from "./chunks/chunk-K6ZOCJ4V.js";
111
- import {
112
- resolveCliProjectRoot
113
- } from "./chunks/chunk-WLFOBECN.js";
114
114
  import {
115
115
  __commonJS,
116
116
  __require,
@@ -51654,6 +51654,33 @@ var SelectList = class {
51654
51654
  }
51655
51655
  invalidate() {
51656
51656
  }
51657
+ /**
51658
+ * Lay out one item row: label (left column) + description (right column).
51659
+ *
51660
+ * The label column is sized from the actual labels and the available
51661
+ * width. The previous fixed 30-column cap truncated long commands (e.g.
51662
+ * /skills/skill:terminal-pty-testing) even on wide terminals.
51663
+ */
51664
+ renderLabelParts(prefix, displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width) {
51665
+ const prefixWidth = visibleWidth(prefix);
51666
+ if (useDescriptionColumn && descriptionSingleLine) {
51667
+ const truncatedValue = truncateToWidth(displayValue, labelColumnWidth, "");
51668
+ const valueWidth = visibleWidth(truncatedValue);
51669
+ const spacing = " ".repeat(Math.max(1, labelColumnWidth - valueWidth + 2));
51670
+ const descriptionStart = prefixWidth + valueWidth + spacing.length;
51671
+ const remainingWidth = width - descriptionStart - 2;
51672
+ if (remainingWidth > 10) {
51673
+ return {
51674
+ value: truncatedValue,
51675
+ spacing,
51676
+ desc: truncateToWidth(descriptionSingleLine, remainingWidth, "")
51677
+ };
51678
+ }
51679
+ return { value: truncateToWidth(displayValue, width - prefixWidth - 2, ""), spacing: "", desc: "" };
51680
+ }
51681
+ const maxWidth = width - prefixWidth - 2;
51682
+ return { value: truncateToWidth(displayValue, maxWidth, ""), spacing: "", desc: "" };
51683
+ }
51657
51684
  render(width) {
51658
51685
  const lines = [];
51659
51686
  if (this.filteredItems.length === 0) {
@@ -51661,54 +51688,35 @@ var SelectList = class {
51661
51688
  return lines;
51662
51689
  }
51663
51690
  const { startIndex, endIndex } = this.getVisibleRange();
51691
+ const useDescriptionColumn = this.filteredItems.some((item) => item.description) && width > 40;
51692
+ let labelColumnWidth = 0;
51693
+ if (useDescriptionColumn) {
51694
+ const maxLabelWidth = Math.max(
51695
+ ...this.filteredItems.map((item) => visibleWidth(item.label || item.value))
51696
+ );
51697
+ labelColumnWidth = Math.max(8, Math.min(maxLabelWidth, Math.floor(width * 0.45)));
51698
+ }
51664
51699
  for (let i = startIndex; i < endIndex; i++) {
51665
51700
  const item = this.filteredItems[i];
51666
51701
  if (!item) continue;
51667
51702
  const isSelected = i === this.selectedIndex;
51668
51703
  const descriptionSingleLine = item.description ? normalizeToSingleLine(item.description) : void 0;
51704
+ const displayValue = item.label || item.value;
51669
51705
  let line = "";
51670
51706
  if (isSelected) {
51671
- const prefixWidth = 2;
51672
- const displayValue = item.label || item.value;
51673
- if (descriptionSingleLine && width > 40) {
51674
- const maxValueWidth = Math.min(30, width - prefixWidth - 4);
51675
- const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
51676
- const valueWidth = visibleWidth(truncatedValue);
51677
- const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
51678
- const descriptionStart = prefixWidth + valueWidth + spacing.length;
51679
- const remainingWidth = width - descriptionStart - 2;
51680
- if (remainingWidth > 10) {
51681
- const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
51682
- line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncatedValue}${spacing}${truncatedDesc}`), width, "");
51683
- } else {
51684
- const maxWidth = width - prefixWidth - 2;
51685
- line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
51686
- }
51687
- } else {
51688
- const maxWidth = width - prefixWidth - 2;
51689
- line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
51690
- }
51707
+ const parts = this.renderLabelParts("\u2192 ", displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width);
51708
+ line = truncateToWidth(
51709
+ this.theme.selectedText(`\u2192 ${parts.value}${parts.spacing}${parts.desc}`),
51710
+ width,
51711
+ ""
51712
+ );
51691
51713
  } else {
51692
- const displayValue = item.label || item.value;
51693
- const prefix = " ";
51694
- if (descriptionSingleLine && width > 40) {
51695
- const maxValueWidth = Math.min(30, width - prefix.length - 4);
51696
- const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
51697
- const valueWidth = visibleWidth(truncatedValue);
51698
- const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
51699
- const descriptionStart = prefix.length + valueWidth + spacing.length;
51700
- const remainingWidth = width - descriptionStart - 2;
51701
- if (remainingWidth > 10) {
51702
- const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
51703
- const descText = this.theme.description(spacing + truncatedDesc);
51704
- line = truncateToWidth(prefix + truncatedValue + descText, width, "");
51705
- } else {
51706
- const maxWidth = width - prefix.length - 2;
51707
- line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
51708
- }
51714
+ const parts = this.renderLabelParts(" ", displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width);
51715
+ if (parts.desc) {
51716
+ const descText = this.theme.description(parts.spacing + parts.desc);
51717
+ line = truncateToWidth(" " + parts.value + descText, width, "");
51709
51718
  } else {
51710
- const maxWidth = width - prefix.length - 2;
51711
- line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
51719
+ line = truncateToWidth(" " + parts.value, width, "");
51712
51720
  }
51713
51721
  }
51714
51722
  lines.push(truncateToWidth(line, width, ""));
@@ -52086,6 +52094,10 @@ var Editor = class {
52086
52094
  this.autocompleteList.handleInput(data);
52087
52095
  return;
52088
52096
  }
52097
+ if (kb.matches(data, "cursorLeft") || kb.matches(data, "cursorRight") || kb.matches(data, "pageUp") || kb.matches(data, "pageDown")) {
52098
+ this.autocompleteList.handleInput(data);
52099
+ return;
52100
+ }
52089
52101
  if (kb.matches(data, "tab")) {
52090
52102
  const selected = this.autocompleteList.getSelectedItem();
52091
52103
  if (selected && this.autocompleteProvider) {
@@ -52107,32 +52119,26 @@ var Editor = class {
52107
52119
  return;
52108
52120
  }
52109
52121
  if (kb.matches(data, "selectConfirm")) {
52110
- const currentLine = this.state.lines[this.state.cursorLine] || "";
52111
- const isBareSlashSubmit = this.state.lines.length === 1 && currentLine === "/" && this.state.cursorCol === 1;
52112
- if (isBareSlashSubmit) {
52113
- this.cancelAutocomplete();
52114
- } else {
52115
- const selected = this.autocompleteList.getSelectedItem();
52116
- if (selected && this.autocompleteProvider) {
52117
- this.pushUndoSnapshot();
52118
- this.lastAction = null;
52119
- const result = this.autocompleteProvider.applyCompletion(
52120
- this.state.lines,
52121
- this.state.cursorLine,
52122
- this.state.cursorCol,
52123
- selected,
52124
- this.autocompletePrefix
52125
- );
52126
- this.state.lines = result.lines;
52127
- this.state.cursorLine = result.cursorLine;
52128
- this.setCursorCol(result.cursorCol);
52129
- if (this.autocompletePrefix.startsWith("/")) {
52130
- this.cancelAutocomplete();
52131
- } else {
52132
- this.cancelAutocomplete();
52133
- if (this.onChange) this.onChange(this.getText());
52134
- return;
52135
- }
52122
+ const selected = this.autocompleteList.getSelectedItem();
52123
+ if (selected && this.autocompleteProvider) {
52124
+ this.pushUndoSnapshot();
52125
+ this.lastAction = null;
52126
+ const result = this.autocompleteProvider.applyCompletion(
52127
+ this.state.lines,
52128
+ this.state.cursorLine,
52129
+ this.state.cursorCol,
52130
+ selected,
52131
+ this.autocompletePrefix
52132
+ );
52133
+ this.state.lines = result.lines;
52134
+ this.state.cursorLine = result.cursorLine;
52135
+ this.setCursorCol(result.cursorCol);
52136
+ if (this.autocompletePrefix.startsWith("/")) {
52137
+ this.cancelAutocomplete();
52138
+ } else {
52139
+ this.cancelAutocomplete();
52140
+ if (this.onChange) this.onChange(this.getText());
52141
+ return;
52136
52142
  }
52137
52143
  }
52138
52144
  }
@@ -53128,12 +53134,28 @@ var Editor = class {
53128
53134
  );
53129
53135
  if (suggestions && suggestions.items.length > 0) {
53130
53136
  this.autocompletePrefix = suggestions.prefix;
53131
- this.autocompleteList = new SelectList(suggestions.items, this.autocompleteMaxVisible, this.theme.selectList);
53137
+ this.autocompleteList = new SelectList(
53138
+ suggestions.items,
53139
+ this.computeAutocompleteMaxVisible(suggestions.items.length),
53140
+ this.theme.selectList
53141
+ );
53132
53142
  this.autocompleteState = "regular";
53133
53143
  } else {
53134
53144
  this.cancelAutocomplete();
53135
53145
  }
53136
53146
  }
53147
+ /**
53148
+ * Visible autocomplete rows, scaled with terminal height so tall screens
53149
+ * show the full command list instead of paginating five rows at a time.
53150
+ * Floor: the configured max (default 5). Ceiling: ~45% of rows, capped at
53151
+ * 20 so a huge terminal never dedicates half the screen to suggestions.
53152
+ */
53153
+ computeAutocompleteMaxVisible(itemCount) {
53154
+ const rows = this.tui.terminal.rows;
53155
+ const heightScaled = Number.isFinite(rows) ? Math.floor(rows * 0.45) : this.autocompleteMaxVisible;
53156
+ const desired = Math.max(this.autocompleteMaxVisible, Math.min(heightScaled, 20));
53157
+ return Math.max(1, Math.min(desired, Math.max(itemCount, 1)));
53158
+ }
53137
53159
  handleTabCompletion() {
53138
53160
  if (!this.autocompleteProvider) return;
53139
53161
  const currentLine = this.state.lines[this.state.cursorLine] || "";
@@ -53183,7 +53205,11 @@ var Editor = class {
53183
53205
  return;
53184
53206
  }
53185
53207
  this.autocompletePrefix = suggestions.prefix;
53186
- this.autocompleteList = new SelectList(suggestions.items, this.autocompleteMaxVisible, this.theme.selectList);
53208
+ this.autocompleteList = new SelectList(
53209
+ suggestions.items,
53210
+ this.computeAutocompleteMaxVisible(suggestions.items.length),
53211
+ this.theme.selectList
53212
+ );
53187
53213
  this.autocompleteState = "force";
53188
53214
  } else {
53189
53215
  this.cancelAutocomplete();
@@ -53210,7 +53236,11 @@ var Editor = class {
53210
53236
  );
53211
53237
  if (suggestions && suggestions.items.length > 0) {
53212
53238
  this.autocompletePrefix = suggestions.prefix;
53213
- this.autocompleteList = new SelectList(suggestions.items, this.autocompleteMaxVisible, this.theme.selectList);
53239
+ this.autocompleteList = new SelectList(
53240
+ suggestions.items,
53241
+ this.computeAutocompleteMaxVisible(suggestions.items.length),
53242
+ this.theme.selectList
53243
+ );
53214
53244
  } else {
53215
53245
  this.cancelAutocomplete();
53216
53246
  }
@@ -55394,6 +55424,17 @@ var SettingsList = class {
55394
55424
  item.currentValue = newValue;
55395
55425
  }
55396
55426
  }
55427
+ /**
55428
+ * Move the selection to an item by id (respects the active filter).
55429
+ * Used when a command targets a specific row (e.g. /settings/theme).
55430
+ */
55431
+ focusItemById(id) {
55432
+ const displayItems = this.searchEnabled ? this.filteredItems : this.items;
55433
+ const index = displayItems.findIndex((item) => item.id === id);
55434
+ if (index >= 0) {
55435
+ this.selectedIndex = index;
55436
+ }
55437
+ }
55397
55438
  invalidate() {
55398
55439
  this.submenuComponent?.invalidate?.();
55399
55440
  }
@@ -62341,6 +62382,9 @@ var SettingsSelectorComponent = class extends Container {
62341
62382
  { enableSearch: true }
62342
62383
  );
62343
62384
  this.addChild(this.settingsList);
62385
+ if (config.focusItem) {
62386
+ this.settingsList.focusItemById(config.focusItem);
62387
+ }
62344
62388
  }
62345
62389
  getSettingsList() {
62346
62390
  return this.settingsList;
@@ -62447,36 +62491,6 @@ function selectRuntimeExtensionWinners(infos) {
62447
62491
  }
62448
62492
  return reversed.reverse();
62449
62493
  }
62450
- var ExtensionStateSubmenu = class extends Container {
62451
- selectList;
62452
- constructor(identity, currentValue, scope, onSelect, onCommitted, onCancel) {
62453
- super();
62454
- this.addChild(new Text(theme.bold(theme.fg("accent", identity)), 0, 0));
62455
- this.addChild(new Spacer(1));
62456
- const settingsPath = scope === "project" ? "./.pie/settings.json" : "~/.pie/settings.json";
62457
- this.addChild(new Text(theme.fg("muted", `Save an override in ${settingsPath}`), 0, 0));
62458
- this.addChild(new Spacer(1));
62459
- const options = [
62460
- { value: "on", label: "On", description: "Enable on next start" },
62461
- { value: "off", label: "Off", description: "Disable on next start" }
62462
- ];
62463
- this.selectList = new SelectList(options, options.length, getSelectListTheme());
62464
- this.selectList.setSelectedIndex(currentValue === "off" ? 1 : 0);
62465
- this.selectList.onSelect = (item) => {
62466
- const effective = onSelect(item.value === "on");
62467
- if (effective !== void 0) {
62468
- onCommitted(effective);
62469
- }
62470
- };
62471
- this.selectList.onCancel = onCancel;
62472
- this.addChild(this.selectList);
62473
- this.addChild(new Spacer(1));
62474
- this.addChild(new Text(theme.fg("dim", " Enter to select \xB7 Esc to go back"), 0, 0));
62475
- }
62476
- handleInput(data) {
62477
- this.selectList.handleInput(data);
62478
- }
62479
- };
62480
62494
  function unidentifiedLabel(info) {
62481
62495
  const parentName = path23.basename(path23.dirname(info.entryPath));
62482
62496
  const fileName = path23.basename(info.entryPath);
@@ -62497,37 +62511,41 @@ var ExtensionEnablementSelectorComponent = class extends Container {
62497
62511
  0
62498
62512
  ));
62499
62513
  this.addChild(new Spacer(1));
62514
+ const identityById = /* @__PURE__ */ new Map();
62515
+ const lastPersistedValue = /* @__PURE__ */ new Map();
62500
62516
  const items = selectRuntimeExtensionWinners(infos).map((info, index) => {
62501
62517
  const identity = info.identity;
62502
62518
  const descriptionParts = [`Source: ${info.source}`];
62503
62519
  if (info.description) descriptionParts.push(info.description);
62504
62520
  if (!identity) descriptionParts.push("No stable identity; this entry is read-only.");
62521
+ const id = identity ?? `unidentified:${index}`;
62522
+ if (identity) {
62523
+ identityById.set(id, identity);
62524
+ lastPersistedValue.set(id, info.enabled ? "on" : "off");
62525
+ }
62505
62526
  const item = {
62506
- id: `extension:${index}`,
62527
+ id,
62507
62528
  label: identity ?? unidentifiedLabel(info),
62508
62529
  description: descriptionParts.join(" \xB7 "),
62509
62530
  currentValue: info.enabled ? "on" : "off"
62510
62531
  };
62511
- if (identity) {
62512
- item.submenu = (currentValue, done) => {
62513
- const submenu = new ExtensionStateSubmenu(
62514
- identity,
62515
- currentValue,
62516
- scope,
62517
- (enabled) => callbacks.onToggle(identity, enabled),
62518
- (effectiveEnabled) => done(effectiveEnabled ? "on" : "off"),
62519
- () => done()
62520
- );
62521
- return submenu;
62522
- };
62523
- }
62532
+ if (identity) item.values = ["on", "off"];
62524
62533
  return item;
62525
62534
  });
62526
62535
  this.settingsList = new SettingsList(
62527
62536
  items,
62528
62537
  10,
62529
62538
  getSettingsListTheme(),
62530
- () => {
62539
+ (id, newValue) => {
62540
+ const identity = identityById.get(id);
62541
+ if (!identity) return;
62542
+ const previous = lastPersistedValue.get(id) ?? "on";
62543
+ const accepted = callbacks.onToggle(identity, newValue === "on");
62544
+ if (accepted === false) {
62545
+ this.settingsList.updateValue(id, previous);
62546
+ return;
62547
+ }
62548
+ lastPersistedValue.set(id, newValue);
62531
62549
  },
62532
62550
  callbacks.onCancel,
62533
62551
  { enableSearch: true }
@@ -62587,9 +62605,9 @@ function createExtensionSelector(host, scope, onCancel) {
62587
62605
  return new ExtensionEnablementSelectorComponent(infos, scope, {
62588
62606
  onToggle: (identity, enabled) => {
62589
62607
  const outcome = trySetExtensionEnabled(host, identity, enabled, scope);
62590
- if (!outcome) return void 0;
62608
+ if (!outcome) return false;
62591
62609
  host.showStatus(outcome.message);
62592
- return outcome.effectiveEnabled;
62610
+ return true;
62593
62611
  },
62594
62612
  onCancel
62595
62613
  });
@@ -62679,16 +62697,26 @@ var BUILTIN_SLASH_COMMANDS = [
62679
62697
  { name: "debugs/context", description: "Append a context summary to ~/.pie/logs/pie-cli.log" },
62680
62698
  { name: "debugs/package", description: "Append a package summary to ~/.pie/logs/pie-cli.log" },
62681
62699
  { name: "settings/quit", description: "Exit Pie" },
62682
- { name: "skills", description: "Open skills menu" },
62683
- { name: "skills/list", description: "List available skills" },
62700
+ { name: "skills", description: "Manage skills: list, toggle enable/disable, invoke" },
62701
+ { name: "skills/list", description: "List available skills (plain text)" },
62702
+ { name: "skills/create", description: "Create a new skill from a template" },
62684
62703
  { name: "skills/enable", description: "Enable a skill by name" },
62685
62704
  { name: "skills/disable", description: "Disable a skill by name" },
62686
62705
  { name: "skills/reload", description: "Reload skills from disk" },
62687
62706
  { name: "skills/use", description: "Use a skill" },
62688
62707
  { name: "tools", description: "List tools and manage enable/disable toggles" },
62708
+ { name: "tools/list", description: "List runtime tools and their state (plain text)" },
62689
62709
  { name: "tools/enable", description: "Enable a tool by name" },
62690
62710
  { name: "tools/disable", description: "Disable a tool by name" },
62691
- { name: "tools/subagent", description: "Spawn subagents in parallel to handle tasks" }
62711
+ { name: "tools/subagent", description: "Spawn subagents in parallel to handle tasks" },
62712
+ { name: "files/upload", description: "Attach a file to the conversation" },
62713
+ { name: "files/upload-pic", description: "Attach an image to the conversation" },
62714
+ { name: "files/upload-video", description: "Attach a video to the conversation" },
62715
+ { name: "files/list", description: "List uploaded files" },
62716
+ { name: "files/status", description: "Check file status" },
62717
+ { name: "files/refresh", description: "Refresh expired files" },
62718
+ { name: "files/delete", description: "Delete a file" },
62719
+ { name: "files/stats", description: "Show file statistics" }
62692
62720
  ];
62693
62721
 
62694
62722
  // src/commands/interactive-debug-commands.ts
@@ -65261,6 +65289,80 @@ function errorMessage2(error) {
65261
65289
  return error instanceof Error ? error.message : String(error);
65262
65290
  }
65263
65291
  function handleSkillsCommand(host) {
65292
+ host.showSelector((done) => {
65293
+ const settingsManager = host.options.settingsManager;
65294
+ const discovered = listDiscoveredSkills(host);
65295
+ const lastPersisted = /* @__PURE__ */ new Map();
65296
+ const items = discovered.map((skill) => ({
65297
+ id: `skill:${skill.name}`,
65298
+ label: skill.name,
65299
+ description: `${skill.description} \xB7 Source: ${skill.source ?? "unknown"}`,
65300
+ currentValue: settingsManager.isSkillEnabled(skill.name) ? "on" : "off",
65301
+ values: ["on", "off"]
65302
+ }));
65303
+ for (const item of items) lastPersisted.set(item.id, item.currentValue);
65304
+ const settingsList = new SettingsList(
65305
+ items,
65306
+ 12,
65307
+ getSettingsListTheme(),
65308
+ (id, newValue) => {
65309
+ const name = id.slice("skill:".length);
65310
+ const enabled = newValue === "on";
65311
+ const previous = lastPersisted.get(id) ?? "on";
65312
+ try {
65313
+ settingsManager.setSkillEnabled(name, enabled);
65314
+ } catch (error) {
65315
+ settingsList.updateValue(id, previous);
65316
+ host.showError(`Failed to update skill "${name}": ${errorMessage2(error)}`);
65317
+ return;
65318
+ }
65319
+ lastPersisted.set(id, newValue);
65320
+ applyReloadedSkills(host, discoverSkills(host));
65321
+ host.showStatus(`Skill "${name}" ${enabled ? "enabled" : "disabled"} (reloaded).`);
65322
+ },
65323
+ () => done(),
65324
+ { enableSearch: true }
65325
+ );
65326
+ const component = {
65327
+ render: (width) => [
65328
+ theme.bold(theme.fg("accent", "Skills")),
65329
+ "",
65330
+ theme.fg("muted", "Enter/Space toggles \xB7 changes apply immediately \xB7 Esc to close"),
65331
+ theme.fg("dim", `Usage: /skills/skill:<name> <your request> (${discovered.length} discovered)`),
65332
+ "",
65333
+ ...settingsList.render(width)
65334
+ ],
65335
+ handleInput: (data) => settingsList.handleInput(data),
65336
+ invalidate: () => settingsList.invalidate()
65337
+ };
65338
+ return { component, focus: settingsList };
65339
+ });
65340
+ }
65341
+ function discoverSkills(host) {
65342
+ const builtinDir = path25.join(getBuiltinDir(), "skills");
65343
+ const userDir = path25.join(os7.homedir(), ".pie", "skills");
65344
+ const projectDir = path25.join(process.cwd(), ".pie", "skills");
65345
+ return loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
65346
+ }
65347
+ function listDiscoveredSkills(host) {
65348
+ return discoverSkills(host).skills;
65349
+ }
65350
+ function applyReloadedSkills(host, result) {
65351
+ host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
65352
+ host.skillsSection = formatSkillsForPrompt(host.skills);
65353
+ host.applyRuntimeToolMode(host.allTools.length > 0 ? host.allTools : host.agent.state.tools);
65354
+ host.updateSystemPromptTools();
65355
+ for (const skill of host.skills) {
65356
+ const skillPath = ["skills", `skill:${skill.name}`];
65357
+ if (!commandTree.find(skillPath)) {
65358
+ commandTree.register(skillPath, {
65359
+ description: skill.description,
65360
+ handler: (_2, args) => host.handleSkillInvoke(skill.name, args || "")
65361
+ });
65362
+ }
65363
+ }
65364
+ }
65365
+ function handleSkillsListCommand(host) {
65264
65366
  host.chatContainer.addChild(new Spacer(1));
65265
65367
  host.chatContainer.addChild(new Text(theme.bold("Available Skills"), 1, 0));
65266
65368
  if (host.skills.length === 0) {
@@ -65417,7 +65519,12 @@ async function handleSkillToggleCommand(host, args, enabled) {
65417
65519
  host.ui.requestRender();
65418
65520
  }
65419
65521
  async function handleSkillsCreate(host, args) {
65420
- console.error(`[SkillsCreate] Called with args: "${args}"`);
65522
+ const debugLog2 = (message) => {
65523
+ if (process.env.PIE_VERBOSE) {
65524
+ console.error(`[SkillsCreate] ${message}`);
65525
+ }
65526
+ };
65527
+ debugLog2(`Called with args: "${args}"`);
65421
65528
  try {
65422
65529
  const trimmed = args.trim();
65423
65530
  if (!trimmed) {
@@ -65448,7 +65555,7 @@ async function handleSkillsCreate(host, args) {
65448
65555
  description = descPart.replace(/^["']|["']$/g, "");
65449
65556
  }
65450
65557
  }
65451
- console.error(`[SkillsCreate] Parsed name: "${name}", description: "${description}"`);
65558
+ debugLog2(`Parsed name: "${name}", description: "${description}"`);
65452
65559
  if (!name) {
65453
65560
  host.showSkillCreatePrompt();
65454
65561
  return;
@@ -65464,7 +65571,7 @@ async function handleSkillsCreate(host, args) {
65464
65571
  const skillsDir = path25.join(os7.homedir(), ".pie", "skills");
65465
65572
  const skillDir = path25.join(skillsDir, name);
65466
65573
  const skillFile = path25.join(skillDir, "SKILL.md");
65467
- console.error(`[SkillsCreate] Creating at: ${skillFile}`);
65574
+ debugLog2(`Creating at: ${skillFile}`);
65468
65575
  if (fs23.existsSync(skillDir)) {
65469
65576
  host.showError(`Skill "${name}" already exists at ${skillDir}`);
65470
65577
  return;
@@ -65472,7 +65579,7 @@ async function handleSkillsCreate(host, args) {
65472
65579
  fs23.mkdirSync(skillDir, { recursive: true });
65473
65580
  const template = createSkillTemplate(name, description);
65474
65581
  fs23.writeFileSync(skillFile, template, "utf-8");
65475
- console.error(`[SkillsCreate] Successfully created skill`);
65582
+ debugLog2("Successfully created skill");
65476
65583
  host.chatContainer.addChild(new Spacer(1));
65477
65584
  host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
65478
65585
  host.chatContainer.addChild(new Text(theme.fg("dim", ` Location: ${skillFile}`), 1, 0));
@@ -65481,7 +65588,7 @@ async function handleSkillsCreate(host, args) {
65481
65588
  host.chatContainer.addChild(new Spacer(1));
65482
65589
  host.ui.requestRender();
65483
65590
  } catch (err) {
65484
- console.error(`[SkillsCreate] Error: ${errorMessage2(err)}`);
65591
+ debugLog2(`Error: ${errorMessage2(err)}`);
65485
65592
  host.showError(`Failed to create skill: ${errorMessage2(err)}`);
65486
65593
  }
65487
65594
  }
@@ -65507,23 +65614,8 @@ async function handleSkillsReload(host) {
65507
65614
  host.chatContainer.addChild(new Text(theme.fg("accent", "Reloading skills..."), 1, 0));
65508
65615
  host.ui.requestRender();
65509
65616
  try {
65510
- const builtinDir = path25.join(getBuiltinDir(), "skills");
65511
- const userDir = path25.join(os7.homedir(), ".pie", "skills");
65512
- const projectDir = path25.join(process.cwd(), ".pie", "skills");
65513
- const result = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
65514
- host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
65515
- host.skillsSection = formatSkillsForPrompt(host.skills);
65516
- host.applyRuntimeToolMode(host.allTools.length > 0 ? host.allTools : host.agent.state.tools);
65517
- host.updateSystemPromptTools();
65518
- for (const skill of host.skills) {
65519
- const skillPath = ["skills", `skill:${skill.name}`];
65520
- if (!commandTree.find(skillPath)) {
65521
- commandTree.register(skillPath, {
65522
- description: skill.description,
65523
- handler: (_2, args) => host.handleSkillInvoke(skill.name, args || "")
65524
- });
65525
- }
65526
- }
65617
+ const result = discoverSkills(host);
65618
+ applyReloadedSkills(host, result);
65527
65619
  const builtinCount = host.skills.filter((s) => s.source === "builtin").length;
65528
65620
  const userCount = host.skills.filter((s) => s.source === "user" || s.source === "user-agents").length;
65529
65621
  const projectCount = host.skills.filter((s) => s.source === "project" || s.source === "project-agents").length;
@@ -65556,6 +65648,77 @@ function collectKnownToolNames(host) {
65556
65648
  const disabled = disabledNames.filter((name) => !liveNames.includes(name));
65557
65649
  return { active: [...liveNames].sort(), disabled: [...disabled].sort() };
65558
65650
  }
65651
+ function describeToggleEffect(host, name, enabled) {
65652
+ const loaded = collectKnownToolNames(host).active.includes(name);
65653
+ if (enabled) {
65654
+ return loaded ? `Tool "${name}" enabled (active now).` : `Tool "${name}" enabled in ~/.pie/settings.json (loads on next start \u2014 it was not loaded this session).`;
65655
+ }
65656
+ return loaded ? `Tool "${name}" disabled (removed from this session).` : `Tool "${name}" disabled in ~/.pie/settings.json.`;
65657
+ }
65658
+ function showToolsManager(host) {
65659
+ host.showSelector((done) => {
65660
+ const { active, disabled } = collectKnownToolNames(host);
65661
+ const settingsManager = host.options.settingsManager;
65662
+ const lastPersisted = /* @__PURE__ */ new Map();
65663
+ const items = [
65664
+ ...active.map((name) => ({
65665
+ id: `tool:${name}`,
65666
+ label: name,
65667
+ description: "Runtime agent tool",
65668
+ currentValue: settingsManager.isToolEnabled(name) ? "on" : "off",
65669
+ values: ["on", "off"]
65670
+ })),
65671
+ ...disabled.map((name) => ({
65672
+ id: `tool:${name}`,
65673
+ label: name,
65674
+ description: "Not loaded this session (starts enabled next launch)",
65675
+ currentValue: "off",
65676
+ values: ["on", "off"]
65677
+ }))
65678
+ ];
65679
+ for (const item of items) lastPersisted.set(item.id, item.currentValue);
65680
+ const settingsList = new SettingsList(
65681
+ items,
65682
+ 14,
65683
+ getSettingsListTheme(),
65684
+ (id, newValue) => {
65685
+ const name = id.slice("tool:".length);
65686
+ const enabled = newValue === "on";
65687
+ const previous = lastPersisted.get(id) ?? "off";
65688
+ try {
65689
+ settingsManager.setToolEnabled(name, enabled);
65690
+ } catch (error) {
65691
+ settingsList.updateValue(id, previous);
65692
+ host.showError(`Failed to update tool "${name}": ${errorMessage3(error)}`);
65693
+ return;
65694
+ }
65695
+ lastPersisted.set(id, newValue);
65696
+ host.applyRuntimeToolMode();
65697
+ host.showStatus(describeToggleEffect(host, name, enabled));
65698
+ },
65699
+ () => done(),
65700
+ { enableSearch: true }
65701
+ );
65702
+ const component = {
65703
+ render: (width) => [
65704
+ ...renderHeader(width),
65705
+ ...settingsList.render(width)
65706
+ ],
65707
+ handleInput: (data) => settingsList.handleInput(data),
65708
+ invalidate: () => settingsList.invalidate()
65709
+ };
65710
+ return { component, focus: settingsList };
65711
+ });
65712
+ }
65713
+ function renderHeader(width) {
65714
+ const lines = [];
65715
+ lines.push(theme.bold(theme.fg("accent", "Tools")));
65716
+ lines.push("");
65717
+ lines.push(theme.fg("muted", "Enter/Space toggles \xB7 live tools apply immediately \xB7 Esc to close"));
65718
+ const hint = "Usage: /tools/enable <name> | /tools/disable <name>";
65719
+ if (width > 20) lines.push(theme.fg("dim", hint));
65720
+ return lines;
65721
+ }
65559
65722
  function handleToolsCommand(host, args) {
65560
65723
  const parts = args.trim().split(/\s+/).filter(Boolean);
65561
65724
  const subcommand = parts[0];
@@ -65565,8 +65728,8 @@ function handleToolsCommand(host, args) {
65565
65728
  host.showError(`Usage: /tools ${subcommand} <tool-name>`);
65566
65729
  return;
65567
65730
  }
65568
- const { active: active2, disabled: disabled2 } = collectKnownToolNames(host);
65569
- if (!active2.includes(name) && !disabled2.includes(name)) {
65731
+ const { active, disabled } = collectKnownToolNames(host);
65732
+ if (!active.includes(name) && !disabled.includes(name)) {
65570
65733
  host.showError(`Tool not found: ${name}. Use /tools to list tool names.`);
65571
65734
  return;
65572
65735
  }
@@ -65577,38 +65740,42 @@ function handleToolsCommand(host, args) {
65577
65740
  host.showError(`Failed to update tool "${name}": ${errorMessage3(error)}`);
65578
65741
  return;
65579
65742
  }
65743
+ host.applyRuntimeToolMode();
65580
65744
  host.chatContainer.addChild(new Spacer(1));
65581
65745
  host.chatContainer.addChild(new Text(
65582
- theme.fg("accent", `Tool "${name}" ${enabled ? "enabled" : "disabled"} in ~/.pie/settings.json. Takes effect on next start.`),
65746
+ theme.fg("accent", describeToggleEffect(host, name, enabled)),
65583
65747
  1,
65584
65748
  0
65585
65749
  ));
65586
65750
  host.ui.requestRender();
65587
65751
  return;
65588
65752
  }
65589
- if (subcommand) {
65590
- host.showError("Usage: /tools [enable|disable <tool-name>]");
65753
+ if (subcommand === "list") {
65754
+ const { active, disabled } = collectKnownToolNames(host);
65755
+ host.chatContainer.addChild(new Spacer(1));
65756
+ host.chatContainer.addChild(new Text(theme.bold("Tools"), 1, 0));
65757
+ if (active.length === 0 && disabled.length === 0) {
65758
+ host.chatContainer.addChild(new Text(theme.fg("dim", " No tools available."), 1, 0));
65759
+ }
65760
+ for (const name of active) {
65761
+ const state = host.options.settingsManager.isToolEnabled(name) ? "enabled" : "disabled (removed from this session)";
65762
+ host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: ${state}`), 1, 0));
65763
+ }
65764
+ for (const name of disabled) {
65765
+ host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: disabled (/tools/enable ${name})`), 1, 0));
65766
+ }
65767
+ host.ui.requestRender();
65591
65768
  return;
65592
65769
  }
65593
- const { active, disabled } = collectKnownToolNames(host);
65594
- host.chatContainer.addChild(new Spacer(1));
65595
- host.chatContainer.addChild(new Text(theme.bold("Tools"), 1, 0));
65596
- if (active.length === 0 && disabled.length === 0) {
65597
- host.chatContainer.addChild(new Text(theme.fg("dim", " No tools available."), 1, 0));
65598
- }
65599
- for (const name of active) {
65600
- host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: enabled`), 1, 0));
65601
- }
65602
- for (const name of disabled) {
65603
- host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: disabled (/tools/enable ${name})`), 1, 0));
65770
+ if (subcommand) {
65771
+ host.showError("Usage: /tools [list | enable|disable <tool-name>]");
65772
+ return;
65604
65773
  }
65605
- host.chatContainer.addChild(new Spacer(1));
65606
- host.chatContainer.addChild(new Text(theme.fg("dim", "Usage: /tools/enable <name> | /tools/disable <name> (takes effect on next start)"), 1, 0));
65607
- host.ui.requestRender();
65774
+ showToolsManager(host);
65608
65775
  }
65609
65776
 
65610
65777
  // src/commands/interactive-command-handlers.ts
65611
- function showSettingsSelector(host) {
65778
+ function showSettingsSelector(host, focusItem) {
65612
65779
  host.showSelector((done) => {
65613
65780
  const currentModelId = host.options.model?.id || "unknown";
65614
65781
  const currentProvider = host.options.model?.provider || "unknown";
@@ -65624,7 +65791,8 @@ function showSettingsSelector(host) {
65624
65791
  yoloMode: host.yoloMode,
65625
65792
  calmMode: host.calmMode,
65626
65793
  notificationsBell: host.options.settingsManager.getBellNotificationsEnabled(),
65627
- notificationsDesktop: host.options.settingsManager.getDesktopNotificationsEnabled()
65794
+ notificationsDesktop: host.options.settingsManager.getDesktopNotificationsEnabled(),
65795
+ focusItem
65628
65796
  },
65629
65797
  {
65630
65798
  onThinkingLevelChange: (level) => {
@@ -66012,7 +66180,19 @@ async function handleClearCommand(host) {
66012
66180
  host.syncSessionModelMetadata();
66013
66181
  host.planModeEnabled = false;
66014
66182
  host.pendingPlanModeTransition = null;
66015
- host.footer.setState({ planMode: false });
66183
+ const contextUsage = host.calculateContextUsage();
66184
+ const contextWindow = host.options.model?.contextWindow ?? 0;
66185
+ host.footer.setState({
66186
+ planMode: false,
66187
+ status: "ready",
66188
+ inputTokens: contextUsage.input,
66189
+ outputTokens: contextUsage.output,
66190
+ cacheRead: contextUsage.cacheRead,
66191
+ cacheWrite: contextUsage.cacheWrite,
66192
+ cost: contextUsage.cost,
66193
+ contextPercent: contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0,
66194
+ contextWindow
66195
+ });
66016
66196
  host.updateTerminalTitle();
66017
66197
  host.chatContainer.clear();
66018
66198
  host.streamingComponent = void 0;
@@ -66193,7 +66373,7 @@ function registerBuiltinCommands(host) {
66193
66373
  });
66194
66374
  commandTree.register(["settings", "theme"], {
66195
66375
  description: "Change theme",
66196
- handler: () => host.showSettingsSelector()
66376
+ handler: () => host.showSettingsSelector("theme")
66197
66377
  });
66198
66378
  commandTree.register(["settings", "thinking"], {
66199
66379
  description: "Set thinking level (off/minimal/low/medium/high/xhigh)",
@@ -66223,14 +66403,22 @@ function registerBuiltinCommands(host) {
66223
66403
  description: "Disable an extension by identity (writes settings)",
66224
66404
  handler: (_2, args) => host.handleExtensionsCommand(`disable ${args || ""}`)
66225
66405
  });
66226
- commandTree.register(["skills", "list"], {
66227
- description: "List available skills",
66406
+ commandTree.register(["skills"], {
66407
+ description: "Manage skills: list, toggle enable/disable, invoke",
66228
66408
  handler: () => host.handleSkillsCommand()
66229
66409
  });
66410
+ commandTree.register(["skills", "list"], {
66411
+ description: "List available skills (plain text)",
66412
+ handler: () => host.handleSkillsListCommand()
66413
+ });
66230
66414
  commandTree.register(["skills", "use"], {
66231
66415
  description: "Use a skill",
66232
66416
  handler: (_2, args) => host.handleSkillCommand(args || "")
66233
66417
  });
66418
+ commandTree.register(["skills", "create"], {
66419
+ description: "Create a new skill from a template",
66420
+ handler: (_2, args) => host.handleSkillsCreate(args || "")
66421
+ });
66234
66422
  commandTree.register(["skills", "reload"], {
66235
66423
  description: "Reload skills from disk",
66236
66424
  handler: async () => {
@@ -66259,12 +66447,16 @@ function registerBuiltinCommands(host) {
66259
66447
  description: "List runtime tools and manage enable/disable toggles",
66260
66448
  handler: (_2, args) => host.handleToolsCommand(args || "")
66261
66449
  });
66450
+ commandTree.register(["tools", "list"], {
66451
+ description: "List runtime tools and their state (plain text)",
66452
+ handler: (_2, args) => host.handleToolsCommand(args ? `list ${args}` : "list")
66453
+ });
66262
66454
  commandTree.register(["tools", "enable"], {
66263
- description: "Enable a tool by name (writes settings; next start)",
66455
+ description: "Enable a tool by name (writes settings; live tools apply now)",
66264
66456
  handler: (_2, args) => host.handleToolsCommand(`enable ${args || ""}`)
66265
66457
  });
66266
66458
  commandTree.register(["tools", "disable"], {
66267
- description: "Disable a tool by name (writes settings; next start)",
66459
+ description: "Disable a tool by name (writes settings; applies now)",
66268
66460
  handler: (_2, args) => host.handleToolsCommand(`disable ${args || ""}`)
66269
66461
  });
66270
66462
  commandTree.register(["debugs", "cache-test"], {
@@ -66422,6 +66614,7 @@ function ringTerminalBell(options = {}) {
66422
66614
  function ringTurnSettledBell(host) {
66423
66615
  if ((host.agentSessionController?.pendingMessageCount ?? 0) > 0) return;
66424
66616
  if (host.executionState.read().awaitingContinuation) return;
66617
+ if (host.peekTodoAutoContinuePrompt?.()) return;
66425
66618
  host.ringAttentionBell?.("turn-settled");
66426
66619
  }
66427
66620
  function attentionMessage(reason) {
@@ -70064,12 +70257,19 @@ function clearContinuationTimeout(host, reason) {
70064
70257
  function isWaitingForUserInteraction(host) {
70065
70258
  return host.activeInteractionCount > 0;
70066
70259
  }
70260
+ function peekTodoAutoContinuePrompt(host) {
70261
+ if (isWaitingForUserInteraction(host)) return void 0;
70262
+ if (host.submitLock || host.isProcessing || host.isInterrupting || host.isCompacting) return void 0;
70263
+ const hasTodoTool = (host.agent?.state?.tools ?? []).some((tool) => tool.name === "manage_todo_list");
70264
+ if (!hasTodoTool) return void 0;
70265
+ return host.executionState.takeTodoClosureFollowUp() || void 0;
70266
+ }
70067
70267
  function getTodoAutoContinueMessage(host) {
70268
+ const prompt = peekTodoAutoContinuePrompt(host);
70068
70269
  if (isWaitingForUserInteraction(host)) return { reason: "waiting_for_user_interaction" };
70069
70270
  if (host.submitLock || host.isProcessing || host.isInterrupting || host.isCompacting) return { reason: "host_busy" };
70070
70271
  const hasTodoTool = (host.agent?.state?.tools ?? []).some((tool) => tool.name === "manage_todo_list");
70071
70272
  if (!hasTodoTool) return { reason: "todo_tool_unavailable" };
70072
- const prompt = host.executionState.takeTodoClosureFollowUp();
70073
70273
  if (!prompt) return { reason: "no_active_todo_follow_up" };
70074
70274
  host.logDebug("todo_closure:follow_up", {
70075
70275
  textPreview: prompt.slice(0, 120),
@@ -71106,11 +71306,14 @@ async function restoreExtensionProviderCredentials(modelRegistry) {
71106
71306
  }
71107
71307
 
71108
71308
  // src/attachments/resolver.ts
71309
+ var PROVIDER_SOURCE = "(provider)";
71109
71310
  var AttachmentResolver = class {
71110
- constructor(extensions) {
71311
+ constructor(extensions, builtInHandlers = []) {
71111
71312
  this.extensions = extensions;
71313
+ this.builtInHandlers = builtInHandlers;
71112
71314
  }
71113
71315
  extensions;
71316
+ builtInHandlers;
71114
71317
  findHandler(model, attachment) {
71115
71318
  const candidate = this.collectCandidates(model, attachment)[0];
71116
71319
  if (!candidate) return void 0;
@@ -71135,6 +71338,15 @@ var AttachmentResolver = class {
71135
71338
  }
71136
71339
  collectCandidates(model, attachment) {
71137
71340
  const matches = [];
71341
+ for (const handler of this.builtInHandlers) {
71342
+ if (!handler.matches(model, attachment)) continue;
71343
+ matches.push({
71344
+ handlerName: handler.name,
71345
+ extensionPath: PROVIDER_SOURCE,
71346
+ priority: handler.priority ?? 0,
71347
+ prepare: handler.prepare.bind(handler)
71348
+ });
71349
+ }
71138
71350
  for (const extension of this.extensions) {
71139
71351
  for (const handler of extension.attachmentHandlers.values()) {
71140
71352
  if (!handler.matches(model, attachment)) continue;
@@ -71157,6 +71369,48 @@ var AttachmentResolver = class {
71157
71369
  }
71158
71370
  };
71159
71371
 
71372
+ // src/attachments/provider-handlers.ts
71373
+ function getModality(mimeType) {
71374
+ if (mimeType.startsWith("image/")) return "image";
71375
+ if (mimeType.startsWith("video/")) return "video";
71376
+ return "file";
71377
+ }
71378
+ function isKimiAttachmentPlatform(model) {
71379
+ return model.attachmentPlatform === "kimi" || model.filePlatform === "kimi";
71380
+ }
71381
+ var kimiNativeAttachmentHandler = {
71382
+ name: "kimi-native-attachments",
71383
+ priority: 100,
71384
+ matches(model, attachment) {
71385
+ return isKimiAttachmentPlatform(model) && Boolean(attachment.fileId) && getModality(attachment.mimeType) !== "file";
71386
+ },
71387
+ async prepare(_model, attachment, ctx) {
71388
+ const fileId = attachment.fileId;
71389
+ if (!fileId) {
71390
+ return {
71391
+ items: [{ type: "text", text: `[${attachment.id}]` }],
71392
+ warnings: ["\u9644\u4EF6\u7F3A\u5C11 fileId\uFF0C\u65E0\u6CD5\u8D70 Kimi \u539F\u751F\u5F15\u7528"]
71393
+ };
71394
+ }
71395
+ const modality = getModality(attachment.mimeType);
71396
+ const url = `ms://${fileId}`;
71397
+ ctx.log(`Kimi handler prepared ${modality} reference for ${attachment.id}`);
71398
+ return {
71399
+ items: [
71400
+ {
71401
+ type: "file-ref",
71402
+ mimeType: attachment.mimeType,
71403
+ url,
71404
+ modality
71405
+ }
71406
+ ]
71407
+ };
71408
+ }
71409
+ };
71410
+ var providerAttachmentHandlers = [
71411
+ kimiNativeAttachmentHandler
71412
+ ];
71413
+
71160
71414
  // src/app/runtime-composition-pipeline.ts
71161
71415
  var CLI_COMPOSITION_STEP_ORDER = [
71162
71416
  "model_config",
@@ -71307,7 +71561,7 @@ async function loadInteractiveExtensions(host) {
71307
71561
  buildExtensionLoadOptions(host.options.settingsManager, host.options.extensionFlags)
71308
71562
  );
71309
71563
  host.extensions = extensions;
71310
- host.attachmentResolver = new AttachmentResolver(extensions);
71564
+ host.attachmentResolver = new AttachmentResolver(extensions, providerAttachmentHandlers);
71311
71565
  host.extensionRunner = new ExtensionRunner(
71312
71566
  extensions,
71313
71567
  extensionActions,
@@ -71479,6 +71733,10 @@ var InteractiveMode = class {
71479
71733
  getTodoAutoContinueMessage() {
71480
71734
  return getTodoAutoContinueMessage(this.continuationHost);
71481
71735
  }
71736
+ /** Side-effect-free todo auto-continue prediction for the turn-settled bell. */
71737
+ peekTodoAutoContinuePrompt() {
71738
+ return peekTodoAutoContinuePrompt(this.continuationHost);
71739
+ }
71482
71740
  appendWarningSummary(message) {
71483
71741
  return appendWarningSummary(this.continuationHost, message);
71484
71742
  }
@@ -71635,9 +71893,12 @@ var InteractiveMode = class {
71635
71893
  const rebuilt = this.rebuildSkillAwareTools(completeToolSet);
71636
71894
  const currentTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.currentTools, this.extensionRunner) : rebuilt.currentTools;
71637
71895
  const originalTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.originalTools, this.extensionRunner) : rebuilt.originalTools;
71638
- const activeTools = selectToolsForRuntimeMode(
71639
- currentTools,
71640
- this.planModeEnabled ? "plan" : "normal"
71896
+ const activeTools = filterEnabledTools(
71897
+ selectToolsForRuntimeMode(
71898
+ currentTools,
71899
+ this.planModeEnabled ? "plan" : "normal"
71900
+ ),
71901
+ this.options.settingsManager
71641
71902
  );
71642
71903
  this.agent.setTools(activeTools);
71643
71904
  this.allTools = [...currentTools];
@@ -71648,7 +71909,8 @@ var InteractiveMode = class {
71648
71909
  planMode: this.planModeEnabled ? "planning" : "off",
71649
71910
  filesystemScope: this.yoloMode ? "all" : "workspace",
71650
71911
  toolCount: activeTools.length,
71651
- availableToolCount: currentTools.length
71912
+ availableToolCount: currentTools.length,
71913
+ disabledToolCount: this.options.settingsManager.getDisabledTools().length
71652
71914
  });
71653
71915
  }
71654
71916
  noteRuntimeModeChanged(trigger) {
@@ -71901,8 +72163,8 @@ var InteractiveMode = class {
71901
72163
  async selectMentionOption(option) {
71902
72164
  return selectMentionOption(this.filePipelineHost, option);
71903
72165
  }
71904
- showSettingsSelector() {
71905
- return showSettingsSelector(this);
72166
+ showSettingsSelector(focusItem) {
72167
+ return showSettingsSelector(this, focusItem);
71906
72168
  }
71907
72169
  async handleModelCommand(searchTerm) {
71908
72170
  return handleModelCommand(this, searchTerm);
@@ -72013,6 +72275,9 @@ var InteractiveMode = class {
72013
72275
  handleSkillsCommand() {
72014
72276
  return handleSkillsCommand(this);
72015
72277
  }
72278
+ handleSkillsListCommand() {
72279
+ return handleSkillsListCommand(this);
72280
+ }
72016
72281
  handleSkillCommand(name) {
72017
72282
  return handleSkillCommand(this, name);
72018
72283
  }