@timurproko/a1 0.2.5 → 0.2.6-dev.727

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/bin/cli.js +13 -2
  2. package/bin/ui.js +13 -0
  3. package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
  4. package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
  5. package/dist/app/session-shell/session-shell-root.d.ts +5 -1
  6. package/dist/app/session-shell/session-shell-root.js +13 -6
  7. package/dist/app/session-shell/session-shell.js +132 -51
  8. package/dist/app/session-shell/session-viewport-controller.js +33 -21
  9. package/dist/cli/dispatch.js +5 -3
  10. package/dist/cli/session-context.d.ts +5 -1
  11. package/dist/cli/session-context.js +25 -8
  12. package/dist/composition/owned-ui.d.ts +3 -0
  13. package/dist/composition/owned-ui.js +66 -6
  14. package/dist/composition/settings-route-host.js +4 -3
  15. package/dist/contracts/owned-ui/index.d.ts +4 -2
  16. package/dist/contracts/owned-ui/index.js +1 -1
  17. package/dist/contracts/owned-ui/model.d.ts +4 -0
  18. package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
  19. package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
  20. package/dist/contracts/owned-ui/validation.js +7 -0
  21. package/dist/features/launch/index.d.ts +1 -1
  22. package/dist/features/launch/session-context.d.ts +17 -2
  23. package/dist/features/launch/session-context.js +9 -5
  24. package/dist/features/owned-ui/reference-routes.d.ts +1 -1
  25. package/dist/features/owned-ui/reference-routes.js +1 -1
  26. package/dist/features/owned-ui/settings-app.js +21 -39
  27. package/dist/features/prompt-suggestions/diagnostics.js +4 -1
  28. package/dist/foundation/lifecycle/index.d.ts +2 -2
  29. package/dist/foundation/lifecycle/index.js +1 -1
  30. package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
  31. package/dist/foundation/lifecycle/session-repository-context.js +434 -66
  32. package/dist/foundation/process-containment/index.d.ts +1 -0
  33. package/dist/foundation/process-containment/index.js +1 -0
  34. package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
  35. package/dist/foundation/process-containment/native-process-inspector.js +21 -0
  36. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  37. package/dist/foundation/release/progress-palette.generated.js +2 -2
  38. package/dist/foundation/startup/startup-descriptor.js +2 -2
  39. package/dist/integrations/pi/components/components.js +2 -2
  40. package/dist/integrations/pi/components/index.d.ts +2 -2
  41. package/dist/integrations/pi/components/index.js +1 -1
  42. package/dist/integrations/pi/components/lazy-selectors.d.ts +42 -0
  43. package/dist/integrations/pi/components/lazy-selectors.js +32 -0
  44. package/dist/integrations/pi/components/modal-frame.js +3 -4
  45. package/dist/integrations/pi/components/models-dialog.js +5 -5
  46. package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
  47. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  48. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  49. package/dist/integrations/pi/components/share-operation-dialog.js +3 -3
  50. package/dist/integrations/pi/components/shell-editor-autocomplete.js +8 -7
  51. package/dist/integrations/pi/components/shell-extension-ui.d.ts +2 -0
  52. package/dist/integrations/pi/components/shell-extension-ui.js +20 -10
  53. package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
  54. package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
  55. package/dist/integrations/pi/components/shell-presenters-transcript.js +10 -10
  56. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
  57. package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
  58. package/dist/integrations/pi/components/skills-dialog.js +3 -3
  59. package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
  60. package/dist/integrations/pi/components/theme.d.ts +9 -0
  61. package/dist/integrations/pi/components/theme.js +30 -0
  62. package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
  63. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  65. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  66. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  67. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  68. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  69. package/dist/integrations/pi/components/upstream/components/extension-editor.js +6 -6
  70. package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
  71. package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
  72. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  73. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
  74. package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
  75. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  76. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  77. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +3 -3
  78. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  79. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  80. package/dist/integrations/pi/components/upstream/components/session-selector.js +14 -20
  81. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
  82. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
  83. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  84. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  85. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  86. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  87. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  88. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +2 -2
  89. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
  90. package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
  91. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
  92. package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
  93. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  94. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  95. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +4 -4
  96. package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
  97. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  98. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  99. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  100. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  101. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  102. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  103. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  104. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  105. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +31 -0
  106. package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
  107. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +1 -1
  108. package/dist/integrations/pi/components/upstream/theme/system-theme.js +1 -1
  109. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  110. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +18 -1
  111. package/dist/integrations/pi/components/upstream/theme/theme.js +207 -10
  112. package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
  113. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  114. package/dist/integrations/pi/engine/session-events.js +10 -2
  115. package/dist/integrations/pi/engine/transcript-projection.js +2 -1
  116. package/dist/integrations/pi/startup-public.js +306 -290
  117. package/dist/integrations/pi/startup-public.manifest.json +289 -265
  118. package/dist/integrations/pi/tui-runtime/adapter.d.ts +8 -1
  119. package/dist/integrations/pi/tui-runtime/adapter.js +31 -1
  120. package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
  121. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  122. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  123. package/dist/native/darwin-arm64/manifest.json +1 -1
  124. package/dist/native/linux-x64/manifest.json +1 -1
  125. package/dist/native/win32-x64/manifest.json +2 -2
  126. package/dist/native/win32-x64/process-guardian.exe +0 -0
  127. package/dist/product-identity.d.ts +2 -2
  128. package/dist/product-identity.js +2 -2
  129. package/dist/product-identity.json +3 -1
  130. package/dist/runtime-payload-inventory.json +3092 -2878
  131. package/dist/ui/components/prompt-input.d.ts +2 -0
  132. package/dist/ui/components/prompt-input.js +5 -1
  133. package/dist/ui/components/text-selection.d.ts +1 -1
  134. package/dist/ui/components/text-selection.js +3 -1
  135. package/dist/ui/components/theme.d.ts +2 -0
  136. package/dist/ui/components/transcript-viewport.d.ts +6 -4
  137. package/dist/ui/components/transcript-viewport.js +94 -16
  138. package/dist/ui/components/value-menu.d.ts +2 -0
  139. package/dist/ui/components/value-menu.js +13 -8
  140. package/dist/ui/settings/declarations.d.ts +26 -14
  141. package/dist/ui/settings/declarations.js +24 -11
  142. package/dist/ui/settings/migrations.js +16 -0
  143. package/docs/architecture/project-structure.md +4 -3
  144. package/docs/architecture/prompt-suggestions.md +14 -10
  145. package/docs/local-worktree-cleanup.md +23 -9
  146. package/docs/manual-owned-ui-checkpoint.md +1 -1
  147. package/docs/openspec-archive-automation.md +20 -19
  148. package/package.json +3 -3
@@ -1,15 +1,15 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.0.4 (MIT), commit 7c10bd4337495ee613f2224843ecdf349b80d1df,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.1.0 (MIT), commit abe508e1b89912adde45528136c3221eb69acdd7,
3
3
  * packages/coding-agent/src/modes/interactive/theme/theme.ts.
4
4
  * Modifications: Source-synchronized theme port: retain pinned theme schema, variable/color
5
5
  * resolution, built-in and custom loading, terminal detection, and layout defaults while constructing
6
- * the public package-root Theme class.
7
- * Deviations: theme-public-api-boundary, theme-owned-watcher-boundary.
6
+ * the public package-root Theme class and projecting A1's optional semantic accent.
7
+ * Deviations: theme-public-api-boundary, theme-owned-watcher-boundary, semantic-accent-projection.
8
8
  */
9
9
  import { existsSync, readFileSync, readdirSync, watch } from "node:fs";
10
10
  import { join } from "node:path";
11
11
  import { getAgentDir, initTheme, Theme, } from "../../../startup-public.js";
12
- import { getCapabilities } from "@earendil-works/pi-tui";
12
+ import { backgroundAnsi, colorToOkhsl, foregroundAnsi, getCapabilities, okhslColor, } from "@earendil-works/pi-tui";
13
13
  import { BUILTIN_THEME_RESOURCES, isBuiltinThemeName } from "../../resources/builtin-themes.js";
14
14
  export const PINNED_PI_LAYOUT = Object.freeze({
15
15
  editorPaddingX: 0,
@@ -31,12 +31,53 @@ const FOREGROUND_COLORS = [
31
31
  const BACKGROUND_COLORS = [
32
32
  "selectedBg", "searchMatchBg", "userMessageBg", "customMessageBg", "toolPendingBg", "toolSuccessBg", "toolErrorBg",
33
33
  ];
34
+ const ACCENT_PALETTE = Object.freeze({
35
+ purple: Object.freeze({
36
+ dark: Object.freeze({ kind: "rgb", r: 167, g: 152, b: 215 }),
37
+ light: Object.freeze({ kind: "rgb", r: 116, g: 89, b: 180 }),
38
+ }),
39
+ blue: Object.freeze({ dark: okhslColor(232, 0.54, 0.67), light: okhslColor(231, 0.68, 0.47) }),
40
+ cyan: Object.freeze({ dark: okhslColor(202, 0.58, 0.67), light: okhslColor(203, 0.73, 0.46) }),
41
+ green: Object.freeze({ dark: okhslColor(159, 0.59, 0.67), light: okhslColor(159, 0.75, 0.46) }),
42
+ orange: Object.freeze({ dark: okhslColor(48, 0.75, 0.67), light: okhslColor(48, 0.90, 0.47) }),
43
+ pink: Object.freeze({ dark: okhslColor(337, 0.72, 0.67), light: okhslColor(337, 0.75, 0.48) }),
44
+ });
45
+ function clamp(value, minimum, maximum) {
46
+ return Math.max(minimum, Math.min(maximum, value));
47
+ }
48
+ function wrapHue(hue) {
49
+ return ((hue % 360) + 360) % 360;
50
+ }
51
+ /** Derive the complete semantic family from any primary accent, including future custom colors. */
52
+ export function derivePiAccentProjection(accent, appearance) {
53
+ const { h, s, l } = colorToOkhsl(accent);
54
+ const warm = h < 90 || h >= 270;
55
+ const magenta = h >= 270 && h < 325;
56
+ const blue = h >= 210 && h < 270;
57
+ const borderHue = wrapHue(h + (warm ? -20 : 20));
58
+ const secondaryHue = wrapHue(h + (magenta ? 55 : blue ? -50 : warm ? 35 : -35));
59
+ const dark = appearance === "dark";
60
+ const selectedSaturation = clamp(s * (dark ? 0.25 : 0.16), dark ? 0.10 : 0.08, dark ? 0.16 : 0.11);
61
+ const selectedLightness = dark ? l * 0.37 : 1 - (1 - l) * 0.075;
62
+ return Object.freeze({
63
+ accent,
64
+ border: okhslColor(borderHue, clamp(s * 0.78, 0.30, 0.64), clamp(l - (dark ? 0.17 : 0.11), 0, 1)),
65
+ secondaryHeading: okhslColor(secondaryHue, clamp(s + 0.20, 0.62, 0.82), clamp(l + (dark ? 0.09 : -0.09), 0, 1)),
66
+ selectedBg: okhslColor(h, selectedSaturation, selectedLightness),
67
+ userMessageBg: okhslColor(h, selectedSaturation * 2 / 3, dark ? l * 0.34 : 1 - (1 - l) * 0.055),
68
+ });
69
+ }
70
+ let activeBaseTheme;
34
71
  let activeTheme;
35
72
  let activeThemeName;
36
73
  let activeThemeMode;
74
+ let activeAccentColor = "purple";
75
+ let packageBorderProjectionEnabled = true;
37
76
  let themeWatcher;
38
77
  let themeReloadTimer;
39
78
  const themeChangeListeners = new Set();
79
+ const accentProjectionBases = new WeakMap();
80
+ const accentProjectionCache = new WeakMap();
40
81
  export function ensurePiTheme() {
41
82
  if (activeTheme)
42
83
  return activeTheme;
@@ -51,13 +92,48 @@ export function currentPiThemeName() {
51
92
  ensurePiTheme();
52
93
  return activeThemeName;
53
94
  }
95
+ export function currentPiAccentColor() {
96
+ return activeAccentColor;
97
+ }
98
+ /** Paints one menu swatch from a named A1 palette entry. */
99
+ export function renderPiAccentPreview(color, text) {
100
+ ensurePiTheme();
101
+ const base = activeBaseTheme;
102
+ if (!isAccentColor(color))
103
+ return null;
104
+ const accent = ACCENT_PALETTE[color][base.appearance];
105
+ return `${foregroundAnsi(accent, base.getColorMode())}${text}\u001b[39m`;
106
+ }
107
+ /** Keeps the complete comparison theme unmodified while bare A1 projects its semantic accent family. */
108
+ export function setPiPackageBorderProjectionEnabled(enabled) {
109
+ if (packageBorderProjectionEnabled === enabled)
110
+ return;
111
+ packageBorderProjectionEnabled = enabled;
112
+ if (activeBaseTheme !== undefined)
113
+ activeTheme = resolvePiAccentTheme(activeBaseTheme);
114
+ syncPiPackageBorderProjection();
115
+ notifyThemeChanged();
116
+ }
117
+ /** Reprojects the active base theme; repeated changes never derive from an earlier projection. */
118
+ export function setPiAccentColor(color) {
119
+ if (activeAccentColor === color)
120
+ return;
121
+ activeAccentColor = color;
122
+ if (activeBaseTheme === undefined)
123
+ return;
124
+ activeTheme = resolvePiAccentTheme(activeBaseTheme);
125
+ syncPiPackageBorderProjection();
126
+ notifyThemeChanged();
127
+ }
54
128
  export function applyPiTheme(name, enableWatcher = false, mode) {
55
129
  try {
56
130
  const loaded = loadPiTheme(name, mode);
57
131
  initTheme(name, false);
58
- activeTheme = loaded;
132
+ activeBaseTheme = loaded;
133
+ activeTheme = resolvePiAccentTheme(loaded);
59
134
  activeThemeName = name;
60
135
  activeThemeMode = mode;
136
+ syncPiPackageBorderProjection();
61
137
  if (enableWatcher)
62
138
  startPiThemeWatcher(name);
63
139
  notifyThemeChanged();
@@ -65,18 +141,23 @@ export function applyPiTheme(name, enableWatcher = false, mode) {
65
141
  }
66
142
  catch (error) {
67
143
  initTheme("dark", false);
68
- activeTheme = loadPiTheme("dark", mode);
144
+ activeBaseTheme = loadPiTheme("dark", mode);
145
+ activeTheme = resolvePiAccentTheme(activeBaseTheme);
69
146
  activeThemeName = "dark";
70
147
  activeThemeMode = mode;
148
+ syncPiPackageBorderProjection();
71
149
  notifyThemeChanged();
72
150
  return { success: false, name: "dark", error: error instanceof Error ? error.message : String(error) };
73
151
  }
74
152
  }
75
153
  export function applyPiThemeInstance(theme) {
76
154
  stopPiThemeWatcher();
77
- activeTheme = theme;
78
- activeThemeName = theme.name ?? "<in-memory>";
79
- activeThemeMode = theme.getColorMode();
155
+ const base = accentProjectionBases.get(theme) ?? theme;
156
+ activeBaseTheme = base;
157
+ activeTheme = resolvePiAccentTheme(base);
158
+ activeThemeName = base.name ?? "<in-memory>";
159
+ activeThemeMode = base.getColorMode();
160
+ syncPiPackageBorderProjection();
80
161
  notifyThemeChanged();
81
162
  return { success: true, name: activeThemeName };
82
163
  }
@@ -236,7 +317,9 @@ function startPiThemeWatcher(name) {
236
317
  if (activeThemeName !== name || !existsSync(path))
237
318
  return;
238
319
  try {
239
- activeTheme = loadPiTheme(name, activeThemeMode);
320
+ activeBaseTheme = loadPiTheme(name, activeThemeMode);
321
+ activeTheme = resolvePiAccentTheme(activeBaseTheme);
322
+ syncPiPackageBorderProjection();
240
323
  notifyThemeChanged();
241
324
  }
242
325
  catch { }
@@ -248,6 +331,120 @@ function notifyThemeChanged() {
248
331
  for (const listener of themeChangeListeners)
249
332
  listener();
250
333
  }
334
+ function resolvePiAccentTheme(base) {
335
+ const rootBase = accentProjectionBases.get(base) ?? base;
336
+ return packageBorderProjectionEnabled ? projectPiAccent(rootBase, activeAccentColor) : rootBase;
337
+ }
338
+ function syncPiPackageBorderProjection() {
339
+ if (activeBaseTheme === undefined || activeTheme === undefined)
340
+ return;
341
+ if (!packageBorderProjectionEnabled) {
342
+ setPiPackageThemeInstance(activeBaseTheme);
343
+ return;
344
+ }
345
+ const base = activeBaseTheme;
346
+ const projected = activeTheme;
347
+ setPiPackageThemeInstance(new Proxy(base, {
348
+ get(target, property) {
349
+ if (property === "colors")
350
+ return Object.freeze({ ...target.colors, border: projected.colors.border });
351
+ if (property === "fg") {
352
+ return (token, text) => token === "border"
353
+ ? projected.fg(token, text)
354
+ : target.fg(token, text);
355
+ }
356
+ if (property === "getFgAnsi") {
357
+ return (token) => token === "border"
358
+ ? projected.getFgAnsi(token)
359
+ : target.getFgAnsi(token);
360
+ }
361
+ if (property === "style") {
362
+ return (text, options) => target.style(text, {
363
+ ...options,
364
+ ...(options.fg === "border" ? { fg: projected.colors.border } : {}),
365
+ });
366
+ }
367
+ const value = Reflect.get(target, property, target);
368
+ return typeof value === "function" ? value.bind(target) : value;
369
+ },
370
+ }));
371
+ }
372
+ function setPiPackageThemeInstance(theme) {
373
+ Reflect.set(globalThis, Symbol.for("@earendil-works/pi-coding-agent:theme"), theme);
374
+ Reflect.set(globalThis, Symbol.for("@mariozechner/pi-coding-agent:theme"), theme);
375
+ }
376
+ function isAccentColor(value) {
377
+ return Object.hasOwn(ACCENT_PALETTE, value);
378
+ }
379
+ /** A transparent Theme projection keeps every role outside the selected accent family on the base. */
380
+ function projectPiAccent(base, color) {
381
+ const rootBase = accentProjectionBases.get(base) ?? base;
382
+ const cached = accentProjectionCache.get(rootBase)?.get(color);
383
+ if (cached !== undefined)
384
+ return cached;
385
+ const tone = derivePiAccentProjection(ACCENT_PALETTE[color][rootBase.appearance], rootBase.appearance);
386
+ const accentAnsi = foregroundAnsi(tone.accent, rootBase.getColorMode());
387
+ const foregrounds = Object.freeze({
388
+ accent: tone.accent,
389
+ border: tone.border,
390
+ mdHeading: tone.secondaryHeading,
391
+ mdListBullet: tone.secondaryHeading,
392
+ });
393
+ const foregroundSequences = Object.freeze({
394
+ accent: accentAnsi,
395
+ border: foregroundAnsi(tone.border, rootBase.getColorMode()),
396
+ mdHeading: foregroundAnsi(tone.secondaryHeading, rootBase.getColorMode()),
397
+ mdListBullet: foregroundAnsi(tone.secondaryHeading, rootBase.getColorMode()),
398
+ });
399
+ const backgrounds = Object.freeze({
400
+ selectedBg: tone.selectedBg,
401
+ userMessageBg: tone.userMessageBg,
402
+ });
403
+ const backgroundSequences = Object.freeze({
404
+ selectedBg: backgroundAnsi(tone.selectedBg, rootBase.getColorMode()),
405
+ userMessageBg: backgroundAnsi(tone.userMessageBg, rootBase.getColorMode()),
406
+ });
407
+ const projection = new Proxy(rootBase, {
408
+ get(target, property) {
409
+ if (property === "colors")
410
+ return Object.freeze({
411
+ ...target.colors,
412
+ ...foregrounds,
413
+ ...backgrounds,
414
+ });
415
+ if (property === "fg") {
416
+ return (token, text) => foregroundSequences[token] === undefined
417
+ ? target.fg(token, text)
418
+ : `${foregroundSequences[token]}${text}\u001b[39m`;
419
+ }
420
+ if (property === "bg") {
421
+ return (token, text) => backgroundSequences[token] === undefined
422
+ ? target.bg(token, text)
423
+ : `${backgroundSequences[token]}${text}\u001b[49m`;
424
+ }
425
+ if (property === "getFgAnsi") {
426
+ return (token) => foregroundSequences[token] ?? target.getFgAnsi(token);
427
+ }
428
+ if (property === "getBgAnsi") {
429
+ return (token) => backgroundSequences[token] ?? target.getBgAnsi(token);
430
+ }
431
+ if (property === "style") {
432
+ return (text, options) => target.style(text, {
433
+ ...options,
434
+ ...(typeof options.fg === "string" && foregrounds[options.fg] !== undefined ? { fg: foregrounds[options.fg] } : {}),
435
+ ...(typeof options.bg === "string" && backgrounds[options.bg] !== undefined ? { bg: backgrounds[options.bg] } : {}),
436
+ });
437
+ }
438
+ const value = Reflect.get(target, property, target);
439
+ return typeof value === "function" ? value.bind(target) : value;
440
+ },
441
+ });
442
+ accentProjectionBases.set(projection, rootBase);
443
+ const projections = accentProjectionCache.get(rootBase) ?? new Map();
444
+ projections.set(color, projection);
445
+ accentProjectionCache.set(rootBase, projections);
446
+ return projection;
447
+ }
251
448
  function customThemePath(name) {
252
449
  return join(getAgentDir(), "themes", `${name}.json`);
253
450
  }
@@ -149,7 +149,7 @@
149
149
  },
150
150
  "outputPad": {
151
151
  "label": "Output padding",
152
- "description": "Horizontal padding for user messages, assistant messages, and thinking",
152
+ "description": "Horizontal padding for messages, tool output, and command output",
153
153
  "opensDialog": false,
154
154
  "values": [
155
155
  "0",