@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,122 +0,0 @@
1
- import { normalizeColor } from "../colors.js";
2
- import type { WidgetOptions } from "../types.js";
3
- import type { WidgetProperty, WidgetPropertyDefault, WidgetSpec } from "./types.js";
4
-
5
- const SYSTEM_BASE_OPTION_DEFAULTS = {
6
- raw: false,
7
- hideWhenEmpty: false,
8
- hideWhenZero: false,
9
- text: "-",
10
- icon: "",
11
- } as const;
12
-
13
- // The options-relevant slice of a spec, derived from WidgetSpec (excludes render so concrete
14
- // widget specs stay assignable — render's generic params make the full spec invariant).
15
- type WidgetOptionsSpec = Pick<
16
- WidgetSpec,
17
- "baseOptions" | "baseOptionDefaults" | "properties" | "defaultStyle" | "createOptionDefaults"
18
- >;
19
-
20
- export function defaultOptionsFromSpec(spec: WidgetOptionsSpec): WidgetOptions {
21
- const base: WidgetOptions = {};
22
-
23
- for (const option of spec.baseOptions) {
24
- const optionId: string = option;
25
- base[optionId] = SYSTEM_BASE_OPTION_DEFAULTS[option];
26
- }
27
- Object.assign(base, spec.baseOptionDefaults ?? {});
28
-
29
- for (const property of spec.properties) {
30
- base[property.id] = property.default;
31
- }
32
-
33
- const dynamicDefaults = spec.createOptionDefaults?.();
34
- if (dynamicDefaults) Object.assign(base, dynamicDefaults);
35
-
36
- if (spec.defaultStyle.fg !== undefined) base.fg = spec.defaultStyle.fg;
37
- if (spec.defaultStyle.bg !== undefined) base.bg = spec.defaultStyle.bg;
38
- if (spec.defaultStyle.bold !== undefined) base.bold = spec.defaultStyle.bold;
39
-
40
- return base;
41
- }
42
-
43
- export function sanitizeOptionsFromSpec(
44
- spec: WidgetOptionsSpec,
45
- input: Record<string, unknown>,
46
- ): WidgetOptions {
47
- const defaults = defaultOptionsFromSpec(spec);
48
- const merged: Record<string, unknown> = { ...defaults, ...input };
49
- const next: WidgetOptions = {};
50
-
51
- for (const option of spec.baseOptions) {
52
- if (!(option in defaults)) continue;
53
- const optionId: string = option;
54
- next[optionId] = sanitizeMetadataValue(merged[optionId], defaults[optionId]);
55
- }
56
-
57
- const fg = normalizeColor(merged.fg);
58
- if (fg) next.fg = fg;
59
- const bg = normalizeColor(merged.bg);
60
- if (bg) next.bg = bg;
61
- next.bold = typeof merged.bold === "boolean" ? merged.bold : Boolean(defaults.bold);
62
-
63
- for (const property of spec.properties) {
64
- next[property.id] = sanitizeWidgetProperty(property, merged[property.id]);
65
- }
66
-
67
- return next;
68
- }
69
-
70
- function sanitizeWidgetProperty(
71
- property: WidgetProperty,
72
- value: unknown,
73
- ): string | number | boolean {
74
- switch (property.kind) {
75
- case "boolean":
76
- return typeof value === "boolean" ? value : property.default;
77
- case "number":
78
- return sanitizeMetadataNumber(
79
- value,
80
- property.default,
81
- property.options?.min,
82
- property.options?.max,
83
- );
84
- case "text":
85
- if (
86
- property.id === "warningFg" ||
87
- property.id === "warningBg" ||
88
- property.id === "dangerFg" ||
89
- property.id === "dangerBg"
90
- )
91
- return normalizeColor(value) ?? property.default;
92
- return typeof value === "string" ? value : property.default;
93
- case "choice": {
94
- const choices = property.options?.choices ?? [];
95
- return typeof value === "string" && choices.some((choice) => choice.id === value)
96
- ? value
97
- : property.default;
98
- }
99
- }
100
- }
101
-
102
- function sanitizeMetadataValue(
103
- value: unknown,
104
- defaultValue: WidgetOptions[keyof WidgetOptions],
105
- ): WidgetOptions[keyof WidgetOptions] {
106
- if (typeof defaultValue === "boolean") return typeof value === "boolean" ? value : defaultValue;
107
- if (typeof defaultValue === "number")
108
- return typeof value === "number" && Number.isInteger(value) ? value : defaultValue;
109
- if (typeof defaultValue === "string") return typeof value === "string" ? value : defaultValue;
110
- return defaultValue;
111
- }
112
-
113
- function sanitizeMetadataNumber(
114
- value: unknown,
115
- defaultValue: WidgetPropertyDefault,
116
- min = Number.NEGATIVE_INFINITY,
117
- max = Number.POSITIVE_INFINITY,
118
- ): number {
119
- const numberValue = typeof value === "number" && Number.isInteger(value) ? value : defaultValue;
120
- const safeNumber = typeof numberValue === "number" ? numberValue : 0;
121
- return Math.min(max, Math.max(min, safeNumber));
122
- }
@@ -1,361 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- import { readdir } from "node:fs/promises";
3
-
4
- import type { ColorName } from "../../colors.js";
5
- import { CACHE_NAMESPACES, asyncCache } from "../../cache.js";
6
- import type { WidgetIconSet } from "../types.js";
7
- import { defineWidget } from "../types.js";
8
-
9
- const VERSION_TIMEOUT_MS = 1_000;
10
- const RUNTIME_CACHE_TTL_MS = 10_000;
11
-
12
- interface VersionCommand {
13
- command: string;
14
- args: readonly string[];
15
- parse: (output: string) => string | undefined;
16
- }
17
-
18
- interface RuntimeDefinition<TName extends string = string> {
19
- name: TName;
20
- files: readonly string[];
21
- matchesEntry?: (entry: CwdEntry) => boolean;
22
- versionCommands: readonly VersionCommand[];
23
- icons: WidgetIconSet;
24
- color: ColorName;
25
- }
26
-
27
- interface CwdEntry {
28
- name: string;
29
- isFile: boolean;
30
- }
31
-
32
- const RUNTIME_DEFINITIONS = [
33
- {
34
- name: "bun",
35
- files: ["bun.lock", "bun.lockb"],
36
- versionCommands: [
37
- {
38
- command: "bun",
39
- args: ["--version"],
40
- parse: (output) => /\bv?([0-9][^\s]*)/i.exec(output)?.[1],
41
- },
42
- ],
43
- icons: { emoji: "🥟", nerd: "", text: "" },
44
- color: "pi:warning",
45
- },
46
- {
47
- name: "deno",
48
- files: ["deno.json", "deno.jsonc", "deno.lock"],
49
- versionCommands: [
50
- {
51
- command: "deno",
52
- args: ["--version"],
53
- parse: (output) => /deno\s+([0-9][^\s]*)/i.exec(output)?.[1],
54
- },
55
- ],
56
- icons: { emoji: "🦕", nerd: "", text: "" },
57
- color: "pi:syntaxType",
58
- },
59
- {
60
- name: "lua",
61
- files: ["stylua.toml", ".stylua.toml", ".luarc.json", ".luarc.jsonc", "init.lua"],
62
- matchesEntry: (entry) => entry.name === "lua" || (entry.isFile && entry.name.endsWith(".lua")),
63
- versionCommands: [
64
- { command: "lua", args: ["-v"], parse: (output) => /Lua\s+([0-9][^\s]*)/i.exec(output)?.[1] },
65
- {
66
- command: "luajit",
67
- args: ["-v"],
68
- parse: (output) => /LuaJIT\s+([0-9][^\s]*)/i.exec(output)?.[1],
69
- },
70
- ],
71
- icons: { emoji: "🌙", nerd: "", text: "" },
72
- color: "pi:accent",
73
- },
74
- {
75
- name: "node",
76
- files: ["package.json", ".nvmrc", ".node-version"],
77
- versionCommands: [
78
- {
79
- command: "node",
80
- args: ["--version"],
81
- parse: (output) => /\bv?([0-9][^\s]*)/i.exec(output)?.[1],
82
- },
83
- ],
84
- icons: { emoji: "⬢", nerd: "", text: "" },
85
- color: "pi:success",
86
- },
87
- {
88
- name: "python",
89
- files: [
90
- "pyproject.toml",
91
- "requirements.txt",
92
- "setup.py",
93
- "setup.cfg",
94
- "Pipfile",
95
- ".python-version",
96
- ],
97
- versionCommands: [
98
- {
99
- command: "python3",
100
- args: ["--version"],
101
- parse: (output) => /Python\s+([0-9][^\s]*)/i.exec(output)?.[1],
102
- },
103
- {
104
- command: "python",
105
- args: ["--version"],
106
- parse: (output) => /Python\s+([0-9][^\s]*)/i.exec(output)?.[1],
107
- },
108
- ],
109
- icons: { emoji: "🐍", nerd: "", text: "" },
110
- color: "pi:warning",
111
- },
112
- {
113
- name: "go",
114
- files: ["go.mod"],
115
- versionCommands: [
116
- {
117
- command: "go",
118
- args: ["version"],
119
- parse: (output) => /go version go([0-9][^\s]*)/i.exec(output)?.[1],
120
- },
121
- ],
122
- icons: { emoji: "🐹", nerd: "", text: "" },
123
- color: "pi:syntaxType",
124
- },
125
- {
126
- name: "rust",
127
- files: ["Cargo.toml"],
128
- versionCommands: [
129
- {
130
- command: "rustc",
131
- args: ["--version"],
132
- parse: (output) => /rustc\s+([0-9][^\s]*)/i.exec(output)?.[1],
133
- },
134
- ],
135
- icons: { emoji: "🦀", nerd: "", text: "" },
136
- color: "pi:error",
137
- },
138
- {
139
- name: "java",
140
- files: ["pom.xml", "build.gradle", "build.gradle.kts"],
141
- versionCommands: [
142
- {
143
- command: "java",
144
- args: ["-version"],
145
- parse: (output) => /(?:openjdk|java)\s+version\s+"?([0-9][^"\s]*)/i.exec(output)?.[1],
146
- },
147
- ],
148
- icons: { emoji: "☕", nerd: "", text: "" },
149
- color: "pi:warning",
150
- },
151
- {
152
- name: "ruby",
153
- files: ["Gemfile", ".ruby-version"],
154
- versionCommands: [
155
- {
156
- command: "ruby",
157
- args: ["--version"],
158
- parse: (output) => /ruby\s+([0-9][^\s]*)/i.exec(output)?.[1],
159
- },
160
- ],
161
- icons: { emoji: "💎", nerd: "", text: "" },
162
- color: "pi:error",
163
- },
164
- {
165
- name: "php",
166
- files: ["composer.json"],
167
- versionCommands: [
168
- {
169
- command: "php",
170
- args: ["--version"],
171
- parse: (output) => /PHP\s+([0-9][^\s]*)/i.exec(output)?.[1],
172
- },
173
- ],
174
- icons: { emoji: "🐘", nerd: "", text: "" },
175
- color: "pi:accent",
176
- },
177
- ] as const satisfies readonly RuntimeDefinition[];
178
-
179
- export type RuntimeName = (typeof RUNTIME_DEFINITIONS)[number]["name"];
180
-
181
- interface RuntimeInfo {
182
- name: RuntimeName;
183
- version?: string;
184
- icons: WidgetIconSet;
185
- color: ColorName;
186
- }
187
-
188
- interface RuntimeDetection {
189
- cwd: string;
190
- displayVersion: boolean;
191
- }
192
-
193
- export const RuntimeWidget = defineWidget({
194
- type: "runtime",
195
- label: "Runtime",
196
- category: "Project",
197
- description: "Current project runtime (e.g. Bun, Python, Go, Rust)",
198
- dependencies: ["cwd"],
199
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
200
- baseOptionDefaults: { hideWhenEmpty: true },
201
- properties: [
202
- {
203
- id: "style",
204
- label: "Style",
205
- kind: "choice",
206
- description: "Display style",
207
- default: "compact",
208
- options: {
209
- choices: [
210
- { id: "default", label: "Default", list: "default" },
211
- { id: "compact", label: "Compact", list: "compact" },
212
- ],
213
- showInWidgets: true,
214
- showInColors: false,
215
- listProperty: "style",
216
- },
217
- },
218
- {
219
- id: "displayVersion",
220
- label: "Display version",
221
- kind: "boolean",
222
- description: "Show runtime version",
223
- default: true,
224
- options: {
225
- label: "with-version",
226
- showInWidgets: true,
227
- showInColors: true,
228
- listProperty: "",
229
- },
230
- },
231
- ],
232
- icons: { emoji: "⚙️", nerd: "", text: "runtime" },
233
- defaultStyle: { fg: "default", bg: "default", bold: false },
234
- render({ ctx, options, renderWidget }) {
235
- const cwd = ctx.cwd;
236
- if (cwd.length === 0) return renderWidget("");
237
-
238
- const info = asyncCache.get(
239
- CACHE_NAMESPACES.runtime,
240
- `${cwd}:${options.displayVersion ? "version" : "no-version"}`,
241
- RUNTIME_CACHE_TTL_MS,
242
- { cwd, displayVersion: options.displayVersion },
243
- detectRuntime,
244
- ctx.requestRender,
245
- );
246
- if (!info) return renderWidget("", { icons: { emoji: "", nerd: "", text: "" } });
247
-
248
- return renderWidget(renderRuntimeValue(info, options.displayVersion, options.style), {
249
- icons: info.icons,
250
- fg: options.fg && options.fg !== "default" ? options.fg : info.color,
251
- });
252
- },
253
- });
254
-
255
- function renderRuntimeValue(
256
- info: RuntimeInfo,
257
- displayVersion: boolean,
258
- style: "default" | "compact",
259
- ) {
260
- if (!displayVersion || !info.version) return info.name;
261
- if (style === "compact") return compactRuntimeVersion(info.name, info.version);
262
- return `${info.name} ${info.version}`;
263
- }
264
-
265
- function prefixRuntimeVersion(version: string) {
266
- const trimmed = version.trim();
267
- if (!trimmed) return trimmed;
268
- return trimmed.toLowerCase().startsWith("v") ? trimmed : `v${trimmed}`;
269
- }
270
-
271
- function compactRuntimeVersion(name: RuntimeName, version: string) {
272
- const prefixed = prefixRuntimeVersion(version);
273
- const match = /^v([0-9]+)(?:\.([0-9]+))?/i.exec(prefixed);
274
- if (!match) return prefixed;
275
-
276
- const major = match[1] ?? "";
277
- const minor = match[2];
278
- if ((name === "python" || name === "go" || name === "bun") && minor !== undefined)
279
- return `v${major}.${minor}`;
280
- return `v${major}`;
281
- }
282
-
283
- async function detectRuntime({
284
- cwd,
285
- displayVersion,
286
- }: RuntimeDetection): Promise<RuntimeInfo | null> {
287
- const entries = await readCwdEntries(cwd);
288
- if (!entries) return null;
289
-
290
- for (const definition of RUNTIME_DEFINITIONS) {
291
- if (!matchesRuntime(definition, entries)) continue;
292
-
293
- const version = displayVersion ? await detectVersion(definition) : undefined;
294
- return version
295
- ? {
296
- name: definition.name,
297
- version,
298
- icons: definition.icons,
299
- color: definition.color,
300
- }
301
- : {
302
- name: definition.name,
303
- icons: definition.icons,
304
- color: definition.color,
305
- };
306
- }
307
-
308
- return null;
309
- }
310
-
311
- async function readCwdEntries(cwd: string) {
312
- try {
313
- const entries = await readdir(cwd, { withFileTypes: true });
314
- return entries.map((entry) => ({ name: entry.name, isFile: entry.isFile() }));
315
- } catch {
316
- return undefined;
317
- }
318
- }
319
-
320
- function matchesRuntime(definition: RuntimeDefinition, entries: readonly CwdEntry[]) {
321
- if (hasAnyFile(entries, definition.files)) return true;
322
- return definition.matchesEntry
323
- ? entries.some((entry) => definition.matchesEntry?.(entry) === true)
324
- : false;
325
- }
326
-
327
- function hasAnyFile(entries: readonly CwdEntry[], files: readonly string[]) {
328
- const fileNames = new Set(entries.filter((entry) => entry.isFile).map((entry) => entry.name));
329
- return files.some((file) => fileNames.has(file));
330
- }
331
-
332
- async function detectVersion(definition: RuntimeDefinition) {
333
- for (const command of definition.versionCommands) {
334
- const version = await runVersion(command);
335
- if (version) return version;
336
- }
337
- return undefined;
338
- }
339
-
340
- async function runVersion(versionCommand: VersionCommand) {
341
- return new Promise<string | undefined>((resolve) => {
342
- execFile(
343
- versionCommand.command,
344
- [...versionCommand.args],
345
- { encoding: "utf8", timeout: VERSION_TIMEOUT_MS, windowsHide: true },
346
- (error, stdout, stderr) => {
347
- const output = `${stringOutput(stdout)}\n${stringOutput(stderr)}`;
348
- if (error && output.trim().length === 0) {
349
- resolve(undefined);
350
- return;
351
- }
352
- const parsed = versionCommand.parse(output);
353
- resolve(parsed ? prefixRuntimeVersion(parsed) : undefined);
354
- },
355
- );
356
- });
357
- }
358
-
359
- function stringOutput(value: string | Buffer) {
360
- return typeof value === "string" ? value : value.toString("utf8");
361
- }
@@ -1,223 +0,0 @@
1
- import type { WidgetEntry, WidgetOptions } from "../types.js";
2
- import { ActiveToolsWidget } from "./core/active-tools.js";
3
- import { ContextWindowWidget } from "./core/context-window.js";
4
- import { CwdBasenameWidget } from "./core/cwd-basename.js";
5
- import { CwdWidget } from "./core/cwd.js";
6
- import { EventValueWidget } from "./core/event.js";
7
- import { ExtensionStatusWidget } from "./core/external-status.js";
8
- import { ModelProviderWidget } from "./core/model-provider.js";
9
- import { ModelWidget } from "./core/model.js";
10
- import { ProviderWidget } from "./core/provider.js";
11
- import { SessionNameWidget } from "./core/session-name.js";
12
- import { TextVerbosityWidget } from "./core/text-verbosity.js";
13
- import { ThinkingLevelWidget } from "./core/thinking-level.js";
14
- import { GitAheadBehindWidget } from "./git/ahead-behind.js";
15
- import { GitBranchWidget } from "./git/branch.js";
16
- import { GitCleanStatusWidget } from "./git/clean.js";
17
- import { GitDeletionsWidget } from "./git/deletions.js";
18
- import { GitDiffWidget } from "./git/diff.js";
19
- import { GitInsertionsWidget } from "./git/insertions.js";
20
- import { GitRemoteWidget } from "./git/remote.js";
21
- import { GitRootDirWidget } from "./git/root.js";
22
- import { GitShaWidget } from "./git/sha.js";
23
- import { GitStagedWidget } from "./git/staged.js";
24
- import { GitStatusWidget } from "./git/status.js";
25
- import { GitUnstagedWidget } from "./git/unstaged.js";
26
- import { GitUntrackedWidget } from "./git/untracked.js";
27
- import { WidgetInstance } from "./instance.js";
28
- import { CustomTextWidget } from "./layout/custom-text.js";
29
- import { FlexSeparatorWidget } from "./layout/flex-separator.js";
30
- import { SeparatorWidget } from "./layout/separator.js";
31
- import { SpacerWidget } from "./layout/spacer.js";
32
- import { sanitizeOptionsFromSpec } from "./options.js";
33
- import { RuntimeWidget } from "./project/runtime.js";
34
- import { AssistantMessagesWidget } from "./session/assistant-messages.js";
35
- import { CompactionsWidget } from "./session/compactions.js";
36
- import { ElapsedWidget } from "./session/elapsed.js";
37
- import { LastActivityWidget } from "./session/last-activity.js";
38
- import { MessagesWidget } from "./session/messages.js";
39
- import { SessionIdWidget } from "./session/session-id.js";
40
- import { SessionStartWidget } from "./session/session-start.js";
41
- import { ToolResultsWidget } from "./session/tool-results.js";
42
- import { TotalMessagesWidget } from "./session/total-messages.js";
43
- import { TotalTimeWidget } from "./session/total-time.js";
44
- import { UserMessagesWidget } from "./session/user-messages.js";
45
- import { CacheHitRateWidget } from "./tokens/cache-hit-rate.js";
46
- import { CacheReadWidget } from "./tokens/cache-read.js";
47
- import { CacheWriteWidget } from "./tokens/cache-write.js";
48
- import { ContextBarWidget } from "./tokens/context-bar.js";
49
- import { ContextLengthWidget } from "./tokens/context-length.js";
50
- import { ContextRemainingWidget } from "./tokens/context-remaining.js";
51
- import { ContextWidget } from "./tokens/context.js";
52
- import { CostWidget } from "./tokens/cost.js";
53
- import { InputSpeedWidget } from "./tokens/input-speed.js";
54
- import { InputTokensWidget } from "./tokens/input-tokens.js";
55
- import { OutputSpeedWidget } from "./tokens/output-speed.js";
56
- import { OutputTokensWidget } from "./tokens/output-tokens.js";
57
- import { TokensWidget } from "./tokens/tokens.js";
58
- import { TotalSpeedWidget } from "./tokens/total-speed.js";
59
- import { TotalTokensWidget } from "./tokens/total-tokens.js";
60
- import type { Widget } from "./types.js";
61
-
62
- const WIDGETS = [
63
- ModelWidget,
64
- ProviderWidget,
65
- ModelProviderWidget,
66
- ThinkingLevelWidget,
67
- TextVerbosityWidget,
68
- ContextWindowWidget,
69
- ActiveToolsWidget,
70
- SessionNameWidget,
71
- CwdWidget,
72
- CwdBasenameWidget,
73
- EventValueWidget,
74
- ExtensionStatusWidget,
75
- CustomTextWidget,
76
- SeparatorWidget,
77
- SpacerWidget,
78
- FlexSeparatorWidget,
79
- RuntimeWidget,
80
- AssistantMessagesWidget,
81
- CompactionsWidget,
82
- ElapsedWidget,
83
- LastActivityWidget,
84
- MessagesWidget,
85
- SessionIdWidget,
86
- SessionStartWidget,
87
- ToolResultsWidget,
88
- TotalMessagesWidget,
89
- TotalTimeWidget,
90
- UserMessagesWidget,
91
- GitAheadBehindWidget,
92
- GitBranchWidget,
93
- GitCleanStatusWidget,
94
- GitDeletionsWidget,
95
- GitDiffWidget,
96
- GitInsertionsWidget,
97
- GitRemoteWidget,
98
- GitRootDirWidget,
99
- GitShaWidget,
100
- GitStagedWidget,
101
- GitStatusWidget,
102
- GitUnstagedWidget,
103
- GitUntrackedWidget,
104
- ContextBarWidget,
105
- ContextLengthWidget,
106
- ContextWidget,
107
- ContextRemainingWidget,
108
- CostWidget,
109
- CacheReadWidget,
110
- CacheWriteWidget,
111
- CacheHitRateWidget,
112
- TokensWidget,
113
- InputTokensWidget,
114
- OutputTokensWidget,
115
- TotalTokensWidget,
116
- InputSpeedWidget,
117
- OutputSpeedWidget,
118
- TotalSpeedWidget,
119
- ] as const;
120
-
121
- export type WidgetSpecUnion = (typeof WIDGETS)[number];
122
- export type WidgetType = WidgetSpecUnion["type"];
123
- export type WidgetCategory = WidgetSpecUnion["category"];
124
-
125
- export interface WidgetDefinition {
126
- readonly type: WidgetType;
127
- readonly label: string;
128
- readonly category: WidgetCategory;
129
- readonly description: string;
130
- }
131
-
132
- interface WidgetRegistry {
133
- readonly specs: readonly WidgetSpecUnion[];
134
- readonly definitions: readonly WidgetDefinition[];
135
- readonly types: readonly WidgetType[];
136
- readonly typeSet: ReadonlySet<WidgetType>;
137
-
138
- spec(type: WidgetType): WidgetSpecUnion;
139
- maybeSpec(type: string): WidgetSpecUnion | undefined;
140
- createEntry(type: WidgetType, options?: Record<string, unknown>): WidgetEntry;
141
- cloneEntry(entry: WidgetEntry): WidgetEntry;
142
- normalizeOptions(type: WidgetType, input: Record<string, unknown>): WidgetOptions;
143
- createWidget(type: WidgetType, options?: Record<string, unknown>): Widget;
144
- cloneWidget(widget: Widget): Widget;
145
- hydrateWidget(entry: WidgetEntry): Widget;
146
- }
147
-
148
- function createWidgetRegistry(widgets: readonly WidgetSpecUnion[]): WidgetRegistry {
149
- const specs = [...widgets];
150
- const specsByType = new Map<WidgetType, WidgetSpecUnion>(
151
- specs.map((spec) => [spec.type as WidgetType, spec]),
152
- );
153
- const definitions = specs.map(definitionFromWidgetSpec);
154
- const types = definitions.map((definition) => definition.type);
155
- const typeSet = new Set<WidgetType>(types);
156
-
157
- const specFor = (type: WidgetType): WidgetSpecUnion => {
158
- const spec = specsByType.get(type);
159
- if (!spec) throw new Error(`Unsupported widget type: ${type}`);
160
- return spec;
161
- };
162
-
163
- const buildEntry = (
164
- type: WidgetType,
165
- options: Record<string, unknown> = {},
166
- enabled = true,
167
- ): WidgetEntry => ({
168
- id: `${type}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
169
- type,
170
- enabled,
171
- options: sanitizeOptionsFromSpec(specFor(type), options),
172
- });
173
-
174
- return {
175
- specs,
176
- definitions,
177
- types,
178
- typeSet,
179
- spec(type) {
180
- return specFor(type);
181
- },
182
- maybeSpec(type) {
183
- return specsByType.get(type as WidgetType);
184
- },
185
- createEntry(type, options = {}) {
186
- return buildEntry(type, options);
187
- },
188
- normalizeOptions(type, input) {
189
- return sanitizeOptionsFromSpec(specFor(type), input);
190
- },
191
- cloneEntry(entry) {
192
- return buildEntry(entry.type, entry.options, entry.enabled);
193
- },
194
- createWidget(type, options = {}) {
195
- return new WidgetInstance(specFor(type), buildEntry(type, options));
196
- },
197
- cloneWidget(widget) {
198
- return new WidgetInstance(
199
- specFor(widget.type),
200
- buildEntry(widget.type, widget.options, widget.enabled),
201
- );
202
- },
203
- hydrateWidget(entry) {
204
- return new WidgetInstance(specFor(entry.type), {
205
- id: entry.id,
206
- type: entry.type,
207
- enabled: entry.enabled,
208
- options: { ...entry.options },
209
- });
210
- },
211
- };
212
- }
213
-
214
- function definitionFromWidgetSpec(spec: WidgetSpecUnion): WidgetDefinition {
215
- return {
216
- type: spec.type as WidgetType,
217
- label: spec.label,
218
- category: spec.category as WidgetCategory,
219
- description: spec.description,
220
- };
221
- }
222
-
223
- export const registry = createWidgetRegistry(WIDGETS);