@selesai/code 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/cli/startup-ui.js +2 -1
  3. package/dist/core/agent-session.d.ts +12 -1
  4. package/dist/core/agent-session.js +77 -9
  5. package/dist/core/compaction/branch-summarization.js +4 -3
  6. package/dist/core/compaction/compaction.d.ts +5 -0
  7. package/dist/core/compaction/compaction.js +19 -4
  8. package/dist/core/extensions/index.d.ts +1 -1
  9. package/dist/core/extensions/runner.d.ts +5 -0
  10. package/dist/core/extensions/runner.js +48 -1
  11. package/dist/core/extensions/types.d.ts +18 -1
  12. package/dist/core/llama/client.d.ts +6 -0
  13. package/dist/core/llama/client.js +7 -0
  14. package/dist/core/llama/provider.d.ts +3 -1
  15. package/dist/core/llama/provider.js +28 -6
  16. package/dist/core/session-manager.js +4 -2
  17. package/dist/core/settings-manager.d.ts +8 -1
  18. package/dist/core/settings-manager.js +17 -0
  19. package/dist/core/usage-totals.d.ts +2 -0
  20. package/dist/core/usage-totals.js +10 -0
  21. package/dist/defaults/models.json +32 -9
  22. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +2 -1
  23. package/dist/extensions/pi-zentui/test/format.test.ts +15 -1
  24. package/dist/extensions/tokenin-onboarding.ts +112 -2
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +1 -0
  27. package/dist/main.js +2 -0
  28. package/dist/modes/interactive/components/footer.js +2 -2
  29. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  30. package/dist/modes/interactive/components/settings-selector.js +10 -0
  31. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  32. package/dist/modes/interactive/interactive-mode.js +59 -43
  33. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  34. package/dist/modes/rpc/rpc-client.js +7 -0
  35. package/dist/modes/rpc/rpc-mode.js +3 -0
  36. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  37. package/dist/utils/shell.js +6 -4
  38. package/docs/settings.md +4 -0
  39. package/package.json +4 -4
@@ -6,7 +6,7 @@ import * as fs from "node:fs";
6
6
  import * as os from "node:os";
7
7
  import * as path from "node:path";
8
8
  import * as TuiLayouts from "@earendil-works/pi-tui";
9
- import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
9
+ import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
10
10
  import chalk from "chalk";
11
11
  import { spawn, spawnSync } from "child_process";
12
12
  import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getBundledDefaultsDir, getDebugLogPath, getDocsPath, getShareViewerUrl, getUpdateInstruction, PACKAGE_NAME, VERSION, } from "../../config.js";
@@ -25,7 +25,7 @@ import { buildGitCommandPrompt, GIT_COMMAND_MODES } from "../../core/git-command
25
25
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
26
26
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
27
27
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
28
- import { getUsageCostBreakdown } from "../../core/usage-totals.js";
28
+ import { formatCost, getUsageCostBreakdown } from "../../core/usage-totals.js";
29
29
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
30
30
  import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
31
31
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
@@ -199,6 +199,7 @@ export function createInteractiveTui(options) {
199
199
  searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
200
200
  openUrl: openBrowser,
201
201
  onRightClickPaste: options.onRightClickPaste,
202
+ copyOnSelect: options.fullscreenCopyOnSelect,
202
203
  copySelection: async (text) => {
203
204
  try {
204
205
  await copyToClipboard(text);
@@ -359,6 +360,7 @@ export class InteractiveMode {
359
360
  }
360
361
  constructor(runtimeHost, options = {}) {
361
362
  this.runtimeHost = runtimeHost;
363
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
362
364
  const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
363
365
  this.options = { ...options, tuiMode };
364
366
  this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
@@ -374,6 +376,7 @@ export class InteractiveMode {
374
376
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
375
377
  logDirectory: getAgentDir(),
376
378
  onRightClickPaste: this.onRightClickPaste,
379
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
377
380
  });
378
381
  this.ui = createInteractiveTuiReference(() => this.renderer);
379
382
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
@@ -610,6 +613,7 @@ export class InteractiveMode {
610
613
  logDirectory: getAgentDir(),
611
614
  terminal,
612
615
  onRightClickPaste: this.onRightClickPaste,
616
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
613
617
  });
614
618
  nextUi.setClearOnShrink(clearOnShrink);
615
619
  nextUi.onDebug = onDebug;
@@ -1424,7 +1428,11 @@ export class InteractiveMode {
1424
1428
  this.showStartupNoticesIfNeeded();
1425
1429
  }
1426
1430
  applyRuntimeSettings() {
1431
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
1427
1432
  configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
1433
+ if (this.renderer instanceof TuiAltScreen) {
1434
+ this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1435
+ }
1428
1436
  this.footer.setSession(this.session);
1429
1437
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
1430
1438
  this.footerDataProvider.setCwd(this.sessionManager.getCwd());
@@ -1571,6 +1579,9 @@ export class InteractiveMode {
1571
1579
  this.statusContainer.addChild(this.idleStatus);
1572
1580
  }
1573
1581
  }
1582
+ showWorkingStatusIndicator() {
1583
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1584
+ }
1574
1585
  setWorkingVisible(visible) {
1575
1586
  this.workingVisible = visible;
1576
1587
  if (!visible) {
@@ -1579,7 +1590,7 @@ export class InteractiveMode {
1579
1590
  return;
1580
1591
  }
1581
1592
  if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
1582
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1593
+ this.showWorkingStatusIndicator();
1583
1594
  }
1584
1595
  this.ui.requestRender();
1585
1596
  }
@@ -2191,7 +2202,7 @@ export class InteractiveMode {
2191
2202
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2192
2203
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2193
2204
  this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
2194
- this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
2205
+ this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
2195
2206
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2196
2207
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2197
2208
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
@@ -2510,17 +2521,21 @@ export class InteractiveMode {
2510
2521
  switch (event.type) {
2511
2522
  case "agent_start":
2512
2523
  this.pendingTools.clear();
2513
- if (this.settingsManager.getShowTerminalProgress()) {
2514
- this.ui.terminal.setProgress(true);
2515
- }
2516
2524
  // Restore main escape handler if retry handler is still active
2517
2525
  // (retry success event fires later, but we need main handler now)
2518
2526
  if (this.retryEscapeHandler) {
2519
2527
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2520
2528
  this.retryEscapeHandler = undefined;
2521
2529
  }
2530
+ break;
2531
+ case "turn_start":
2532
+ if (this.settingsManager.getShowTerminalProgress()) {
2533
+ this.ui.terminal.setProgress(true);
2534
+ }
2522
2535
  if (this.workingVisible) {
2523
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
2536
+ if (this.activeStatusIndicator?.kind !== "working") {
2537
+ this.showWorkingStatusIndicator();
2538
+ }
2524
2539
  }
2525
2540
  else {
2526
2541
  this.clearStatusIndicator();
@@ -3372,18 +3387,19 @@ export class InteractiveMode {
3372
3387
  }
3373
3388
  this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
3374
3389
  }
3390
+ /** Update rendered assistant messages without rebuilding live tool components. */
3391
+ updateThinkingBlockVisibility() {
3392
+ for (const child of this.chatContainer.children) {
3393
+ if (child instanceof AssistantMessageComponent) {
3394
+ child.setHideThinkingBlock(this.hideThinkingBlock);
3395
+ }
3396
+ }
3397
+ this.ui.requestRender();
3398
+ }
3375
3399
  toggleThinkingBlockVisibility() {
3376
3400
  this.hideThinkingBlock = !this.hideThinkingBlock;
3377
3401
  this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
3378
- // Rebuild chat from session messages
3379
- this.chatContainer.clear();
3380
- this.rebuildChatFromMessages();
3381
- // If streaming, re-add the streaming component with updated visibility and re-render
3382
- if (this.streamingComponent && this.streamingMessage) {
3383
- this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
3384
- this.streamingComponent.updateContent(this.streamingMessage);
3385
- this.chatContainer.addChild(this.streamingComponent);
3386
- }
3402
+ this.updateThinkingBlockVisibility();
3387
3403
  this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
3388
3404
  }
3389
3405
  async handleOpenExternalEditor() {
@@ -3680,6 +3696,7 @@ export class InteractiveMode {
3680
3696
  tuiMode: this.settingsManager.getTuiMode(),
3681
3697
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3682
3698
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
3699
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
3683
3700
  warnings: this.settingsManager.getWarnings(),
3684
3701
  skills: this.buildSkillToggleItems(),
3685
3702
  }, {
@@ -3751,13 +3768,7 @@ export class InteractiveMode {
3751
3768
  onHideThinkingBlockChange: (hidden) => {
3752
3769
  this.hideThinkingBlock = hidden;
3753
3770
  this.settingsManager.setHideThinkingBlock(hidden);
3754
- for (const child of this.chatContainer.children) {
3755
- if (child instanceof AssistantMessageComponent) {
3756
- child.setHideThinkingBlock(hidden);
3757
- }
3758
- }
3759
- this.chatContainer.clear();
3760
- this.rebuildChatFromMessages();
3771
+ this.updateThinkingBlockVisibility();
3761
3772
  },
3762
3773
  onShowCacheMissNoticesChange: (shown) => {
3763
3774
  this.settingsManager.setShowCacheMissNotices(shown);
@@ -3847,6 +3858,11 @@ export class InteractiveMode {
3847
3858
  this.transcriptScrollView?.setScrollbar(mode);
3848
3859
  this.ui.requestRender();
3849
3860
  },
3861
+ onFullscreenCopyOnSelectChange: (enabled) => {
3862
+ this.settingsManager.setFullscreenCopyOnSelect(enabled);
3863
+ if (this.renderer instanceof TuiAltScreen)
3864
+ this.renderer.setCopyOnSelect(enabled);
3865
+ },
3850
3866
  onWarningsChange: (warnings) => {
3851
3867
  this.settingsManager.setWarnings(warnings);
3852
3868
  },
@@ -4057,6 +4073,7 @@ export class InteractiveMode {
4057
4073
  return;
4058
4074
  try {
4059
4075
  await this.session.setModel(model);
4076
+ this.updateAvailableProviderCount();
4060
4077
  this.footer.invalidate();
4061
4078
  this.updateEditorBorderColor();
4062
4079
  done();
@@ -4870,21 +4887,8 @@ export class InteractiveMode {
4870
4887
  activeHeader.setExpanded(this.toolOutputExpanded);
4871
4888
  }
4872
4889
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
4890
+ this.applyRuntimeSettings();
4873
4891
  await this.themeController.applyFromSettings();
4874
- const editorPaddingX = this.settingsManager.getEditorPaddingX();
4875
- const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
4876
- this.defaultEditor.setPaddingX(editorPaddingX);
4877
- this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
4878
- if (this.editor !== this.defaultEditor) {
4879
- this.editor.setPaddingX?.(editorPaddingX);
4880
- this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
4881
- }
4882
- this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
4883
- const clearOnShrink = this.settingsManager.getClearOnShrink();
4884
- this.ui.setClearOnShrink(clearOnShrink);
4885
- if (!clearOnShrink && !this.activeStatusIndicator) {
4886
- this.statusContainer.clear();
4887
- }
4888
4892
  this.setupAutocompleteProvider();
4889
4893
  const runner = this.session.extensionRunner;
4890
4894
  this.setupExtensionShortcuts(runner);
@@ -5082,7 +5086,14 @@ export class InteractiveMode {
5082
5086
  }
5083
5087
  }
5084
5088
  }
5085
- async handleCopyCommand() {
5089
+ async handleCopyCommand(options = {}) {
5090
+ if (options.preferSelection &&
5091
+ this.ui instanceof TuiAltScreen &&
5092
+ !this.ui.getCopyOnSelect() &&
5093
+ this.ui.hasActiveSelection()) {
5094
+ await this.ui.copyActiveSelectionToClipboard();
5095
+ return;
5096
+ }
5086
5097
  const text = this.session.getLastAssistantText();
5087
5098
  if (!text) {
5088
5099
  this.showError("No agent messages to copy yet.");
@@ -5090,7 +5101,12 @@ export class InteractiveMode {
5090
5101
  }
5091
5102
  try {
5092
5103
  await copyToClipboard(text);
5093
- this.showStatus("Copied last agent message to clipboard");
5104
+ if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
5105
+ this.ui.flash("Copied!");
5106
+ }
5107
+ else {
5108
+ this.showStatus("Copied last agent message to clipboard");
5109
+ }
5094
5110
  }
5095
5111
  catch (error) {
5096
5112
  this.showError(error instanceof Error ? error.message : String(error));
@@ -5157,10 +5173,10 @@ export class InteractiveMode {
5157
5173
  info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
5158
5174
  if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
5159
5175
  info += `\n${theme.bold("Cost")}\n`;
5160
- info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
5176
+ info += `${theme.fg("dim", "Total:")} ${formatCost(stats.cost)}`;
5161
5177
  if (usageBreakdown.length > 1) {
5162
5178
  for (const entry of usageBreakdown) {
5163
- info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5179
+ info += `\n ${theme.fg("dim", `${entry.key}:`)} ${formatCost(entry.cost)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5164
5180
  }
5165
5181
  }
5166
5182
  if (cacheWaste.missedTokens > 0) {
@@ -5168,7 +5184,7 @@ export class InteractiveMode {
5168
5184
  const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
5169
5185
  info +=
5170
5186
  cacheWaste.missedCost >= 0.0001
5171
- ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
5187
+ ? `\n${theme.fg("dim", "Cache Re-billed:")} ${formatCost(cacheWaste.missedCost)} ${theme.fg("dim", `(${detail})`)}`
5172
5188
  : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
5173
5189
  }
5174
5190
  }
@@ -75,6 +75,13 @@ export declare class RpcClient {
75
75
  * Abort current operation.
76
76
  */
77
77
  abort(): Promise<void>;
78
+ /**
79
+ * Clear queued steering and follow-up messages, returning their text.
80
+ */
81
+ clearQueue(): Promise<{
82
+ steering: string[];
83
+ followUp: string[];
84
+ }>;
78
85
  /**
79
86
  * Start a new session, optionally with parent tracking.
80
87
  * @param parentSession - Optional parent session path for lineage tracking
@@ -153,6 +153,13 @@ export class RpcClient {
153
153
  async abort() {
154
154
  await this.send({ type: "abort" });
155
155
  }
156
+ /**
157
+ * Clear queued steering and follow-up messages, returning their text.
158
+ */
159
+ async clearQueue() {
160
+ const response = await this.send({ type: "clear_queue" });
161
+ return this.getData(response);
162
+ }
156
163
  /**
157
164
  * Start a new session, optionally with parent tracking.
158
165
  * @param parentSession - Optional parent session path for lineage tracking
@@ -331,6 +331,9 @@ export async function runRpcMode(runtimeHost) {
331
331
  await session.abort();
332
332
  return success(id, "abort");
333
333
  }
334
+ case "clear_queue": {
335
+ return success(id, "clear_queue", session.clearQueue());
336
+ }
334
337
  case "new_session": {
335
338
  const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
336
339
  const result = await runtimeHost.newSession(options);
@@ -30,6 +30,9 @@ export type RpcCommand = {
30
30
  } | {
31
31
  id?: string;
32
32
  type: "abort";
33
+ } | {
34
+ id?: string;
35
+ type: "clear_queue";
33
36
  } | {
34
37
  id?: string;
35
38
  type: "new_session";
@@ -206,6 +209,15 @@ export type RpcResponse = {
206
209
  type: "response";
207
210
  command: "abort";
208
211
  success: true;
212
+ } | {
213
+ id?: string;
214
+ type: "response";
215
+ command: "clear_queue";
216
+ success: true;
217
+ data: {
218
+ steering: string[];
219
+ followUp: string[];
220
+ };
209
221
  } | {
210
222
  id?: string;
211
223
  type: "response";
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import { delimiter } from "node:path";
2
+ import { delimiter, join } from "node:path";
3
3
  import { spawn, spawnSync } from "child_process";
4
4
  import { getBinDir } from "../config.js";
5
5
  /**
@@ -183,16 +183,18 @@ export function killTrackedDetachedChildren() {
183
183
  */
184
184
  export function killProcessTree(pid) {
185
185
  if (process.platform === "win32") {
186
- // Use taskkill on Windows to kill process tree
186
+ // Use the trusted System32 executable so cleanup does not depend on PATH.
187
187
  try {
188
- spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
188
+ const child = spawn(join(process.env.SystemRoot ?? "C:\\Windows", "System32", "taskkill.exe"), ["/F", "/T", "/PID", String(pid)], {
189
189
  stdio: "ignore",
190
190
  detached: true,
191
191
  windowsHide: true,
192
192
  });
193
+ // A failed spawn emits "error" asynchronously; consume it to avoid crashing Node.
194
+ child.once("error", () => { });
193
195
  }
194
196
  catch {
195
- // Ignore errors if taskkill fails
197
+ // Ignore errors if taskkill fails.
196
198
  }
197
199
  }
198
200
  else {
package/docs/settings.md CHANGED
@@ -64,6 +64,7 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
64
64
  | `showHardwareCursor` | boolean | `false` | Show the terminal cursor while TUI positions it for IME support |
65
65
  | `tuiMode` | string | `"fullscreen"` | TUI layout: `"fullscreen"` (default) or `"regular"`. `fullscreen` uses Pi's native alternate-screen viewport with a fixed dock for the input editor, status, and widgets; set `"regular"` to opt out |
66
66
  | `fullscreenScrollbar` | string | `"auto"` | Fullscreen transcript scrollbar: `"auto"`, `"always"`, or `"hidden"`; configurable in `/settings`. No effect in regular TUI mode |
67
+ | `fullscreenCopyOnSelect` | boolean | `true` | Automatically copy selected text in fullscreen mode; disable to copy selections with Ctrl+X. Configurable in `/settings`. No effect in regular TUI mode |
67
68
 
68
69
  ### Telemetry and update checks
69
70
 
@@ -169,6 +170,9 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
169
170
  | `terminal.showImages` | boolean | `true` | Show images in terminal (if supported) |
170
171
  | `terminal.imageWidthCells` | number | `60` | Preferred inline image width in terminal cells |
171
172
  | `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) |
173
+ | `terminal.images` | string | `"auto"` | Terminal image protocol: `"kitty"`, `"iterm2"`, `"auto"`, or `false` to disable inline images |
174
+ | `terminal.trueColor` | boolean/string | `"auto"` | Pin true-color support (`true`/`false`) or keep `"auto"` detection |
175
+ | `terminal.hyperlinks` | boolean/string | `"auto"` | Pin hyperlink support (`true`/`false`) or keep `"auto"` detection |
172
176
  | `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max |
173
177
  | `images.blockImages` | boolean | `false` | Block all images from being sent to LLM |
174
178
  | `images.imageCaptionModel` | string | unset | Vision model (`provider/model`) to describe images when the active model cannot accept images; the caption text is used in place of the image (e.g. `tokenin/gemma-4`, `tokenin/kimi-k3`) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selesai/code",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Maintained, extension-first Pi coding agent with built-in workflows, subagents, web research, questions, skills, and an enhanced terminal UI.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -61,9 +61,9 @@
61
61
  "dependencies": {
62
62
  "acorn": "8.18.0",
63
63
  "@ast-grep/cli": "0.45.0",
64
- "@earendil-works/pi-agent-core": "0.84.3",
65
- "@earendil-works/pi-ai": "0.84.3",
66
- "@earendil-works/pi-tui": "0.84.3",
64
+ "@earendil-works/pi-agent-core": "0.84.4",
65
+ "@earendil-works/pi-ai": "0.84.4",
66
+ "@earendil-works/pi-tui": "0.84.4",
67
67
  "@mozilla/readability": "^0.6.0",
68
68
  "@silvia-odwyer/photon-node": "0.3.4",
69
69
  "chalk": "5.6.2",