pi-one-ui 0.3.1 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.0] - 2026-09-03
10
+
11
+ ### Changed
12
+
13
+ - Simplified Editor styling to the `opencode` and `minimalist` options; removed Minimalist context-usage metadata in favor of Footer's more complete context configuration.
14
+ - Added response-local live output throughput to the WorkingLine token segment after a bounded sampling window.
15
+
16
+ ### Removed
17
+
18
+ - Removed the `opencode-copy-friendly` and `accent-rail` Editor styles, including Accent Rail layout patching and style-specific settings.
19
+ - Removed the inherited upstream image from pi-one-ui's package-gallery metadata.
20
+
21
+ ### Migration
22
+
23
+ - Existing `opencode-copy-friendly` or `accent-rail` selections fall back to `opencode`; remove obsolete nested settings for those styles when convenient.
24
+ - Configure context percentage, token totals, thresholds, and gauges through Footer instead of Minimalist Editor settings.
25
+
9
26
  ## [0.3.1] - 2026-08-31
10
27
 
11
28
  ### Changed
@@ -45,7 +62,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
45
62
 
46
63
  - Reduced rendering lag when expanding settled tool groups by reusing cached child output.
47
64
 
48
- [Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.3.1...HEAD
65
+ [Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.4.0...HEAD
66
+ [0.4.0]: https://github.com/kerolt/pi-one-ui/compare/v0.3.1...v0.4.0
49
67
  [0.3.1]: https://github.com/kerolt/pi-one-ui/compare/v0.3.0...v0.3.1
50
68
  [0.3.0]: https://github.com/kerolt/pi-one-ui/compare/v0.2.2...v0.3.0
51
69
  [0.2.2]: https://github.com/kerolt/pi-one-ui/compare/v0.2.1...v0.2.2
package/README.en.md CHANGED
@@ -25,24 +25,24 @@ Header → Context → WorkingLine → Editor → Footer
25
25
 
26
26
  - **Header**: startup information, logo, and shortcut hints.
27
27
  - **Context**: the conversation area, including user messages, assistant messages, thinking, tools, diffs, Markdown, and summaries.
28
- - **WorkingLine**: working state, spinner, token/thought/elapsed information, and turn summaries.
29
- - **Editor**: input editor, completion, metadata, Accent Rail, and Minimalist styles.
28
+ - **WorkingLine**: working state, spinner, token/thought/elapsed information, live output rate, and turn summaries.
29
+ - **Editor**: input editor, completion, metadata, and the Opencode and Minimalist styles.
30
30
  - **Footer**: current directory, Git, runtime, token, cost, and extension status information.
31
31
  - **Overlay**: temporary interfaces such as the settings panel and Context Inspector, managed by a shared OverlayManager.
32
32
 
33
33
  ### Built-in functionality
34
34
 
35
- | Feature | Description | Entry point |
36
- | --- | --- | --- |
37
- | Unified settings panel | Organizes settings by Header, Context, WorkingLine, Editor, Footer, and Features | `/oneui` |
38
- | Context Inspector | Shows context usage and previews the system prompt, memory, skills, tools, and messages | `/context` |
39
- | Session reference | Searches previous Pi sessions or SubAgents and injects their useful context | `@` completion |
40
- | Subagent autocomplete | Completes SubAgent names and delegation hints | `@` completion |
41
- | Tool / Diff renderer | Provides unified rendering for tool calls, results, collapsed content, and Edit/Write diffs | Automatic |
42
- | Subagent live renderer | Preserves pi-subagents' dedicated progress cards and keeps them out of generic tool groups | Automatic |
43
- | Markdown enhancement | Adds Mermaid, admonitions, URL linking, and related rendering improvements | Automatic |
44
- | Built-in themes | Provides CC Dark and CC Light themes | `/theme` |
45
- | Compatibility aliases | Optionally provides common command aliases | `/clear`, `/exit` |
35
+ | Feature | Description | Entry point |
36
+ | ---------------------- | ------------------------------------------------------------------------------------------- | ----------------- |
37
+ | Unified settings panel | Organizes settings by Header, Context, WorkingLine, Editor, Footer, and Features | `/oneui` |
38
+ | Context Inspector | Shows context usage and previews the system prompt, memory, skills, tools, and messages | `/context` |
39
+ | Session reference | Searches previous Pi sessions or SubAgents and injects their useful context | `@` completion |
40
+ | Subagent autocomplete | Completes SubAgent names and delegation hints | `@` completion |
41
+ | Tool / Diff renderer | Provides unified rendering for tool calls, results, collapsed content, and Edit/Write diffs | Automatic |
42
+ | Subagent live renderer | Preserves pi-subagents' dedicated progress cards and keeps them out of generic tool groups | Automatic |
43
+ | Markdown enhancement | Adds Mermaid, admonitions, URL linking, and related rendering improvements | Automatic |
44
+ | Built-in themes | Provides CC Dark and CC Light themes | `/theme` |
45
+ | Compatibility aliases | Optionally provides common command aliases | `/clear`, `/exit` |
46
46
 
47
47
  ## Quick start
48
48
 
@@ -111,6 +111,10 @@ Using the `/oneui` settings panel is recommended. The panel uses a top-centered
111
111
  }
112
112
  ```
113
113
 
114
+ The Editor now supports only the `opencode` and `minimalist` styles. `minimalist` no longer duplicates context-usage information; context percentage, token totals, thresholds, gauges, and related presentation are configured through Footer. Existing configurations that select the removed `opencode-copy-friendly` or `accent-rail` styles safely fall back to the default `opencode`, and their old nested style settings are ignored.
115
+
116
+ The WorkingLine token segment appends live output throughput, such as `⚡12 tok/s`, after a model response has run for at least 500ms. Throughput is calculated independently for the current response and resets on the next `turn_start`; disabling the token segment hides it as well.
117
+
114
118
  Available layout and renderer options may change between versions, so prefer configuring them through `/oneui`.
115
119
 
116
120
  ### Canonical configuration policy
@@ -127,9 +131,9 @@ It does not automatically read, merge, or migrate historical configuration files
127
131
 
128
132
  `pi-one-ui` originally combined source from the following open-source projects. Many thanks to their maintainers and contributors for providing the initial foundation.
129
133
 
130
- | Upstream project | Capabilities incorporated into `pi-one-ui` | Reference baseline |
131
- | --- | --- | --- |
132
- | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship-style Footer, Opencode-style Editor, layouts, and shell capabilities | v0.21.0, commit `5341b38` |
134
+ | Upstream project | Capabilities incorporated into `pi-one-ui` | Reference baseline |
135
+ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------- |
136
+ | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship-style Footer, Opencode-style Editor, layouts, and shell capabilities | v0.21.0, commit `5341b38` |
133
137
  | [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions) | Claude Code-style Context renderer, Tool/Diff rendering, Context Inspector, and references | v0.8.67, commit `dba37e5` |
134
138
 
135
139
  Production code lives in `extensions/`. The project has since unified its entry point, configuration storage, lifecycle, layout ownership, overlays, and input routing. The current implementation is no longer equivalent to either upstream project and does not automatically track upstream changes.
@@ -178,16 +182,16 @@ After changing the source, run the following command in Pi:
178
182
 
179
183
  ### Development commands
180
184
 
181
- | Command | Purpose |
182
- | --- | --- |
183
- | `npm install` | Install dependencies |
184
- | `npm run format` | Format source, tests, and configuration files |
185
- | `npm run check` | Check formatting and import organization |
186
- | `npm run fix` | Fix formatting and organize imports |
187
- | `npm run typecheck` | Run TypeScript type checking |
188
- | `npm test` | Run all tests with Vitest |
189
- | `npm run pack:check` | Preview the npm package contents |
190
- | `npm run verify` | Run Biome checks, type checking, and all tests |
185
+ | Command | Purpose |
186
+ | -------------------- | ---------------------------------------------- |
187
+ | `npm install` | Install dependencies |
188
+ | `npm run format` | Format source, tests, and configuration files |
189
+ | `npm run check` | Check formatting and import organization |
190
+ | `npm run fix` | Fix formatting and organize imports |
191
+ | `npm run typecheck` | Run TypeScript type checking |
192
+ | `npm test` | Run all tests with Vitest |
193
+ | `npm run pack:check` | Preview the npm package contents |
194
+ | `npm run verify` | Run Biome checks, type checking, and all tests |
191
195
 
192
196
  Before submitting changes, run at least:
193
197
 
package/README.md CHANGED
@@ -25,8 +25,8 @@ Header → Context → WorkingLine → Editor → Footer
25
25
 
26
26
  - **Header**:启动信息、Logo 和快捷键提示。
27
27
  - **Context**:对话内容区,包含用户消息、Assistant 消息、Thinking、Tool、Diff、Markdown 和 Summary。
28
- - **WorkingLine**:工作状态、spinner、token/thought/elapsed 信息和回合摘要。
29
- - **Editor**:输入编辑器、completion、metadata、Accent Rail 和 Minimalist 样式。
28
+ - **WorkingLine**:工作状态、spinner、token/thought/elapsed、实时输出速率和回合摘要。
29
+ - **Editor**:输入编辑器、completion、metadata,以及 Opencode 和 Minimalist 样式。
30
30
  - **Footer**:目录、Git、runtime、token、cost 和扩展状态等信息。
31
31
  - **Overlay**:设置面板、Context Inspector 等临时浮层由统一的 OverlayManager 管理。
32
32
 
@@ -111,6 +111,10 @@ pi install git:github.com/kerolt/pi-one-ui
111
111
  }
112
112
  ```
113
113
 
114
+ Editor 当前只支持 `opencode` 和 `minimalist` 两种样式。`minimalist` 不再重复显示上下文占用信息;上下文百分比、token 总量、阈值和 gauge 等展示统一由 Footer 配置。已有配置若选择了已移除的 `opencode-copy-friendly` 或 `accent-rail`,运行时会安全回退到默认的 `opencode`,相应的旧嵌套样式配置会被忽略。
115
+
116
+ WorkingLine 的 token segment 会在一次模型响应持续至少 500ms 后追加实时输出速率,例如 `⚡12 tok/s`。速率按当前响应独立计算,在下一次 `turn_start` 时重置;关闭 token segment 时也会一并隐藏。
117
+
114
118
  不同布局和渲染器的可用选项会随版本变化,建议优先使用 `/oneui` 面板进行配置。
115
119
 
116
120
  ### Canonical 配置约定
@@ -1,7 +1,6 @@
1
1
  import type { Theme } from "@earendil-works/pi-coding-agent";
2
2
  import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
3
  import { renderUserMessageStyle } from "../../layouts/context/message/user-message-styles.ts";
4
- import { renderAccentRailEditorFrame } from "../../layouts/editor/accent-rail-editor.ts";
5
4
  import { sanitizeEditorMetadataText } from "../../layouts/editor/editor-metadata-format.ts";
6
5
  import { renderMinimalistFrame } from "../../layouts/editor/minimalist-editor.ts";
7
6
  import { renderPolishedEditorFrame } from "../../layouts/editor/ui.ts";
@@ -61,16 +60,7 @@ export function renderEditorSettingsPreview(
61
60
  ? { above: "2", below: "3" }
62
61
  : undefined;
63
62
  let frame: string[];
64
- if (editor.style === "accent-rail") {
65
- frame = renderAccentRailEditorFrame({
66
- width: previewWidth,
67
- editorLines,
68
- autocompleteLines,
69
- viewport,
70
- uiTheme: theme,
71
- config: safeConfig,
72
- });
73
- } else if (editor.style === "minimalist") {
63
+ if (editor.style === "minimalist") {
74
64
  frame = renderMinimalistFrame({
75
65
  width: previewWidth,
76
66
  editorLines,
@@ -86,8 +76,6 @@ export function renderEditorSettingsPreview(
86
76
  costLabel: "$.12",
87
77
  modelLabel,
88
78
  thinkingLevel: "high",
89
- contextPercent: 75,
90
- contextWindow: 372_000,
91
79
  sessionName: "Preview",
92
80
  agentDurationMs: 12_000,
93
81
  agentActive: true,
@@ -24,11 +24,7 @@ export type { IconMode } from "../../shared/icons.ts";
24
24
  export type ContextStyle = "text" | "gauge" | "text+gauge";
25
25
  export type SeparatorStyle = "pipe" | "dot" | "chevron" | "none";
26
26
  export type ModelLabelSource = "id" | "name";
27
- export type EditorStyle =
28
- | "opencode"
29
- | "opencode-copy-friendly"
30
- | "accent-rail"
31
- | "minimalist";
27
+ export type EditorStyle = "opencode" | "minimalist";
32
28
  export type UserMessageStyle =
33
29
  | "framed"
34
30
  | "framed-copy-friendly"
@@ -49,7 +45,6 @@ export type ComponentStyleOwner =
49
45
  | "selectorBorders"
50
46
  | "footer";
51
47
  export type MinimalistPathDisplayMode = "compact" | "project" | "full";
52
- export type MinimalistContextFormat = "percent" | "percent-total";
53
48
  export type EditorBorderColorMode = "static" | "adaptive";
54
49
  export type CompletionMenuStyle = "native" | "palette";
55
50
  export type CompactFooterMaxLines = 1 | 2 | 3 | "unlimited";
@@ -113,26 +108,12 @@ export type PolishedEditorStyleConfig = {
113
108
  completionMenu: CompletionMenuStyle;
114
109
  };
115
110
 
116
- export type PolishedCopyFriendlyEditorStyleConfig = {
117
- metadataFormat: string;
118
- completionMenu: CompletionMenuStyle;
119
- };
120
-
121
- export type AccentRailEditorStyleConfig = {
122
- rail: string;
123
- asciiRail: string;
124
- transparent: boolean;
125
- };
126
-
127
111
  export type MinimalistEditorStyleConfig = {
128
112
  pathDisplay: MinimalistPathDisplayMode;
129
- contextFormat: MinimalistContextFormat;
130
- contextGauge: boolean;
131
113
  showSessionName: boolean;
132
114
  showTimer: boolean;
133
115
  showCost: boolean;
134
116
  showGit: boolean;
135
- contextThresholds: ContextThresholds;
136
117
  };
137
118
 
138
119
  /** Temporary name retained for existing settings consumers. */
@@ -151,8 +132,6 @@ export type EditorComponentConfig = {
151
132
  viewportIndicators: boolean;
152
133
  styles: {
153
134
  opencode: PolishedEditorStyleConfig;
154
- "opencode-copy-friendly": PolishedCopyFriendlyEditorStyleConfig;
155
- "accent-rail": AccentRailEditorStyleConfig;
156
135
  minimalist: MinimalistEditorStyleConfig;
157
136
  };
158
137
  };
@@ -323,8 +302,6 @@ export type PolishedTuiColors = {
323
302
  time: ColorSpec;
324
303
  os: ColorSpec;
325
304
  editorAccent?: ColorSpec;
326
- editorRail?: ColorSpec;
327
- editorPrompt?: ColorSpec;
328
305
  editorBorder?: ColorSpec;
329
306
  editorGitBranch?: ColorSpec;
330
307
  editorModel?: ColorSpec;
@@ -439,21 +416,12 @@ const defaultFooterSegments: FooterSegmentsConfig = {
439
416
 
440
417
  const DEFAULT_COMPLETION_MENU: CompletionMenuStyle = "palette";
441
418
 
442
- const defaultAccentRailStyle: AccentRailEditorStyleConfig = {
443
- rail: "▎",
444
- asciiRail: "|",
445
- transparent: false,
446
- };
447
-
448
419
  const defaultMinimalistStyle: MinimalistEditorStyleConfig = {
449
420
  pathDisplay: "compact",
450
- contextFormat: "percent",
451
- contextGauge: false,
452
421
  showSessionName: true,
453
422
  showTimer: true,
454
423
  showCost: true,
455
424
  showGit: true,
456
- contextThresholds: { warning: 70, error: 90 },
457
425
  };
458
426
 
459
427
  const defaultStarshipStyle: StarshipFooterStyleConfig = {
@@ -489,11 +457,6 @@ const defaultComponents: ComponentsConfig = {
489
457
  metadataFormat: DEFAULT_EDITOR_METADATA_FORMAT,
490
458
  completionMenu: DEFAULT_COMPLETION_MENU,
491
459
  },
492
- "opencode-copy-friendly": {
493
- metadataFormat: DEFAULT_EDITOR_METADATA_FORMAT,
494
- completionMenu: DEFAULT_COMPLETION_MENU,
495
- },
496
- "accent-rail": defaultAccentRailStyle,
497
460
  minimalist: defaultMinimalistStyle,
498
461
  },
499
462
  },
@@ -615,14 +578,7 @@ function parseEditorModelLabel(
615
578
  }
616
579
 
617
580
  function parseEditorStyle(value: unknown): EditorStyle {
618
- if (
619
- value === "opencode" ||
620
- value === "opencode-copy-friendly" ||
621
- value === "accent-rail" ||
622
- value === "minimalist"
623
- ) {
624
- return value;
625
- }
581
+ if (value === "opencode" || value === "minimalist") return value;
626
582
  return defaultComponents.editor.style;
627
583
  }
628
584
 
@@ -775,8 +731,6 @@ function normalizeColors(
775
731
  time: colorValue(record, "time"),
776
732
  os: colorValue(record, "os"),
777
733
  editorAccent: colorValue(record, "editorAccent"),
778
- editorRail: colorValue(record, "editorRail"),
779
- editorPrompt: colorValue(record, "editorPrompt"),
780
734
  editorBorder: colorValue(record, "editorBorder"),
781
735
  editorGitBranch: colorValue(record, "editorGitBranch"),
782
736
  editorModel: colorValue(record, "editorModel"),
@@ -1074,10 +1028,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
1074
1028
  const editor = recordValue(components.editor);
1075
1029
  const editorStyles = recordValue(editor.styles);
1076
1030
  const opencode = recordValue(editorStyles.opencode);
1077
- const opencodeCopyFriendly = recordValue(
1078
- editorStyles["opencode-copy-friendly"],
1079
- );
1080
- const accentRail = recordValue(editorStyles["accent-rail"]);
1081
1031
  const minimalist = recordValue(editorStyles.minimalist);
1082
1032
  const userMessages = recordValue(components.userMessages);
1083
1033
  const workingLine = recordValue(components.workingLine);
@@ -1113,29 +1063,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
1113
1063
  ),
1114
1064
  completionMenu: parseCompletionMenuStyle(opencode.completionMenu),
1115
1065
  },
1116
- "opencode-copy-friendly": {
1117
- metadataFormat: parseNonEmptyString(
1118
- opencodeCopyFriendly.metadataFormat,
1119
- DEFAULT_EDITOR_METADATA_FORMAT,
1120
- ),
1121
- completionMenu: parseCompletionMenuStyle(
1122
- opencodeCopyFriendly.completionMenu,
1123
- ),
1124
- },
1125
- "accent-rail": {
1126
- rail: parseNonEmptyString(
1127
- accentRail.rail,
1128
- defaultAccentRailStyle.rail,
1129
- ),
1130
- asciiRail: parseNonEmptyString(
1131
- accentRail.asciiRail,
1132
- defaultAccentRailStyle.asciiRail,
1133
- ),
1134
- transparent: parseBoolean(
1135
- accentRail.transparent,
1136
- defaultAccentRailStyle.transparent,
1137
- ),
1138
- },
1139
1066
  minimalist: {
1140
1067
  pathDisplay:
1141
1068
  minimalist.pathDisplay === "compact" ||
@@ -1143,15 +1070,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
1143
1070
  minimalist.pathDisplay === "full"
1144
1071
  ? minimalist.pathDisplay
1145
1072
  : defaultMinimalistStyle.pathDisplay,
1146
- contextFormat:
1147
- minimalist.contextFormat === "percent" ||
1148
- minimalist.contextFormat === "percent-total"
1149
- ? minimalist.contextFormat
1150
- : defaultMinimalistStyle.contextFormat,
1151
- contextGauge: parseBoolean(
1152
- minimalist.contextGauge,
1153
- defaultMinimalistStyle.contextGauge,
1154
- ),
1155
1073
  showSessionName: parseBoolean(
1156
1074
  minimalist.showSessionName,
1157
1075
  defaultMinimalistStyle.showSessionName,
@@ -1168,10 +1086,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
1168
1086
  minimalist.showGit,
1169
1087
  defaultMinimalistStyle.showGit,
1170
1088
  ),
1171
- contextThresholds: resolveContextThresholds(
1172
- minimalist.contextThresholds,
1173
- defaultMinimalistStyle.contextThresholds,
1174
- ),
1175
1089
  },
1176
1090
  },
1177
1091
  },
@@ -1349,16 +1263,17 @@ const unsupportedComponentStyles = new WeakMap<
1349
1263
  ReadonlySet<ComponentStyleOwner>
1350
1264
  >();
1351
1265
 
1266
+ // Retired selections migrate to Opencode instead of disabling the custom Editor.
1267
+ const retiredEditorStyleIds: ReadonlySet<string> = new Set([
1268
+ "opencode-copy-friendly",
1269
+ "accent-rail",
1270
+ ]);
1271
+
1352
1272
  const knownComponentStyleIds: Record<
1353
1273
  ComponentStyleOwner,
1354
1274
  ReadonlySet<string>
1355
1275
  > = {
1356
- editor: new Set([
1357
- "opencode",
1358
- "opencode-copy-friendly",
1359
- "accent-rail",
1360
- "minimalist",
1361
- ]),
1276
+ editor: new Set(["opencode", "minimalist"]),
1362
1277
  userMessages: new Set([
1363
1278
  "framed",
1364
1279
  "framed-copy-friendly",
@@ -1378,7 +1293,8 @@ function unsupportedSelectedStyleId(
1378
1293
  const style = component.style;
1379
1294
  return typeof style === "string" &&
1380
1295
  style.trim() &&
1381
- !knownComponentStyleIds[owner].has(style)
1296
+ !knownComponentStyleIds[owner].has(style) &&
1297
+ !(owner === "editor" && retiredEditorStyleIds.has(style))
1382
1298
  ? style
1383
1299
  : undefined;
1384
1300
  }
@@ -1580,50 +1496,16 @@ export function savePolishedEditorStylePatch(
1580
1496
  }, path);
1581
1497
  }
1582
1498
 
1583
- export function savePolishedCopyFriendlyEditorStylePatch(
1584
- patch: Partial<PolishedCopyFriendlyEditorStyleConfig>,
1585
- path = configPath,
1586
- ): PolishedTuiConfig {
1587
- return saveComponentsMutation((components) => {
1588
- const style = components.editor.styles["opencode-copy-friendly"];
1589
- if (patch.metadataFormat !== undefined)
1590
- style.metadataFormat = patch.metadataFormat;
1591
- if (patch.completionMenu !== undefined)
1592
- style.completionMenu = patch.completionMenu;
1593
- }, path);
1594
- }
1595
-
1596
- export function saveAccentRailEditorStylePatch(
1597
- patch: Partial<AccentRailEditorStyleConfig>,
1598
- path = configPath,
1599
- ): PolishedTuiConfig {
1600
- return saveComponentsMutation((components) => {
1601
- const style = components.editor.styles["accent-rail"];
1602
- if (patch.rail !== undefined) style.rail = patch.rail;
1603
- if (patch.asciiRail !== undefined) style.asciiRail = patch.asciiRail;
1604
- if (patch.transparent !== undefined) style.transparent = patch.transparent;
1605
- }, path);
1606
- }
1607
-
1608
1499
  function applyMinimalistStylePatch(
1609
1500
  style: MinimalistEditorStyleConfig,
1610
1501
  patch: Partial<MinimalistEditorStyleConfig>,
1611
1502
  ): void {
1612
1503
  if (patch.pathDisplay !== undefined) style.pathDisplay = patch.pathDisplay;
1613
- if (patch.contextFormat !== undefined)
1614
- style.contextFormat = patch.contextFormat;
1615
- if (patch.contextGauge !== undefined) style.contextGauge = patch.contextGauge;
1616
1504
  if (patch.showSessionName !== undefined)
1617
1505
  style.showSessionName = patch.showSessionName;
1618
1506
  if (patch.showTimer !== undefined) style.showTimer = patch.showTimer;
1619
1507
  if (patch.showCost !== undefined) style.showCost = patch.showCost;
1620
1508
  if (patch.showGit !== undefined) style.showGit = patch.showGit;
1621
- if (patch.contextThresholds !== undefined) {
1622
- style.contextThresholds = {
1623
- ...style.contextThresholds,
1624
- ...patch.contextThresholds,
1625
- };
1626
- }
1627
1509
  }
1628
1510
 
1629
1511
  export function saveMinimalistEditorStylePatch(
@@ -1912,10 +1794,6 @@ export function saveContextThresholdsPatch(
1912
1794
  throw new TypeError("Context thresholds must be JSON-serializable numbers");
1913
1795
  }
1914
1796
  return saveComponentsMutation((components) => {
1915
- components.editor.styles.minimalist.contextThresholds = {
1916
- ...components.editor.styles.minimalist.contextThresholds,
1917
- ...thresholds,
1918
- };
1919
1797
  components.footer.styles.starship.contextThresholds = {
1920
1798
  ...components.footer.styles.starship.contextThresholds,
1921
1799
  ...thresholds,
@@ -40,12 +40,7 @@ import { overlayManager } from "./overlay/overlay-manager.ts";
40
40
  import { ownerFor } from "./ownership.ts";
41
41
  import { applyPreset, PRESET_VALUES, type Preset } from "./presets.ts";
42
42
 
43
- const EDITOR_STYLES: EditorStyle[] = [
44
- "opencode",
45
- "opencode-copy-friendly",
46
- "accent-rail",
47
- "minimalist",
48
- ];
43
+ const EDITOR_STYLES: EditorStyle[] = ["opencode", "minimalist"];
49
44
  const MESSAGE_STYLES: UserMessageStyle[] = [
50
45
  "framed",
51
46
  "framed-copy-friendly",
@@ -7,7 +7,6 @@ import registerContext, {
7
7
  type ContextExtensionOptions,
8
8
  type ContextRuntimeController,
9
9
  } from "../../layouts/context/index.ts";
10
- import type { AccentRailLayoutPatchDiagnostic } from "../../layouts/editor/accent-rail-layout-patch.ts";
11
10
  import { EditorLayoutController } from "../../layouts/editor/controller.ts";
12
11
  import { FooterLayoutController } from "../../layouts/footer/controller.ts";
13
12
  import registerHeaderLayout from "../../layouts/header/index.ts";
@@ -240,17 +239,6 @@ function createLayoutRuntime(
240
239
  let minimalistProjectRoot: string | undefined;
241
240
  let activeTuiContext: ExtensionContext | undefined;
242
241
 
243
- const recordAccentRailLayoutPatchDiagnostic = (
244
- diagnostic: AccentRailLayoutPatchDiagnostic,
245
- version?: string,
246
- ) => {
247
- if (process.env.ZENTUI_DEBUG === "1") {
248
- console.error(
249
- `[zentui] Accent Rail fullscreen layout patch: ${diagnostic}${version ? ` (Pi TUI ${version})` : ""}`,
250
- );
251
- }
252
- };
253
-
254
242
  /**
255
243
  * Requests redraws from the Editor controller and shared render seam.
256
244
  */
@@ -297,16 +285,6 @@ function createLayoutRuntime(
297
285
  sessionLifecycle,
298
286
  render: { request: () => footerController.requestRender() },
299
287
  getThinkingLevel,
300
- getContextWindow: (ctx) =>
301
- ctx.model?.contextWindow ?? ctx.getContextUsage()?.contextWindow,
302
- getContextPercent: (ctx) => {
303
- const usage = ctx.getContextUsage();
304
- const contextWindow = ctx.model?.contextWindow ?? usage?.contextWindow;
305
- const live = liveContext.get();
306
- return live && contextWindow && contextWindow > 0
307
- ? (live.tokens / contextWindow) * 100
308
- : (usage?.percent ?? undefined);
309
- },
310
288
  getAgentDurationMs: () => workingLineController.duration().elapsedMs() ?? 0,
311
289
  isAgentActive: () => workingLineController.isAgentActive(),
312
290
  isAgentDurationActive: () => workingLineController.duration().isActive(),
@@ -317,7 +295,6 @@ function createLayoutRuntime(
317
295
  if (activeTuiContext) projectRefreshService.reconcile(activeTuiContext);
318
296
  },
319
297
  onModelLabelChanged: (ctx) => syncFooterState(ctx),
320
- recordLayoutDiagnostic: recordAccentRailLayoutPatchDiagnostic,
321
298
  });
322
299
  const syncFooterState = (ctx: ExtensionContext) => sessionState.sync(ctx);
323
300
  const projectRefreshService = new ProjectRefreshService({
@@ -427,10 +404,8 @@ function createLayoutRuntime(
427
404
  * @param coordinator Shared lifecycle event coordinator.
428
405
  */
429
406
  const installEventHandlers = (coordinator: EventCoordinator): void => {
430
- coordinator.on("session_start", async (_event, ctx) => {
407
+ coordinator.on("session_start", (_event, ctx) => {
431
408
  sessionLifecycle.start();
432
- await editorController.startSession(ctx);
433
- if (!sessionLifecycle.isCurrent()) return;
434
409
  liveContext.startSession();
435
410
  sessionState.startSession();
436
411
  minimalistProjectRoot = undefined;
@@ -9,11 +9,6 @@ import {
9
9
  import type { RenderScheduler } from "../../app/runtime/render-scheduler.ts";
10
10
  import type { SessionLifecycle } from "../../app/runtime/session-lifecycle.ts";
11
11
  import type { FooterState } from "../footer/index.ts";
12
- import {
13
- type AccentRailLayoutPatchDiagnostic,
14
- installHostAccentRailLayoutPatch,
15
- retainAccentRailLayoutPatchInstallation,
16
- } from "./accent-rail-layout-patch.ts";
17
12
  import {
18
13
  type EditorTransferFailureReason,
19
14
  replaceEditorComponentWithExpandedText,
@@ -41,8 +36,6 @@ export type EditorLayoutControllerContext = {
41
36
  readonly sessionLifecycle: SessionLifecycle;
42
37
  readonly render: Pick<RenderScheduler, "request">;
43
38
  readonly getThinkingLevel: () => ReturnType<ExtensionAPI["getThinkingLevel"]>;
44
- readonly getContextWindow: (ctx: ExtensionContext) => number | undefined;
45
- readonly getContextPercent: (ctx: ExtensionContext) => number | undefined;
46
39
  readonly getAgentDurationMs: () => number;
47
40
  readonly isAgentActive: () => boolean;
48
41
  readonly isAgentDurationActive: () => boolean;
@@ -50,10 +43,6 @@ export type EditorLayoutControllerContext = {
50
43
  readonly getProjectRoot: () => string | undefined;
51
44
  readonly onProjectRequirementChanged: () => void;
52
45
  readonly onModelLabelChanged: (ctx: ExtensionContext) => void;
53
- readonly recordLayoutDiagnostic: (
54
- diagnostic: AccentRailLayoutPatchDiagnostic,
55
- version?: string,
56
- ) => void;
57
46
  };
58
47
 
59
48
  type EditorInstallMode = "none" | "standalone" | "wrapper";
@@ -73,8 +62,6 @@ export class EditorLayoutController {
73
62
  private minimalistDecorationActive = false;
74
63
  private minimalistDurationUpdatesActive = false;
75
64
  private stopMinimalistDurationUpdates: () => void = () => {};
76
- private accentRailLayoutPatchCleanup: () => void = () => {};
77
- private accentRailLayoutPatchInstallSerial = 0;
78
65
 
79
66
  /**
80
67
  * Creates an Editor controller with shared runtime selectors.
@@ -85,37 +72,6 @@ export class EditorLayoutController {
85
72
  this.context = context;
86
73
  }
87
74
 
88
- /**
89
- * Installs the host Accent Rail patch for a new session generation.
90
- *
91
- * @param ctx Active Pi extension context.
92
- * @returns A promise that settles after patch retention is attempted.
93
- */
94
- async startSession(ctx: ExtensionContext): Promise<void> {
95
- const lifecycleGeneration =
96
- this.context.sessionLifecycle.currentGeneration();
97
- const installSerial = ++this.accentRailLayoutPatchInstallSerial;
98
- this.accentRailLayoutPatchCleanup();
99
- this.accentRailLayoutPatchCleanup = () => {};
100
- if (!this.isTuiContext(ctx)) return;
101
-
102
- const result = await retainAccentRailLayoutPatchInstallation(
103
- () => installHostAccentRailLayoutPatch(this.ownerToken),
104
- () =>
105
- this.context.sessionLifecycle.isCurrent(lifecycleGeneration) &&
106
- installSerial === this.accentRailLayoutPatchInstallSerial,
107
- (layoutPatch) => {
108
- this.accentRailLayoutPatchCleanup = layoutPatch.cleanup;
109
- this.context.recordLayoutDiagnostic(
110
- layoutPatch.diagnostic,
111
- layoutPatch.version,
112
- );
113
- },
114
- );
115
- if (result === "failed")
116
- this.context.recordLayoutDiagnostic("host-module-unavailable");
117
- }
118
-
119
75
  /**
120
76
  * Installs or reconciles the configured Editor for an active session.
121
77
  *
@@ -355,9 +311,6 @@ export class EditorLayoutController {
355
311
  }
356
312
  }
357
313
  this.clearEditorOwnership();
358
- ++this.accentRailLayoutPatchInstallSerial;
359
- this.accentRailLayoutPatchCleanup();
360
- this.accentRailLayoutPatchCleanup = () => {};
361
314
  this.activeTuiContext = undefined;
362
315
  }
363
316
 
@@ -516,8 +469,6 @@ export class EditorLayoutController {
516
469
  getConfig: this.context.getConfig,
517
470
  getState: this.context.getState,
518
471
  getThinkingLevel: this.context.getThinkingLevel,
519
- getContextWindow: this.context.getContextWindow,
520
- getContextPercent: this.context.getContextPercent,
521
472
  getAgentDurationMs: this.context.getAgentDurationMs,
522
473
  isAgentActive: this.context.isAgentActive,
523
474
  getProjectRoot: this.context.getProjectRoot,
@@ -526,11 +477,6 @@ export class EditorLayoutController {
526
477
  },
527
478
  onDecorationActive: (active) =>
528
479
  this.setMinimalistDecorationActive(active),
529
- isAccentRailActive: () =>
530
- this.context.sessionLifecycle.isCurrent() &&
531
- this.ownsActiveFactory(ctx) &&
532
- this.isEditorEnabled() &&
533
- this.context.getConfig().components.editor.style === "accent-rail",
534
480
  };
535
481
  }
536
482