@oh-my-pi/pi-coding-agent 3.14.0 → 3.15.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 (148) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/docs/theme.md +38 -5
  3. package/examples/sdk/11-sessions.ts +2 -2
  4. package/package.json +7 -4
  5. package/src/cli/file-processor.ts +51 -2
  6. package/src/cli/plugin-cli.ts +25 -19
  7. package/src/cli/update-cli.ts +4 -3
  8. package/src/core/agent-session.ts +31 -4
  9. package/src/core/compaction/branch-summarization.ts +4 -32
  10. package/src/core/compaction/compaction.ts +6 -84
  11. package/src/core/compaction/utils.ts +2 -3
  12. package/src/core/custom-tools/types.ts +2 -0
  13. package/src/core/export-html/index.ts +1 -1
  14. package/src/core/hooks/tool-wrapper.ts +0 -1
  15. package/src/core/hooks/types.ts +2 -2
  16. package/src/core/plugins/doctor.ts +9 -1
  17. package/src/core/sdk.ts +2 -1
  18. package/src/core/session-manager.ts +518 -40
  19. package/src/core/settings-manager.ts +174 -0
  20. package/src/core/system-prompt.ts +9 -14
  21. package/src/core/title-generator.ts +2 -8
  22. package/src/core/tools/ask.ts +19 -37
  23. package/src/core/tools/bash.ts +2 -37
  24. package/src/core/tools/edit.ts +2 -9
  25. package/src/core/tools/exa/render.ts +52 -48
  26. package/src/core/tools/find.ts +10 -8
  27. package/src/core/tools/grep.ts +45 -17
  28. package/src/core/tools/ls.ts +22 -2
  29. package/src/core/tools/lsp/clients/biome-client.ts +207 -0
  30. package/src/core/tools/lsp/clients/index.ts +49 -0
  31. package/src/core/tools/lsp/clients/lsp-linter-client.ts +98 -0
  32. package/src/core/tools/lsp/config.ts +3 -0
  33. package/src/core/tools/lsp/index.ts +107 -55
  34. package/src/core/tools/lsp/render.ts +192 -79
  35. package/src/core/tools/lsp/types.ts +27 -0
  36. package/src/core/tools/lsp/utils.ts +62 -22
  37. package/src/core/tools/notebook.ts +9 -1
  38. package/src/core/tools/output.ts +37 -14
  39. package/src/core/tools/read.ts +349 -34
  40. package/src/core/tools/renderers.ts +290 -89
  41. package/src/core/tools/review.ts +12 -5
  42. package/src/core/tools/task/agents.ts +5 -5
  43. package/src/core/tools/task/commands.ts +3 -3
  44. package/src/core/tools/task/executor.ts +33 -1
  45. package/src/core/tools/task/index.ts +93 -6
  46. package/src/core/tools/task/render.ts +147 -66
  47. package/src/core/tools/task/types.ts +14 -9
  48. package/src/core/tools/web-fetch.ts +242 -103
  49. package/src/core/tools/web-search/index.ts +64 -20
  50. package/src/core/tools/web-search/providers/exa.ts +68 -172
  51. package/src/core/tools/web-search/render.ts +264 -74
  52. package/src/core/tools/write.ts +2 -8
  53. package/src/main.ts +10 -6
  54. package/src/modes/cleanup.ts +23 -0
  55. package/src/modes/index.ts +9 -4
  56. package/src/modes/interactive/components/bash-execution.ts +6 -3
  57. package/src/modes/interactive/components/branch-summary-message.ts +1 -1
  58. package/src/modes/interactive/components/compaction-summary-message.ts +1 -1
  59. package/src/modes/interactive/components/dynamic-border.ts +1 -1
  60. package/src/modes/interactive/components/extensions/extension-dashboard.ts +4 -5
  61. package/src/modes/interactive/components/extensions/extension-list.ts +18 -16
  62. package/src/modes/interactive/components/extensions/inspector-panel.ts +8 -8
  63. package/src/modes/interactive/components/hook-message.ts +2 -2
  64. package/src/modes/interactive/components/hook-selector.ts +1 -1
  65. package/src/modes/interactive/components/model-selector.ts +22 -9
  66. package/src/modes/interactive/components/oauth-selector.ts +20 -4
  67. package/src/modes/interactive/components/plugin-settings.ts +4 -2
  68. package/src/modes/interactive/components/session-selector.ts +9 -6
  69. package/src/modes/interactive/components/settings-defs.ts +285 -1
  70. package/src/modes/interactive/components/settings-selector.ts +176 -3
  71. package/src/modes/interactive/components/status-line/index.ts +4 -0
  72. package/src/modes/interactive/components/status-line/presets.ts +94 -0
  73. package/src/modes/interactive/components/status-line/segments.ts +350 -0
  74. package/src/modes/interactive/components/status-line/separators.ts +55 -0
  75. package/src/modes/interactive/components/status-line/types.ts +81 -0
  76. package/src/modes/interactive/components/status-line-segment-editor.ts +357 -0
  77. package/src/modes/interactive/components/status-line.ts +170 -223
  78. package/src/modes/interactive/components/tool-execution.ts +446 -211
  79. package/src/modes/interactive/components/tree-selector.ts +17 -6
  80. package/src/modes/interactive/components/ttsr-notification.ts +4 -4
  81. package/src/modes/interactive/components/welcome.ts +27 -19
  82. package/src/modes/interactive/interactive-mode.ts +98 -13
  83. package/src/modes/interactive/theme/dark.json +3 -2
  84. package/src/modes/interactive/theme/defaults/dark-arctic.json +111 -0
  85. package/src/modes/interactive/theme/defaults/dark-catppuccin.json +106 -0
  86. package/src/modes/interactive/theme/defaults/dark-cyberpunk.json +109 -0
  87. package/src/modes/interactive/theme/defaults/dark-dracula.json +105 -0
  88. package/src/modes/interactive/theme/defaults/dark-forest.json +103 -0
  89. package/src/modes/interactive/theme/defaults/dark-github.json +112 -0
  90. package/src/modes/interactive/theme/defaults/dark-gruvbox.json +119 -0
  91. package/src/modes/interactive/theme/defaults/dark-monochrome.json +101 -0
  92. package/src/modes/interactive/theme/defaults/dark-monokai.json +105 -0
  93. package/src/modes/interactive/theme/defaults/dark-nord.json +104 -0
  94. package/src/modes/interactive/theme/defaults/dark-ocean.json +108 -0
  95. package/src/modes/interactive/theme/defaults/dark-one.json +107 -0
  96. package/src/modes/interactive/theme/defaults/dark-retro.json +99 -0
  97. package/src/modes/interactive/theme/defaults/dark-rose-pine.json +95 -0
  98. package/src/modes/interactive/theme/defaults/dark-solarized.json +96 -0
  99. package/src/modes/interactive/theme/defaults/dark-sunset.json +106 -0
  100. package/src/modes/interactive/theme/defaults/dark-synthwave.json +102 -0
  101. package/src/modes/interactive/theme/defaults/dark-tokyo-night.json +108 -0
  102. package/src/modes/interactive/theme/defaults/index.ts +67 -0
  103. package/src/modes/interactive/theme/defaults/light-arctic.json +106 -0
  104. package/src/modes/interactive/theme/defaults/light-catppuccin.json +105 -0
  105. package/src/modes/interactive/theme/defaults/light-cyberpunk.json +103 -0
  106. package/src/modes/interactive/theme/defaults/light-forest.json +107 -0
  107. package/src/modes/interactive/theme/defaults/light-github.json +114 -0
  108. package/src/modes/interactive/theme/defaults/light-gruvbox.json +115 -0
  109. package/src/modes/interactive/theme/defaults/light-monochrome.json +100 -0
  110. package/src/modes/interactive/theme/defaults/light-ocean.json +106 -0
  111. package/src/modes/interactive/theme/defaults/light-one.json +105 -0
  112. package/src/modes/interactive/theme/defaults/light-retro.json +105 -0
  113. package/src/modes/interactive/theme/defaults/light-solarized.json +101 -0
  114. package/src/modes/interactive/theme/defaults/light-sunset.json +106 -0
  115. package/src/modes/interactive/theme/defaults/light-synthwave.json +105 -0
  116. package/src/modes/interactive/theme/defaults/light-tokyo-night.json +118 -0
  117. package/src/modes/interactive/theme/light.json +3 -2
  118. package/src/modes/interactive/theme/theme-schema.json +120 -4
  119. package/src/modes/interactive/theme/theme.ts +1228 -14
  120. package/src/prompts/branch-summary-preamble.md +3 -0
  121. package/src/prompts/branch-summary.md +28 -0
  122. package/src/prompts/compaction-summary.md +34 -0
  123. package/src/prompts/compaction-turn-prefix.md +16 -0
  124. package/src/prompts/compaction-update-summary.md +41 -0
  125. package/src/prompts/init.md +30 -0
  126. package/src/{core/tools/task/bundled-agents → prompts}/reviewer.md +6 -0
  127. package/src/prompts/summarization-system.md +3 -0
  128. package/src/prompts/system-prompt.md +27 -0
  129. package/src/{core/tools/task/bundled-agents → prompts}/task.md +2 -0
  130. package/src/prompts/title-system.md +8 -0
  131. package/src/prompts/tools/ask.md +24 -0
  132. package/src/prompts/tools/bash.md +23 -0
  133. package/src/prompts/tools/edit.md +9 -0
  134. package/src/prompts/tools/find.md +6 -0
  135. package/src/prompts/tools/grep.md +12 -0
  136. package/src/prompts/tools/lsp.md +14 -0
  137. package/src/prompts/tools/output.md +23 -0
  138. package/src/prompts/tools/read.md +25 -0
  139. package/src/prompts/tools/web-fetch.md +8 -0
  140. package/src/prompts/tools/web-search.md +10 -0
  141. package/src/prompts/tools/write.md +10 -0
  142. package/src/commands/init.md +0 -20
  143. /package/src/{core/tools/task/bundled-commands → prompts}/architect-plan.md +0 -0
  144. /package/src/{core/tools/task/bundled-agents → prompts}/browser.md +0 -0
  145. /package/src/{core/tools/task/bundled-agents → prompts}/explore.md +0 -0
  146. /package/src/{core/tools/task/bundled-commands → prompts}/implement-with-critic.md +0 -0
  147. /package/src/{core/tools/task/bundled-commands → prompts}/implement.md +0 -0
  148. /package/src/{core/tools/task/bundled-agents → prompts}/plan.md +0 -0
@@ -16,11 +16,13 @@ import {
16
16
  type TabBarTheme,
17
17
  Text,
18
18
  } from "@oh-my-pi/pi-tui";
19
- import type { SettingsManager } from "../../../core/settings-manager";
19
+ import type { SettingsManager, StatusLineSettings } from "../../../core/settings-manager";
20
20
  import { getSelectListTheme, getSettingsListTheme, theme } from "../theme/theme";
21
21
  import { DynamicBorder } from "./dynamic-border";
22
22
  import { PluginSettingsComponent } from "./plugin-settings";
23
23
  import { getSettingsForTab, type SettingDef } from "./settings-defs";
24
+ import { getPreset } from "./status-line/presets";
25
+ import { StatusLineSegmentEditorComponent } from "./status-line-segment-editor";
24
26
 
25
27
  function getTabBarTheme(): TabBarTheme {
26
28
  return {
@@ -36,6 +38,8 @@ function getTabBarTheme(): TabBarTheme {
36
38
  */
37
39
  class SelectSubmenu extends Container {
38
40
  private selectList: SelectList;
41
+ private previewText: Text | null = null;
42
+ private getPreview: (() => string) | undefined;
39
43
 
40
44
  constructor(
41
45
  title: string,
@@ -45,8 +49,10 @@ class SelectSubmenu extends Container {
45
49
  onSelect: (value: string) => void,
46
50
  onCancel: () => void,
47
51
  onSelectionChange?: (value: string) => void,
52
+ getPreview?: () => string,
48
53
  ) {
49
54
  super();
55
+ this.getPreview = getPreview;
50
56
 
51
57
  // Title
52
58
  this.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
@@ -57,6 +63,14 @@ class SelectSubmenu extends Container {
57
63
  this.addChild(new Text(theme.fg("muted", description), 0, 0));
58
64
  }
59
65
 
66
+ // Preview (if provided)
67
+ if (getPreview) {
68
+ this.addChild(new Spacer(1));
69
+ this.addChild(new Text(theme.fg("muted", "Preview:"), 0, 0));
70
+ this.previewText = new Text(getPreview(), 0, 0);
71
+ this.addChild(this.previewText);
72
+ }
73
+
60
74
  // Spacer
61
75
  this.addChild(new Spacer(1));
62
76
 
@@ -78,6 +92,8 @@ class SelectSubmenu extends Container {
78
92
  if (onSelectionChange) {
79
93
  this.selectList.onSelectionChange = (item) => {
80
94
  onSelectionChange(item.value);
95
+ // Update preview after the preview callback has applied changes
96
+ this.updatePreview();
81
97
  };
82
98
  }
83
99
 
@@ -88,6 +104,12 @@ class SelectSubmenu extends Container {
88
104
  this.addChild(new Text(theme.fg("dim", " Enter to select · Esc to go back"), 0, 0));
89
105
  }
90
106
 
107
+ private updatePreview(): void {
108
+ if (this.previewText && this.getPreview) {
109
+ this.previewText.setText(this.getPreview());
110
+ }
111
+ }
112
+
91
113
  handleInput(data: string): void {
92
114
  this.selectList.handleInput(data);
93
115
  }
@@ -97,6 +119,7 @@ type TabId = string;
97
119
 
98
120
  const SETTINGS_TABS: Tab[] = [
99
121
  { id: "config", label: "Config" },
122
+ { id: "status", label: "Status" },
100
123
  { id: "lsp", label: "LSP" },
101
124
  { id: "exa", label: "Exa" },
102
125
  { id: "plugins", label: "Plugins" },
@@ -128,6 +151,10 @@ export interface SettingsCallbacks {
128
151
  onChange: SettingChangeHandler;
129
152
  /** Called for theme preview while browsing */
130
153
  onThemePreview?: (theme: string) => void;
154
+ /** Called for status line preview while configuring - updates actual status line */
155
+ onStatusLinePreview?: (settings: Partial<StatusLineSettings>) => void;
156
+ /** Get current rendered status line for inline preview */
157
+ getStatusLinePreview?: () => string;
131
158
  /** Called when plugins change */
132
159
  onPluginsChanged?: () => void;
133
160
  /** Called when settings panel is closed */
@@ -143,6 +170,9 @@ export class SettingsSelectorComponent extends Container {
143
170
  private currentList: SettingsList | null = null;
144
171
  private currentSubmenu: Container | null = null;
145
172
  private pluginComponent: PluginSettingsComponent | null = null;
173
+ private statusPreviewContainer: Container | null = null;
174
+ private statusPreviewText: Text | null = null;
175
+ private currentTabId: TabId = "config";
146
176
 
147
177
  private settingsManager: SettingsManager;
148
178
  private context: SettingsRuntimeContext;
@@ -176,6 +206,8 @@ export class SettingsSelectorComponent extends Container {
176
206
  }
177
207
 
178
208
  private switchToTab(tabId: TabId): void {
209
+ this.currentTabId = tabId;
210
+
179
211
  // Remove current content
180
212
  if (this.currentList) {
181
213
  this.removeChild(this.currentList);
@@ -185,6 +217,11 @@ export class SettingsSelectorComponent extends Container {
185
217
  this.removeChild(this.pluginComponent);
186
218
  this.pluginComponent = null;
187
219
  }
220
+ if (this.statusPreviewContainer) {
221
+ this.removeChild(this.statusPreviewContainer);
222
+ this.statusPreviewContainer = null;
223
+ this.statusPreviewText = null;
224
+ }
188
225
 
189
226
  // Remove bottom border temporarily
190
227
  const bottomBorder = this.children[this.children.length - 1];
@@ -262,6 +299,11 @@ export class SettingsSelectorComponent extends Container {
262
299
  currentValue: string,
263
300
  done: (value?: string) => void,
264
301
  ): Container {
302
+ // Special case: segment editor
303
+ if (def.id === "statusLineSegments") {
304
+ return this.createSegmentEditor(done);
305
+ }
306
+
265
307
  let options = def.getOptions(this.settingsManager);
266
308
 
267
309
  // Special case: inject runtime options
@@ -274,8 +316,55 @@ export class SettingsSelectorComponent extends Container {
274
316
  options = this.context.availableThemes.map((t) => ({ value: t, label: t }));
275
317
  }
276
318
 
277
- const onPreview = def.id === "theme" ? this.callbacks.onThemePreview : undefined;
278
- const onPreviewCancel = def.id === "theme" ? () => this.callbacks.onThemePreview?.(currentValue) : undefined;
319
+ // Preview handlers
320
+ let onPreview: ((value: string) => void) | undefined;
321
+ let onPreviewCancel: (() => void) | undefined;
322
+
323
+ if (def.id === "theme") {
324
+ onPreview = this.callbacks.onThemePreview;
325
+ onPreviewCancel = () => this.callbacks.onThemePreview?.(currentValue);
326
+ } else if (def.id === "statusLinePreset") {
327
+ onPreview = (value) => {
328
+ const presetDef = getPreset((value as StatusLineSettings["preset"]) ?? "default");
329
+ this.callbacks.onStatusLinePreview?.({
330
+ preset: value as StatusLineSettings["preset"],
331
+ leftSegments: presetDef.leftSegments,
332
+ rightSegments: presetDef.rightSegments,
333
+ separator: presetDef.separator,
334
+ });
335
+ this.updateStatusPreview();
336
+ };
337
+ onPreviewCancel = () => {
338
+ const currentPreset = this.settingsManager.getStatusLinePreset();
339
+ const presetDef = getPreset(currentPreset);
340
+ this.callbacks.onStatusLinePreview?.({
341
+ preset: currentPreset,
342
+ leftSegments: presetDef.leftSegments,
343
+ rightSegments: presetDef.rightSegments,
344
+ separator: presetDef.separator,
345
+ });
346
+ this.updateStatusPreview();
347
+ };
348
+ } else if (def.id === "statusLineSeparator") {
349
+ onPreview = (value) => {
350
+ this.callbacks.onStatusLinePreview?.({
351
+ separator: value as StatusLineSettings["separator"],
352
+ });
353
+ this.updateStatusPreview();
354
+ };
355
+ onPreviewCancel = () => {
356
+ const currentSettings = this.settingsManager.getStatusLineSettings();
357
+ const separator =
358
+ currentSettings.separator ?? getPreset(this.settingsManager.getStatusLinePreset()).separator;
359
+ this.callbacks.onStatusLinePreview?.({
360
+ separator,
361
+ });
362
+ this.updateStatusPreview();
363
+ };
364
+ }
365
+
366
+ // Provide status line preview for theme selection
367
+ const getPreview = def.id === "theme" ? this.callbacks.getStatusLinePreview : undefined;
279
368
 
280
369
  return new SelectSubmenu(
281
370
  def.label,
@@ -294,9 +383,48 @@ export class SettingsSelectorComponent extends Container {
294
383
  done();
295
384
  },
296
385
  onPreview,
386
+ getPreview,
297
387
  );
298
388
  }
299
389
 
390
+ /**
391
+ * Create the segment editor component.
392
+ */
393
+ private createSegmentEditor(done: (value?: string) => void): Container {
394
+ const currentSettings = this.settingsManager.getStatusLineSettings();
395
+ const preset = currentSettings.preset ?? "default";
396
+ const presetDef = getPreset(preset);
397
+
398
+ const leftSegments = currentSettings.leftSegments ?? presetDef.leftSegments;
399
+ const rightSegments = currentSettings.rightSegments ?? presetDef.rightSegments;
400
+
401
+ return new StatusLineSegmentEditorComponent(leftSegments, rightSegments, {
402
+ onSave: (left, right) => {
403
+ this.settingsManager.setStatusLineLeftSegments(left);
404
+ this.settingsManager.setStatusLineRightSegments(right);
405
+ this.callbacks.onChange("statusLineSegments", "saved");
406
+ this.callbacks.onStatusLinePreview?.({ leftSegments: left, rightSegments: right });
407
+ this.updateStatusPreview();
408
+ done("saved");
409
+ },
410
+ onCancel: () => {
411
+ // Restore preview to saved state
412
+ const saved = this.settingsManager.getStatusLineSettings();
413
+ const savedPreset = getPreset(saved.preset ?? "default");
414
+ this.callbacks.onStatusLinePreview?.({
415
+ leftSegments: saved.leftSegments ?? savedPreset.leftSegments,
416
+ rightSegments: saved.rightSegments ?? savedPreset.rightSegments,
417
+ });
418
+ this.updateStatusPreview();
419
+ done();
420
+ },
421
+ onPreview: (left, right) => {
422
+ this.callbacks.onStatusLinePreview?.({ leftSegments: left, rightSegments: right });
423
+ this.updateStatusPreview();
424
+ },
425
+ });
426
+ }
427
+
300
428
  /**
301
429
  * Show a settings tab using definitions.
302
430
  */
@@ -311,6 +439,17 @@ export class SettingsSelectorComponent extends Container {
311
439
  }
312
440
  }
313
441
 
442
+ // Add status line preview for status tab
443
+ if (tabId === "status") {
444
+ this.statusPreviewContainer = new Container();
445
+ this.statusPreviewContainer.addChild(new Spacer(1));
446
+ this.statusPreviewContainer.addChild(new Text(theme.fg("muted", "Preview:"), 0, 0));
447
+ this.statusPreviewText = new Text(this.getStatusPreviewString(), 0, 0);
448
+ this.statusPreviewContainer.addChild(this.statusPreviewText);
449
+ this.statusPreviewContainer.addChild(new Spacer(1));
450
+ this.addChild(this.statusPreviewContainer);
451
+ }
452
+
314
453
  this.currentList = new SettingsList(
315
454
  items,
316
455
  10,
@@ -324,6 +463,11 @@ export class SettingsSelectorComponent extends Container {
324
463
  const boolValue = newValue === "true";
325
464
  def.set(this.settingsManager, boolValue);
326
465
  this.callbacks.onChange(id, boolValue);
466
+
467
+ // Trigger status line preview for status tab boolean settings
468
+ if (tabId === "status") {
469
+ this.triggerStatusLinePreview();
470
+ }
327
471
  } else if (def.type === "enum") {
328
472
  def.set(this.settingsManager, newValue);
329
473
  this.callbacks.onChange(id, newValue);
@@ -336,6 +480,35 @@ export class SettingsSelectorComponent extends Container {
336
480
  this.addChild(this.currentList);
337
481
  }
338
482
 
483
+ /**
484
+ * Get the status line preview string.
485
+ */
486
+ private getStatusPreviewString(): string {
487
+ if (this.callbacks.getStatusLinePreview) {
488
+ return this.callbacks.getStatusLinePreview();
489
+ }
490
+ return theme.fg("dim", "(preview not available)");
491
+ }
492
+
493
+ /**
494
+ * Trigger status line preview with current settings.
495
+ */
496
+ private triggerStatusLinePreview(): void {
497
+ const settings = this.settingsManager.getStatusLineSettings();
498
+ this.callbacks.onStatusLinePreview?.(settings);
499
+ // Update inline preview
500
+ this.updateStatusPreview();
501
+ }
502
+
503
+ /**
504
+ * Update the inline status preview text.
505
+ */
506
+ private updateStatusPreview(): void {
507
+ if (this.statusPreviewText && this.currentTabId === "status") {
508
+ this.statusPreviewText.setText(this.getStatusPreviewString());
509
+ }
510
+ }
511
+
339
512
  private showPluginsTab(): void {
340
513
  this.pluginComponent = new PluginSettingsComponent(this.context.cwd, {
341
514
  onClose: () => this.callbacks.onCancel(),
@@ -0,0 +1,4 @@
1
+ export * from "./presets";
2
+ export * from "./segments";
3
+ export * from "./separators";
4
+ export * from "./types";
@@ -0,0 +1,94 @@
1
+ import type { PresetDef, StatusLinePreset } from "./types";
2
+
3
+ export const STATUS_LINE_PRESETS: Record<StatusLinePreset, PresetDef> = {
4
+ default: {
5
+ // Matches current behavior
6
+ leftSegments: ["pi", "model", "path", "git", "context_pct", "token_total", "cost"],
7
+ rightSegments: [],
8
+ separator: "powerline-thin",
9
+ segmentOptions: {
10
+ model: { showThinkingLevel: true },
11
+ path: { abbreviate: true, maxLength: 40, stripWorkPrefix: true },
12
+ git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
13
+ },
14
+ },
15
+
16
+ minimal: {
17
+ leftSegments: ["path", "git"],
18
+ rightSegments: ["context_pct"],
19
+ separator: "slash",
20
+ segmentOptions: {
21
+ path: { abbreviate: true, maxLength: 30 },
22
+ git: { showBranch: true, showStaged: false, showUnstaged: false, showUntracked: false },
23
+ },
24
+ },
25
+
26
+ compact: {
27
+ leftSegments: ["model", "git"],
28
+ rightSegments: ["cost", "context_pct"],
29
+ separator: "powerline-thin",
30
+ segmentOptions: {
31
+ model: { showThinkingLevel: false },
32
+ git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: false },
33
+ },
34
+ },
35
+
36
+ full: {
37
+ leftSegments: ["pi", "hostname", "model", "path", "git", "subagents"],
38
+ rightSegments: ["token_in", "token_out", "cache_read", "cost", "context_pct", "time_spent", "time"],
39
+ separator: "powerline",
40
+ segmentOptions: {
41
+ model: { showThinkingLevel: true },
42
+ path: { abbreviate: true, maxLength: 50 },
43
+ git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
44
+ time: { format: "24h", showSeconds: false },
45
+ },
46
+ },
47
+
48
+ nerd: {
49
+ // Full preset with all Nerd Font icons
50
+ leftSegments: ["pi", "hostname", "model", "path", "git", "session", "subagents"],
51
+ rightSegments: [
52
+ "token_in",
53
+ "token_out",
54
+ "cache_read",
55
+ "cache_write",
56
+ "cost",
57
+ "context_pct",
58
+ "context_total",
59
+ "time_spent",
60
+ "time",
61
+ ],
62
+ separator: "powerline",
63
+ segmentOptions: {
64
+ model: { showThinkingLevel: true },
65
+ path: { abbreviate: true, maxLength: 60 },
66
+ git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
67
+ time: { format: "24h", showSeconds: true },
68
+ },
69
+ },
70
+
71
+ ascii: {
72
+ // No Nerd Font dependencies
73
+ leftSegments: ["model", "path", "git"],
74
+ rightSegments: ["token_total", "cost", "context_pct"],
75
+ separator: "ascii",
76
+ segmentOptions: {
77
+ model: { showThinkingLevel: true },
78
+ path: { abbreviate: true, maxLength: 40 },
79
+ git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
80
+ },
81
+ },
82
+
83
+ custom: {
84
+ // User-defined - these are just defaults that get overridden
85
+ leftSegments: ["model", "path", "git"],
86
+ rightSegments: ["token_total", "cost", "context_pct"],
87
+ separator: "powerline-thin",
88
+ segmentOptions: {},
89
+ },
90
+ };
91
+
92
+ export function getPreset(name: StatusLinePreset): PresetDef {
93
+ return STATUS_LINE_PRESETS[name] ?? STATUS_LINE_PRESETS.default;
94
+ }