@herbertgao/pi-extensions 2026.9.18 → 2026.9.20

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 (226) hide show
  1. package/README.md +20 -28
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +76 -59
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.md +76 -59
  5. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +93 -34
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +346 -117
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +24 -29
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +479 -0
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +75 -40
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1080 -229
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +232 -259
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +42 -41
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +277 -113
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +115 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +2 -2
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +47 -10
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +2 -2
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +1 -0
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +145 -190
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +24 -90
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +426 -0
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +90 -132
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +76 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  61. package/node_modules/@herbertgao/pi-cc-extensions/package.json +8 -8
  62. package/node_modules/pi-antigravity/README.md +29 -6
  63. package/node_modules/pi-antigravity/package.json +12 -7
  64. package/node_modules/pi-antigravity/src/auth/accounts.ts +327 -0
  65. package/node_modules/pi-antigravity/src/auth/index.ts +9 -0
  66. package/node_modules/pi-antigravity/src/client/client.ts +1 -1
  67. package/node_modules/pi-antigravity/src/image/image.ts +4 -4
  68. package/node_modules/pi-antigravity/src/index.ts +203 -13
  69. package/node_modules/pi-antigravity/src/search/index.ts +1 -0
  70. package/node_modules/pi-antigravity/src/search/search.ts +325 -0
  71. package/node_modules/pi-antigravity/src/stream/stream.ts +191 -14
  72. package/node_modules/pi-antigravity/src/types/enums.ts +45 -36
  73. package/node_modules/pi-antigravity/src/types/types.ts +5 -12
  74. package/node_modules/pi-antigravity/src/utils/http.ts +7 -2
  75. package/node_modules/pi-antigravity/src/utils/util.ts +31 -3
  76. package/node_modules/pi-typesafe/README.md +2 -0
  77. package/node_modules/pi-typesafe/package.json +2 -1
  78. package/node_modules/pi-web-access/CHANGELOG.md +72 -0
  79. package/node_modules/pi-web-access/README.md +34 -13
  80. package/node_modules/pi-web-access/chrome-cookies.ts +79 -25
  81. package/node_modules/pi-web-access/curator-page.ts +5 -1
  82. package/node_modules/pi-web-access/curator-server.ts +2 -0
  83. package/node_modules/pi-web-access/dist/index.js +1337 -1009
  84. package/node_modules/pi-web-access/exa.ts +20 -52
  85. package/node_modules/pi-web-access/extract.ts +41 -4
  86. package/node_modules/pi-web-access/gemini-search.ts +12 -4
  87. package/node_modules/pi-web-access/index.ts +29 -37
  88. package/node_modules/pi-web-access/openai-search.ts +35 -7
  89. package/node_modules/pi-web-access/package.json +6 -5
  90. package/node_modules/pi-web-access/page-query.ts +2 -2
  91. package/node_modules/pi-web-access/query-rewrite.ts +2 -3
  92. package/node_modules/pi-web-access/ssrf-protection.ts +27 -10
  93. package/node_modules/pi-web-access/storage.ts +48 -77
  94. package/node_modules/pi-web-access/summary-model-scope.ts +6 -77
  95. package/node_modules/pi-web-access/summary-review.ts +3 -4
  96. package/node_modules/pi-web-access/tavily.ts +67 -20
  97. package/node_modules/pi-web-access/tool-activation.ts +53 -33
  98. package/node_modules/pi-web-access/utils.ts +1 -1
  99. package/node_modules/pi-web-access/you.ts +164 -0
  100. package/node_modules/pi-web-access/zai.ts +161 -0
  101. package/package.json +7 -11
  102. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  103. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  104. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  105. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  106. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  107. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  108. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  109. package/node_modules/pi-footer/LICENSE +0 -21
  110. package/node_modules/pi-footer/README.md +0 -354
  111. package/node_modules/pi-footer/package.json +0 -68
  112. package/node_modules/pi-footer/src/cache.ts +0 -106
  113. package/node_modules/pi-footer/src/colors.ts +0 -237
  114. package/node_modules/pi-footer/src/config.ts +0 -202
  115. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  116. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  117. package/node_modules/pi-footer/src/git.ts +0 -135
  118. package/node_modules/pi-footer/src/index.ts +0 -268
  119. package/node_modules/pi-footer/src/metrics.ts +0 -141
  120. package/node_modules/pi-footer/src/presets.ts +0 -383
  121. package/node_modules/pi-footer/src/render.ts +0 -114
  122. package/node_modules/pi-footer/src/separators.ts +0 -52
  123. package/node_modules/pi-footer/src/types.ts +0 -122
  124. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  125. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  126. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  127. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  128. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  129. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  130. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  131. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  132. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  133. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  134. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  135. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  136. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  137. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  138. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  139. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  140. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  141. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  142. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  143. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  144. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  145. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  146. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  147. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  148. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  149. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  150. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  151. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  152. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  153. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  154. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  155. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  156. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  157. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  158. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  159. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  160. package/node_modules/pi-footer/src/ui.ts +0 -66
  161. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  162. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  163. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  164. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  165. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  166. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  167. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  168. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  169. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  170. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  171. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  172. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  173. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  174. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  175. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  176. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  177. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  178. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  179. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  180. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  181. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  182. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  183. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  184. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  185. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  186. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  187. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  188. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  189. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  190. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  191. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  192. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  193. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  194. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  195. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  196. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  197. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  198. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  199. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  200. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  201. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  202. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  203. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  204. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  205. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  206. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  207. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  208. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  209. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  210. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  211. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  212. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  213. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  214. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  215. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  216. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  217. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  218. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  219. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  220. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  221. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  222. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  223. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  224. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  225. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  226. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
@@ -1,75 +0,0 @@
1
- import { Key, matchesKey } from "@earendil-works/pi-tui";
2
-
3
- import { WidgetStore } from "../../widgets/store.js";
4
- import {
5
- applyGlobalMenuAction,
6
- applyGlobalSettingsAction,
7
- applyGlobalSettingsBackspace,
8
- applyGlobalSettingsTextInput,
9
- GLOBAL_MENU_ACTIONS,
10
- GLOBAL_MENU_HINT,
11
- globalMenuAction,
12
- globalMenuFields,
13
- } from "../global-menu.js";
14
- import { isPrintable, wrap } from "../helpers.js";
15
- import { Controller } from "./controller.js";
16
-
17
- export class GlobalScreen extends Controller {
18
- private selected = 0;
19
-
20
- renderScreen(width: number): string[] {
21
- const fields = globalMenuFields(this.ctx.state.store.settings);
22
- return [
23
- this.render.line(
24
- this.render.menuTitle("Global Overrides", "Configure global settings for the pi-footer"),
25
- width,
26
- ),
27
- this.render.line(this.ctx.theme.dim(GLOBAL_MENU_HINT), width),
28
- ...fields.map((field, index) => this.render.menuLine(index === this.selected, field, width)),
29
- ];
30
- }
31
-
32
- handleInput(data: string): void {
33
- if (matchesKey(data, Key.up))
34
- this.selected = wrap(this.selected - 1, GLOBAL_MENU_ACTIONS.length);
35
- else if (matchesKey(data, Key.down))
36
- this.selected = wrap(this.selected + 1, GLOBAL_MENU_ACTIONS.length);
37
- else if (matchesKey(data, Key.left)) this.adjust(-1);
38
- else if (matchesKey(data, Key.right) || matchesKey(data, Key.enter)) this.adjust(1);
39
- else if (matchesKey(data, Key.backspace)) this.applyBackspace();
40
- else if (isPrintable(data)) this.applyTextInput(data);
41
- }
42
-
43
- private adjust(delta: number): void {
44
- const action = globalMenuAction(this.selected);
45
- const settings = this.ctx.state.store.settings;
46
-
47
- if (!applyGlobalSettingsAction(settings, action, delta)) {
48
- this.ctx.state.store = WidgetStore.fromConfig(
49
- applyGlobalMenuAction(this.ctx.state.store.toConfig(), action, delta),
50
- );
51
- }
52
-
53
- this.ctx.emitChange();
54
- }
55
-
56
- private applyTextInput(data: string): void {
57
- if (
58
- !applyGlobalSettingsTextInput(
59
- this.ctx.state.store.settings,
60
- globalMenuAction(this.selected),
61
- data,
62
- )
63
- )
64
- return;
65
- this.ctx.emitChange();
66
- }
67
-
68
- private applyBackspace(): void {
69
- if (
70
- !applyGlobalSettingsBackspace(this.ctx.state.store.settings, globalMenuAction(this.selected))
71
- )
72
- return;
73
- this.ctx.emitChange();
74
- }
75
- }
@@ -1,108 +0,0 @@
1
- import { Key, matchesKey } from "@earendil-works/pi-tui";
2
-
3
- import { registry } from "../../widgets/registry.js";
4
- import { wrap } from "../helpers.js";
5
- import { LINE_LIST_HINT, lineListCountLabel, lineListItemLabel } from "../line-list.js";
6
- import type { ScreenView } from "../model.js";
7
- import { pageSelection, scrollWindow } from "../navigation.js";
8
- import type { ScreenContext } from "../screen-context.js";
9
- import type { ScreenRender } from "../screen-render.js";
10
- import { addLineAfter, cloneLineAfter, deleteLine, moveLine } from "../widget-actions.js";
11
- import { Controller } from "./controller.js";
12
-
13
- export class LineListScreen extends Controller {
14
- constructor(
15
- ctx: ScreenContext,
16
- render: ScreenRender,
17
- private readonly title: string,
18
- private readonly nextView: ScreenView,
19
- ) {
20
- super(ctx, render);
21
- }
22
-
23
- renderScreen(width: number): string[] {
24
- const visibleCount = this.ctx.visibleRowCount();
25
- const { start, end } = scrollWindow(
26
- this.ctx.state.store.lines.length,
27
- this.ctx.state.selectedLine,
28
- visibleCount,
29
- );
30
- const visible = this.ctx.state.store.lines.slice(start, end);
31
- const lines = [
32
- this.render.line(
33
- this.render.menuTitle(this.title, "Choose which status line to configure"),
34
- width,
35
- ),
36
- this.render.line(this.ctx.theme.dim(LINE_LIST_HINT), width),
37
- this.render.line(
38
- this.ctx.theme.dim(lineListCountLabel(this.ctx.state.store.lines.length, start, end)),
39
- width,
40
- ),
41
- ];
42
- visible.forEach((line, offset) => {
43
- const index = start + offset;
44
- const text = lineListItemLabel(index, line.length, (value) => this.ctx.theme.dim(value));
45
- lines.push(this.render.menuLine(index === this.ctx.state.selectedLine, text, width));
46
- });
47
- return lines;
48
- }
49
-
50
- handleInput(data: string): void {
51
- if (matchesKey(data, Key.up))
52
- this.ctx.state.selectedLine = wrap(
53
- this.ctx.state.selectedLine - 1,
54
- this.ctx.state.store.lines.length,
55
- );
56
- else if (matchesKey(data, Key.down))
57
- this.ctx.state.selectedLine = wrap(
58
- this.ctx.state.selectedLine + 1,
59
- this.ctx.state.store.lines.length,
60
- );
61
- else if (matchesKey(data, Key.pageUp)) this.page(-1);
62
- else if (matchesKey(data, Key.pageDown)) this.page(1);
63
- else if (matchesKey(data, Key.enter)) {
64
- this.ctx.state.selectedWidget = 0;
65
- this.ctx.show(this.nextView);
66
- } else if (data === "a") {
67
- this.ctx.state.selectedLine = addLineAfter(
68
- this.ctx.state.store.lines,
69
- this.ctx.state.selectedLine,
70
- );
71
- this.ctx.emitChange();
72
- } else if (data === "c") {
73
- this.ctx.state.selectedLine = cloneLineAfter(
74
- this.ctx.state.store.lines,
75
- this.ctx.state.selectedLine,
76
- (widget) => registry.cloneWidget(widget),
77
- );
78
- this.ctx.emitChange();
79
- } else if (data === "w") this.move(-1);
80
- else if (data === "s") this.move(1);
81
- else if (data === "d") this.delete();
82
- }
83
-
84
- private page(delta: -1 | 1): void {
85
- this.ctx.state.selectedLine = pageSelection(
86
- this.ctx.state.selectedLine,
87
- this.ctx.state.store.lines.length,
88
- this.ctx.visibleRowCount(),
89
- delta,
90
- );
91
- }
92
-
93
- private move(delta: number): void {
94
- const next = moveLine(this.ctx.state.store.lines, this.ctx.state.selectedLine, delta);
95
- if (next === this.ctx.state.selectedLine) return;
96
- this.ctx.state.selectedLine = next;
97
- this.ctx.emitChange();
98
- }
99
-
100
- private delete(): void {
101
- const previousLength = this.ctx.state.store.lines.length;
102
- this.ctx.state.selectedLine = deleteLine(
103
- this.ctx.state.store.lines,
104
- this.ctx.state.selectedLine,
105
- );
106
- if (this.ctx.state.store.lines.length !== previousLength) this.ctx.emitChange();
107
- }
108
- }
@@ -1,99 +0,0 @@
1
- import { Key, matchesKey } from "@earendil-works/pi-tui";
2
-
3
- import { wrap } from "../helpers.js";
4
- import type { ScreenView } from "../model.js";
5
- import { Controller } from "./controller.js";
6
-
7
- type MenuAction =
8
- | { type: "view"; view: ScreenView }
9
- | { type: "save-exit" }
10
- | { type: "discard-exit" };
11
-
12
- interface MenuItem {
13
- label: string;
14
- description: string;
15
- action: MenuAction;
16
- }
17
-
18
- const HINT = "↑/↓ select • enter option • ctrl+s save • esc exit";
19
-
20
- const ITEMS: readonly MenuItem[] = [
21
- {
22
- label: "Edit lines",
23
- description: "Manage status lines and line widgets",
24
- action: { type: "view", view: "line-list" },
25
- },
26
- {
27
- label: "Edit colors",
28
- description: "Configure per-widget foreground/background/bold",
29
- action: { type: "view", view: "color-line-list" },
30
- },
31
- {
32
- label: "Terminal Options",
33
- description: "Terminal width and color level",
34
- action: { type: "view", view: "terminal" },
35
- },
36
- {
37
- label: "Global Overrides",
38
- description: "Global presets, separators, icons, minimalist mode",
39
- action: { type: "view", view: "global" },
40
- },
41
- {
42
- label: "Pi extensions",
43
- description: "Published statuses and extension status row visibility",
44
- action: { type: "view", view: "extension-status-row" },
45
- },
46
- {
47
- label: "Save & Exit",
48
- description: "Persist changes and close the configuration UI",
49
- action: { type: "save-exit" },
50
- },
51
- {
52
- label: "Exit without saving",
53
- description: "Discard unsaved changes and close immediately",
54
- action: { type: "discard-exit" },
55
- },
56
- ];
57
-
58
- export class MainScreen extends Controller {
59
- private selected = 0;
60
-
61
- renderScreen(width: number): string[] {
62
- return [
63
- this.render.line(
64
- this.render.menuTitle(
65
- "Main Menu",
66
- "Configure any number of status lines with various widgets",
67
- ),
68
- width,
69
- ),
70
- this.render.line(this.ctx.theme.dim(HINT), width),
71
- ...ITEMS.map((item, index) =>
72
- this.render.menuLine(
73
- index === this.selected,
74
- `${item.label} ${this.ctx.theme.dim(item.description)}`,
75
- width,
76
- ),
77
- ),
78
- ];
79
- }
80
-
81
- handleInput(data: string): void {
82
- if (matchesKey(data, Key.up)) this.selected = wrap(this.selected - 1, ITEMS.length);
83
- else if (matchesKey(data, Key.down)) this.selected = wrap(this.selected + 1, ITEMS.length);
84
- else if (matchesKey(data, Key.enter)) this.applySelectedAction();
85
- }
86
-
87
- private menuAction(index: number): MenuAction | undefined {
88
- return ITEMS[index]?.action;
89
- }
90
-
91
- private applySelectedAction(): void {
92
- const action = this.menuAction(this.selected);
93
- if (!action) return;
94
-
95
- if (action.type === "view") this.ctx.show(action.view);
96
- else if (action.type === "save-exit") this.ctx.save(true);
97
- else this.ctx.exitWithoutSaving();
98
- }
99
- }
@@ -1,121 +0,0 @@
1
- import { Key, matchesKey } from "@earendil-works/pi-tui";
2
-
3
- import type { ColorLevel } from "../../colors.js";
4
- import {
5
- COLOR_LEVEL_CONFIRM_HINT,
6
- COLOR_LEVEL_CONFIRM_WARNING,
7
- colorLevelConfirmAction,
8
- colorLevelConfirmValueLabel,
9
- } from "../color-level-confirm.js";
10
- import { hasCustomAnsiColors, resetCustomAnsiColors } from "../color-options.js";
11
- import { wrap } from "../helpers.js";
12
- import type { ScreenContext } from "../screen-context.js";
13
- import type { ScreenRender } from "../screen-render.js";
14
- import {
15
- nextTerminalColorLevel,
16
- nextTerminalWidthMode,
17
- TERMINAL_MENU_ACTIONS,
18
- TERMINAL_MENU_HINT,
19
- terminalMenuAction,
20
- terminalMenuFields,
21
- } from "../terminal-menu.js";
22
- import { Controller } from "./controller.js";
23
-
24
- export class TerminalState {
25
- pendingColorLevel: ColorLevel | undefined;
26
- }
27
-
28
- export class TerminalScreen extends Controller {
29
- private selected = 0;
30
-
31
- constructor(
32
- ctx: ScreenContext,
33
- render: ScreenRender,
34
- private readonly terminalState: TerminalState,
35
- ) {
36
- super(ctx, render);
37
- }
38
-
39
- renderScreen(width: number): string[] {
40
- const fields = terminalMenuFields(this.ctx.state.store.settings);
41
- return [
42
- this.render.line(
43
- this.render.menuTitle(
44
- "Terminal Options",
45
- "Configure terminal width behavior and color level",
46
- ),
47
- width,
48
- ),
49
- this.render.line(this.ctx.theme.dim(TERMINAL_MENU_HINT), width),
50
- ...fields.map((field, index) => this.render.menuLine(index === this.selected, field, width)),
51
- ];
52
- }
53
-
54
- handleInput(data: string): void {
55
- if (matchesKey(data, Key.up))
56
- this.selected = wrap(this.selected - 1, TERMINAL_MENU_ACTIONS.length);
57
- else if (matchesKey(data, Key.down))
58
- this.selected = wrap(this.selected + 1, TERMINAL_MENU_ACTIONS.length);
59
- else if (matchesKey(data, Key.left)) this.adjust(-1);
60
- else if (matchesKey(data, Key.right) || matchesKey(data, Key.enter)) this.adjust(1);
61
- }
62
-
63
- private adjust(delta: number): void {
64
- if (terminalMenuAction(this.selected) === "width-mode") {
65
- this.ctx.state.store.settings.terminal.widthMode = nextTerminalWidthMode(
66
- this.ctx.state.store.settings,
67
- delta,
68
- );
69
- this.ctx.emitChange();
70
- return;
71
- }
72
- const settings = this.ctx.state.store.settings;
73
- const next = nextTerminalColorLevel(settings, delta);
74
- if (next !== settings.terminal.colorLevel && hasCustomAnsiColors(this.ctx.state.store.lines)) {
75
- this.terminalState.pendingColorLevel = next;
76
- this.ctx.show("confirm-color-level");
77
- return;
78
- }
79
- settings.terminal.colorLevel = next;
80
- this.ctx.emitChange();
81
- }
82
- }
83
-
84
- export class ColorLevelConfirmScreen extends Controller {
85
- constructor(
86
- ctx: ScreenContext,
87
- render: ScreenRender,
88
- private readonly terminalState: TerminalState,
89
- ) {
90
- super(ctx, render);
91
- }
92
-
93
- renderScreen(width: number): string[] {
94
- return [
95
- this.render.line(this.ctx.theme.warning(COLOR_LEVEL_CONFIRM_WARNING), width),
96
- this.render.line(colorLevelConfirmValueLabel(this.terminalState.pendingColorLevel), width),
97
- this.render.line(this.ctx.theme.dim(COLOR_LEVEL_CONFIRM_HINT), width),
98
- ];
99
- }
100
-
101
- handleInput(data: string): void {
102
- const action = colorLevelConfirmAction(
103
- data,
104
- matchesKey(data, Key.escape),
105
- matchesKey(data, Key.enter),
106
- );
107
- if (action === "cancel") {
108
- this.terminalState.pendingColorLevel = undefined;
109
- this.ctx.show("terminal");
110
- return;
111
- }
112
- if (action === "confirm") {
113
- if (this.terminalState.pendingColorLevel)
114
- this.ctx.state.store.settings.terminal.colorLevel = this.terminalState.pendingColorLevel;
115
- resetCustomAnsiColors(this.ctx.state.store.lines);
116
- this.terminalState.pendingColorLevel = undefined;
117
- this.ctx.show("terminal");
118
- this.ctx.emitChange();
119
- }
120
- }
121
- }
@@ -1,154 +0,0 @@
1
- import { Key, matchesKey } from "@earendil-works/pi-tui";
2
-
3
- import { registry } from "../../widgets/registry.js";
4
- import type { Widget } from "../../widgets/types.js";
5
- import { formatWidgetColorOptions, formatWidgetOptions } from "../fields.js";
6
- import { wrap } from "../helpers.js";
7
- import { pageSelection, scrollWindow } from "../navigation.js";
8
- import type { ScreenContext } from "../screen-context.js";
9
- import type { ScreenRender } from "../screen-render.js";
10
- import {
11
- cloneSelectedWidget,
12
- deleteSelectedWidget,
13
- moveWidget,
14
- toggleWidgetEnabled,
15
- toggleWidgetRaw,
16
- } from "../widget-actions.js";
17
- import { Controller } from "./controller.js";
18
-
19
- const HINT =
20
- "↑/↓ select • enter options • a add • c clone • w/s move • d delete • space toggle • r raw • esc back";
21
- const COLOR_HINT = "↑/↓ select • pgup/pgdn jump • enter colors • esc back";
22
-
23
- export class WidgetListScreen extends Controller {
24
- constructor(
25
- ctx: ScreenContext,
26
- render: ScreenRender,
27
- private readonly colors: boolean,
28
- ) {
29
- super(ctx, render);
30
- }
31
-
32
- renderScreen(width: number): string[] {
33
- const line = this.ctx.currentLine();
34
- const visibleCount = this.ctx.visibleRowCount();
35
- const { start, end } = scrollWindow(line.length, this.ctx.state.selectedWidget, visibleCount);
36
- const visible = line.slice(start, end);
37
- const lines = [
38
- this.render.line(
39
- this.render.menuTitle(
40
- `${this.colors ? "Edit widget colors" : "Edit widgets"} / Line ${this.ctx.state.selectedLine + 1}`,
41
- this.colors
42
- ? "Select a widget to edit its colors"
43
- : "Select a widget to edit its options, or add/remove/reorder widgets",
44
- ),
45
- width,
46
- ),
47
- this.render.line(this.ctx.theme.dim(this.colors ? COLOR_HINT : HINT), width),
48
- this.render.line(this.ctx.theme.dim(this.countLabel(line.length, start, end)), width),
49
- ];
50
- if (line.length === 0)
51
- lines.push(
52
- this.render.line(this.ctx.theme.warning("Empty line. Press a to add a widget."), width),
53
- );
54
- visible.forEach((widget, offset) => {
55
- const index = start + offset;
56
- const text = this.colors ? this.colorItemLabel(index, widget) : this.itemLabel(index, widget);
57
- lines.push(this.render.menuLine(index === this.ctx.state.selectedWidget, text, width));
58
- });
59
- return lines;
60
- }
61
-
62
- handleInput(data: string): void {
63
- const line = this.ctx.currentLine();
64
- if (matchesKey(data, Key.up))
65
- this.ctx.state.selectedWidget = wrap(
66
- this.ctx.state.selectedWidget - 1,
67
- Math.max(1, line.length),
68
- );
69
- else if (matchesKey(data, Key.down))
70
- this.ctx.state.selectedWidget = wrap(
71
- this.ctx.state.selectedWidget + 1,
72
- Math.max(1, line.length),
73
- );
74
- else if (matchesKey(data, Key.pageUp)) this.page(line.length, -1);
75
- else if (matchesKey(data, Key.pageDown)) this.page(line.length, 1);
76
- else if (this.colors && matchesKey(data, Key.enter)) this.ctx.show("edit-colors");
77
- else if (!this.colors) this.handleEditListInput(data);
78
- }
79
-
80
- private countLabel(total: number, start: number, end: number): string {
81
- const range = total === 0 ? "0-0" : `${start + 1}-${end}`;
82
- return `${total} widget(s), showing ${range}`;
83
- }
84
-
85
- private itemLabel(index: number, widget: Widget): string {
86
- const enabled = widget.enabled ? this.ctx.theme.success("on ") : this.ctx.theme.dim("off");
87
- const indexPad = index < 9 ? " " : "";
88
- const options = this.ctx.theme.dim(formatWidgetOptions(widget));
89
- return `${enabled} ${index + 1}.${indexPad} ${registry.spec(widget.type).label} ${options}`;
90
- }
91
-
92
- private colorItemLabel(index: number, widget: Widget): string {
93
- const enabled = widget.enabled ? this.ctx.theme.success("on ") : this.ctx.theme.dim("off");
94
- const indexPad = index < 9 ? " " : "";
95
- const options = this.ctx.theme.dim(formatWidgetColorOptions(widget));
96
- return `${enabled} ${index + 1}.${indexPad} ${registry.spec(widget.type).label} ${options}`;
97
- }
98
-
99
- private handleEditListInput(data: string): void {
100
- if (data === "a") this.ctx.show("add-widget");
101
- else if (matchesKey(data, Key.enter) || data === "e") this.ctx.show("edit-widget");
102
- else if (data === "c") this.cloneCurrentWidget();
103
- else if (data === "w") this.moveWidget(-1);
104
- else if (data === "s") this.moveWidget(1);
105
- else if (data === "d") this.deleteCurrentWidget();
106
- else if (matchesKey(data, Key.space)) this.toggleCurrentWidget();
107
- else if (data === "r") this.toggleCurrentWidgetRaw();
108
- }
109
-
110
- private page(length: number, delta: -1 | 1): void {
111
- this.ctx.state.selectedWidget = pageSelection(
112
- this.ctx.state.selectedWidget,
113
- length,
114
- this.ctx.visibleRowCount(),
115
- delta,
116
- );
117
- }
118
-
119
- private moveWidget(delta: number): void {
120
- const next = moveWidget(this.ctx.currentLine(), this.ctx.state.selectedWidget, delta);
121
- if (next === this.ctx.state.selectedWidget) return;
122
- this.ctx.state.selectedWidget = next;
123
- this.ctx.emitChange();
124
- }
125
-
126
- private cloneCurrentWidget(): void {
127
- const next = cloneSelectedWidget(
128
- this.ctx.currentLine(),
129
- this.ctx.state.selectedWidget,
130
- (widget) => registry.cloneWidget(widget),
131
- );
132
- if (next === this.ctx.state.selectedWidget) return;
133
- this.ctx.state.selectedWidget = next;
134
- this.ctx.emitChange();
135
- }
136
-
137
- private deleteCurrentWidget(): void {
138
- const line = this.ctx.currentLine();
139
- const previousLength = line.length;
140
- this.ctx.state.selectedWidget = deleteSelectedWidget(line, this.ctx.state.selectedWidget);
141
- if (line.length === previousLength) return;
142
- this.ctx.emitChange();
143
- }
144
-
145
- private toggleCurrentWidget(): void {
146
- if (!toggleWidgetEnabled(this.ctx.currentWidget())) return;
147
- this.ctx.emitChange();
148
- }
149
-
150
- private toggleCurrentWidgetRaw(): void {
151
- if (!toggleWidgetRaw(this.ctx.currentWidget())) return;
152
- this.ctx.emitChange();
153
- }
154
- }
@@ -1,32 +0,0 @@
1
- import { COLOR_LEVEL_VALUES, type ColorLevel } from "../colors.js";
2
- import { TERMINAL_WIDTH_MODE_VALUES, type StatuslineSettings } from "../types.js";
3
- import { cycle } from "./helpers.js";
4
- import { COLOR_LEVEL_LABELS, WIDTH_MODE_LABELS } from "./model.js";
5
-
6
- export const TERMINAL_MENU_ACTIONS = ["width-mode", "color-level"] as const;
7
-
8
- type TerminalMenuAction = (typeof TERMINAL_MENU_ACTIONS)[number];
9
-
10
- export const TERMINAL_MENU_HINT = "↑/↓ option • ←/→ change • esc back";
11
-
12
- export function terminalMenuFields(config: StatuslineSettings): string[] {
13
- return [
14
- `Terminal Width: ${WIDTH_MODE_LABELS[config.terminal.widthMode]}`,
15
- `Color Level: ${COLOR_LEVEL_LABELS[config.terminal.colorLevel]}`,
16
- ];
17
- }
18
-
19
- export function terminalMenuAction(index: number): TerminalMenuAction {
20
- return TERMINAL_MENU_ACTIONS[index] ?? "color-level";
21
- }
22
-
23
- export function nextTerminalWidthMode(
24
- config: StatuslineSettings,
25
- delta: number,
26
- ): StatuslineSettings["terminal"]["widthMode"] {
27
- return cycle(TERMINAL_WIDTH_MODE_VALUES, config.terminal.widthMode, delta);
28
- }
29
-
30
- export function nextTerminalColorLevel(config: StatuslineSettings, delta: number): ColorLevel {
31
- return cycle(COLOR_LEVEL_VALUES, config.terminal.colorLevel, delta);
32
- }
@@ -1,48 +0,0 @@
1
- import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
2
-
3
- import type { ConfigState } from "./config-lifecycle.js";
4
-
5
- export type ThemeProvider = () => Theme;
6
-
7
- export interface UiTheme {
8
- accent(text: string): string;
9
- dim(text: string): string;
10
- muted(text: string): string;
11
- success(text: string): string;
12
- warning(text: string): string;
13
- error(text: string): string;
14
- bold(text: string): string;
15
- selected(text: string): string;
16
- border(text: string, color?: ThemeColor): string;
17
- previewTitle(text: string): string;
18
- configStateLabel(state: ConfigState, label: string): string;
19
- }
20
-
21
- export function createUiTheme(getTheme: ThemeProvider): UiTheme {
22
- return {
23
- accent: (text) => getTheme().fg("accent", text),
24
- dim: (text) => getTheme().fg("dim", text),
25
- muted: (text) => getTheme().fg("muted", text),
26
- success: (text) => getTheme().fg("success", text),
27
- warning: (text) => getTheme().fg("warning", text),
28
- error: (text) => getTheme().fg("error", text),
29
- bold: (text) => getTheme().bold(text),
30
- selected: (text) => {
31
- const theme = getTheme();
32
- return theme.bg("selectedBg", theme.fg("accent", text));
33
- },
34
- border: (text, color = "border") => getTheme().fg(color, text),
35
- previewTitle: (text) => {
36
- const theme = getTheme();
37
- return theme.fg("accent", theme.bold(text));
38
- },
39
- configStateLabel: (state, label) => {
40
- const theme = getTheme();
41
- if (state === "saved") return theme.fg("accent", label);
42
- if (state === "dirty") return theme.bold(theme.fg("warning", label));
43
- if (state === "saving") return theme.fg("dim", label);
44
- if (state === "error") return theme.bold(theme.fg("error", label));
45
- return "";
46
- },
47
- };
48
- }