@selesai/code 0.9.15 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +6 -9
  3. package/dist/defaults/models.json +2 -2
  4. package/dist/defaults/settings.json +3 -7
  5. package/dist/extensions/package.json +2 -4
  6. package/dist/extensions/pi-zentui/.editorconfig +12 -0
  7. package/dist/extensions/pi-zentui/.github/CODEOWNERS +1 -0
  8. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/bug_report.yml +110 -0
  9. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config.yml +8 -0
  10. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config_question.yml +56 -0
  11. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
  12. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/rendering_issue.yml +106 -0
  13. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/runtime_detection.yml +103 -0
  14. package/dist/extensions/pi-zentui/.github/dependabot.yml +47 -0
  15. package/dist/extensions/pi-zentui/.github/pull_request_template.md +34 -0
  16. package/dist/extensions/pi-zentui/.github/release.yml +18 -0
  17. package/dist/extensions/pi-zentui/.github/workflows/ci.yml +79 -0
  18. package/dist/extensions/pi-zentui/.github/workflows/publish.yml +63 -0
  19. package/dist/extensions/pi-zentui/AGENTS.md +107 -0
  20. package/dist/extensions/pi-zentui/CONTRIBUTING.md +68 -0
  21. package/dist/extensions/pi-zentui/LICENSE +21 -0
  22. package/dist/extensions/pi-zentui/README.md +188 -0
  23. package/dist/extensions/pi-zentui/SECURITY.md +18 -0
  24. package/dist/extensions/pi-zentui/assets/main-cover.png +0 -0
  25. package/dist/extensions/pi-zentui/assets/screenshots/editor-accent-rail.png +0 -0
  26. package/dist/extensions/pi-zentui/assets/screenshots/editor-minimalist.png +0 -0
  27. package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode-copy-friendly.png +0 -0
  28. package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode.png +0 -0
  29. package/dist/extensions/pi-zentui/assets/screenshots/user-message-compact.png +0 -0
  30. package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed-copy-friendly.png +0 -0
  31. package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed.png +0 -0
  32. package/dist/extensions/pi-zentui/assets/screenshots/user-message-labeled.png +0 -0
  33. package/dist/extensions/pi-zentui/assets/zentui.png +0 -0
  34. package/dist/extensions/pi-zentui/biome.json +31 -0
  35. package/dist/extensions/pi-zentui/docs/configuration.md +509 -0
  36. package/dist/extensions/pi-zentui/docs/footer-format.md +162 -0
  37. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +99 -0
  38. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +457 -0
  39. package/dist/extensions/pi-zentui/extensions/zentui/completion-menu.ts +157 -0
  40. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +2100 -0
  41. package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +321 -0
  42. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +73 -0
  43. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +89 -0
  44. package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +364 -0
  45. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +122 -0
  46. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +812 -0
  47. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +568 -0
  48. package/dist/extensions/pi-zentui/extensions/zentui/git.ts +384 -0
  49. package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +252 -0
  50. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +1406 -0
  51. package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +1049 -0
  52. package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +75 -0
  53. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +463 -0
  54. package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +651 -0
  55. package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +120 -0
  56. package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +59 -0
  57. package/dist/extensions/pi-zentui/extensions/zentui/prototype-patch-registry.ts +166 -0
  58. package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +98 -0
  59. package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +841 -0
  60. package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +93 -0
  61. package/dist/extensions/pi-zentui/extensions/zentui/session-lifecycle.ts +60 -0
  62. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1796 -0
  63. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +128 -0
  64. package/dist/extensions/pi-zentui/extensions/zentui/state.ts +94 -0
  65. package/dist/extensions/pi-zentui/extensions/zentui/style.ts +424 -0
  66. package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +82 -0
  67. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +1290 -0
  68. package/dist/extensions/pi-zentui/extensions/zentui/user-message-osc.ts +248 -0
  69. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +215 -0
  70. package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +206 -0
  71. package/dist/extensions/pi-zentui/extensions/zentui/working-line-messages.ts +24 -0
  72. package/dist/extensions/pi-zentui/extensions/zentui/working-line-spinners.ts +54 -0
  73. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +1433 -0
  74. package/dist/extensions/pi-zentui/package-lock.json +5311 -0
  75. package/dist/extensions/pi-zentui/package.json +60 -0
  76. package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +232 -0
  77. package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +669 -0
  78. package/dist/extensions/pi-zentui/test/completion-menu.test.ts +265 -0
  79. package/dist/extensions/pi-zentui/test/config.test.ts +3119 -0
  80. package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +405 -0
  81. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +260 -0
  82. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +1286 -0
  83. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +7196 -0
  84. package/dist/extensions/pi-zentui/test/extension-status.test.ts +182 -0
  85. package/dist/extensions/pi-zentui/test/fixtures/starship-nerd-font-symbols.toml +172 -0
  86. package/dist/extensions/pi-zentui/test/footer-format.test.ts +431 -0
  87. package/dist/extensions/pi-zentui/test/footer-layout.test.ts +113 -0
  88. package/dist/extensions/pi-zentui/test/footer-repository-path.test.ts +123 -0
  89. package/dist/extensions/pi-zentui/test/format.test.ts +865 -0
  90. package/dist/extensions/pi-zentui/test/git.test.ts +212 -0
  91. package/dist/extensions/pi-zentui/test/icons.test.ts +69 -0
  92. package/dist/extensions/pi-zentui/test/interaction-summary.test.ts +1402 -0
  93. package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +378 -0
  94. package/dist/extensions/pi-zentui/test/live-context.test.ts +139 -0
  95. package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +811 -0
  96. package/dist/extensions/pi-zentui/test/package-version.test.ts +321 -0
  97. package/dist/extensions/pi-zentui/test/project-refresh.test.ts +250 -0
  98. package/dist/extensions/pi-zentui/test/project-state.test.ts +159 -0
  99. package/dist/extensions/pi-zentui/test/repository-root.test.ts +108 -0
  100. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +825 -0
  101. package/dist/extensions/pi-zentui/test/runtime.test.ts +183 -0
  102. package/dist/extensions/pi-zentui/test/session-lifecycle.test.ts +40 -0
  103. package/dist/extensions/pi-zentui/test/settings-command.test.ts +1381 -0
  104. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +347 -0
  105. package/dist/extensions/pi-zentui/test/state.test.ts +84 -0
  106. package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +276 -0
  107. package/dist/extensions/pi-zentui/test/telemetry.test.ts +105 -0
  108. package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +327 -0
  109. package/dist/extensions/pi-zentui/test/user-message-osc.test.ts +164 -0
  110. package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +292 -0
  111. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +730 -0
  112. package/dist/extensions/pi-zentui/test/working-line-messages.test.ts +34 -0
  113. package/dist/extensions/pi-zentui/test/working-line.test.ts +1990 -0
  114. package/dist/extensions/pi-zentui/tsconfig.json +16 -0
  115. package/dist/extensions/tps.test.ts +38 -0
  116. package/dist/extensions/{pi-powerline-footer/tps.ts → tps.ts} +4 -0
  117. package/dist/skills/design-references/SKILL.md +31 -0
  118. package/dist/skills/design-references/references/clickhouse/DESIGN.md +544 -0
  119. package/dist/themes/adventure.json +84 -0
  120. package/dist/themes/adwaita-dark.json +84 -0
  121. package/dist/themes/arcoiris.json +84 -0
  122. package/dist/themes/arthur.json +84 -0
  123. package/dist/themes/atom.json +84 -0
  124. package/dist/themes/aura.json +84 -0
  125. package/dist/themes/black-metal-bathory.json +84 -0
  126. package/dist/themes/black-metal-burzum.json +84 -0
  127. package/dist/themes/black-metal-khold.json +84 -0
  128. package/dist/themes/box.json +84 -0
  129. package/dist/themes/brogrammer.json +84 -0
  130. package/dist/themes/carbonfox.json +84 -0
  131. package/dist/themes/catppuccin-mocha.json +84 -0
  132. package/dist/themes/citruszest.json +84 -0
  133. package/dist/themes/cursor-dark.json +84 -0
  134. package/dist/themes/cutie-pro.json +84 -0
  135. package/dist/themes/dark-modern.json +84 -0
  136. package/dist/themes/dark-pastel.json +84 -0
  137. package/dist/themes/dimmed-monokai.json +84 -0
  138. package/dist/themes/doom-peacock.json +84 -0
  139. package/dist/themes/dracula-plus.json +84 -0
  140. package/dist/themes/dracula.json +80 -0
  141. package/dist/themes/earthsong.json +84 -0
  142. package/dist/themes/everforest-dark-hard.json +84 -0
  143. package/dist/themes/everforest-dark.json +80 -0
  144. package/dist/themes/fahrenheit.json +84 -0
  145. package/dist/themes/flatland.json +84 -0
  146. package/dist/themes/flexoki-dark.json +84 -0
  147. package/dist/themes/front-end-delight.json +84 -0
  148. package/dist/themes/fun-forrest.json +84 -0
  149. package/dist/themes/galizur.json +84 -0
  150. package/dist/themes/github-dark-colorblind.json +84 -0
  151. package/dist/themes/github-dark-high-contrast.json +84 -0
  152. package/dist/themes/glacier.json +84 -0
  153. package/dist/themes/gruber-darker.json +84 -0
  154. package/dist/themes/gruvbox-dark-hard.json +84 -0
  155. package/dist/themes/gruvbox-dark.json +84 -0
  156. package/dist/themes/gruvbox-material.json +84 -0
  157. package/dist/themes/guezwhoz.json +84 -0
  158. package/dist/themes/hacktober.json +84 -0
  159. package/dist/themes/hardcore.json +84 -0
  160. package/dist/themes/havn-skumring.json +84 -0
  161. package/dist/themes/ic-orange-ppl.json +84 -0
  162. package/dist/themes/iterm2-smoooooth.json +84 -0
  163. package/dist/themes/iterm2-tango-dark.json +84 -0
  164. package/dist/themes/japanesque.json +84 -0
  165. package/dist/themes/jellybeans.json +84 -0
  166. package/dist/themes/kanagawa-wave.json +84 -0
  167. package/dist/themes/kurokula.json +84 -0
  168. package/dist/themes/later-this-evening.json +84 -0
  169. package/dist/themes/lovelace.json +84 -0
  170. package/dist/themes/material-darker.json +84 -0
  171. package/dist/themes/matte-black.json +84 -0
  172. package/dist/themes/mellow.json +84 -0
  173. package/dist/themes/miasma.json +84 -0
  174. package/dist/themes/nord.json +80 -0
  175. package/dist/themes/nvim-dark.json +84 -0
  176. package/dist/themes/one-dark.json +80 -0
  177. package/dist/themes/popping-and-locking.json +84 -0
  178. package/dist/themes/rose-pine.json +80 -0
  179. package/dist/themes/sea-shells.json +84 -0
  180. package/dist/themes/sleepy-hollow.json +84 -0
  181. package/dist/themes/smyck.json +84 -0
  182. package/dist/themes/solarized-dark.json +80 -0
  183. package/dist/themes/tokyo-night.json +80 -0
  184. package/dist/themes/tomorrow-night-bright.json +84 -0
  185. package/dist/themes/tomorrow-night-burns.json +84 -0
  186. package/dist/themes/tomorrow-night.json +84 -0
  187. package/dist/themes/twilight.json +84 -0
  188. package/dist/themes/vague.json +84 -0
  189. package/dist/themes/vesper.json +84 -0
  190. package/dist/themes/xcode-dark-hc.json +84 -0
  191. package/docs/custom-provider.md +0 -1
  192. package/package.json +3 -3
  193. package/dist/extensions/auto-model/auto-model.test.ts +0 -18
  194. package/dist/extensions/auto-model/classifier.ts +0 -23
  195. package/dist/extensions/auto-model/config.ts +0 -51
  196. package/dist/extensions/auto-model/index.ts +0 -22
  197. package/dist/extensions/auto-model/lifecycle.test.ts +0 -24
  198. package/dist/extensions/pi-powerline-footer/.github/workflows/test.yml +0 -27
  199. package/dist/extensions/pi-powerline-footer/CHANGELOG.md +0 -687
  200. package/dist/extensions/pi-powerline-footer/CONTRIBUTING.md +0 -16
  201. package/dist/extensions/pi-powerline-footer/README.md +0 -513
  202. package/dist/extensions/pi-powerline-footer/banner.png +0 -0
  203. package/dist/extensions/pi-powerline-footer/bash-mode/completion.ts +0 -586
  204. package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +0 -583
  205. package/dist/extensions/pi-powerline-footer/bash-mode/history.ts +0 -204
  206. package/dist/extensions/pi-powerline-footer/bash-mode/shell-session.ts +0 -286
  207. package/dist/extensions/pi-powerline-footer/bash-mode/transcript.ts +0 -108
  208. package/dist/extensions/pi-powerline-footer/bash-mode/types.ts +0 -60
  209. package/dist/extensions/pi-powerline-footer/cd-command.ts +0 -190
  210. package/dist/extensions/pi-powerline-footer/colors.ts +0 -70
  211. package/dist/extensions/pi-powerline-footer/context-usage.ts +0 -156
  212. package/dist/extensions/pi-powerline-footer/currency-rates.ts +0 -142
  213. package/dist/extensions/pi-powerline-footer/editor-composition.ts +0 -32
  214. package/dist/extensions/pi-powerline-footer/editor-performance.ts +0 -99
  215. package/dist/extensions/pi-powerline-footer/git-status.ts +0 -329
  216. package/dist/extensions/pi-powerline-footer/guide.ts +0 -220
  217. package/dist/extensions/pi-powerline-footer/icons.ts +0 -190
  218. package/dist/extensions/pi-powerline-footer/index.ts +0 -3428
  219. package/dist/extensions/pi-powerline-footer/lifecycle.ts +0 -10
  220. package/dist/extensions/pi-powerline-footer/package.json +0 -49
  221. package/dist/extensions/pi-powerline-footer/paths.ts +0 -22
  222. package/dist/extensions/pi-powerline-footer/powerline-config.ts +0 -446
  223. package/dist/extensions/pi-powerline-footer/presets.ts +0 -102
  224. package/dist/extensions/pi-powerline-footer/queue/store.ts +0 -313
  225. package/dist/extensions/pi-powerline-footer/queue/types.ts +0 -53
  226. package/dist/extensions/pi-powerline-footer/render-scheduler.ts +0 -29
  227. package/dist/extensions/pi-powerline-footer/segments.ts +0 -570
  228. package/dist/extensions/pi-powerline-footer/separators.ts +0 -57
  229. package/dist/extensions/pi-powerline-footer/session-usage.ts +0 -44
  230. package/dist/extensions/pi-powerline-footer/shortcuts.ts +0 -61
  231. package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +0 -1905
  232. package/dist/extensions/pi-powerline-footer/tests/cd-command.test.ts +0 -144
  233. package/dist/extensions/pi-powerline-footer/tests/context-usage.test.ts +0 -156
  234. package/dist/extensions/pi-powerline-footer/tests/custom-items.test.ts +0 -344
  235. package/dist/extensions/pi-powerline-footer/tests/editor-composition.test.ts +0 -48
  236. package/dist/extensions/pi-powerline-footer/tests/editor-performance.test.ts +0 -43
  237. package/dist/extensions/pi-powerline-footer/tests/editor-responsiveness.test.ts +0 -136
  238. package/dist/extensions/pi-powerline-footer/tests/fixed-editor-border.test.ts +0 -39
  239. package/dist/extensions/pi-powerline-footer/tests/git-optional-locks.test.ts +0 -64
  240. package/dist/extensions/pi-powerline-footer/tests/git-status.test.ts +0 -92
  241. package/dist/extensions/pi-powerline-footer/tests/guide.test.ts +0 -129
  242. package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +0 -116
  243. package/dist/extensions/pi-powerline-footer/tests/mode-aware-trigger.test.ts +0 -79
  244. package/dist/extensions/pi-powerline-footer/tests/paths.test.ts +0 -63
  245. package/dist/extensions/pi-powerline-footer/tests/queue-store.test.ts +0 -65
  246. package/dist/extensions/pi-powerline-footer/tests/quit-cursor.test.ts +0 -14
  247. package/dist/extensions/pi-powerline-footer/tests/remaining-regressions.test.ts +0 -173
  248. package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +0 -47
  249. package/dist/extensions/pi-powerline-footer/tests/stash-shortcut.test.ts +0 -37
  250. package/dist/extensions/pi-powerline-footer/tests/thinking-segment.test.ts +0 -76
  251. package/dist/extensions/pi-powerline-footer/tests/token-stats.test.ts +0 -249
  252. package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +0 -39
  253. package/dist/extensions/pi-powerline-footer/tests/usage-display.test.ts +0 -237
  254. package/dist/extensions/pi-powerline-footer/tests/welcome.test.ts +0 -199
  255. package/dist/extensions/pi-powerline-footer/tests/working-vibes.test.ts +0 -317
  256. package/dist/extensions/pi-powerline-footer/theme.example.json +0 -24
  257. package/dist/extensions/pi-powerline-footer/theme.json +0 -12
  258. package/dist/extensions/pi-powerline-footer/theme.ts +0 -241
  259. package/dist/extensions/pi-powerline-footer/token-stats.ts +0 -304
  260. package/dist/extensions/pi-powerline-footer/tsconfig.json +0 -13
  261. package/dist/extensions/pi-powerline-footer/types.ts +0 -235
  262. package/dist/extensions/pi-powerline-footer/welcome-dismiss.ts +0 -34
  263. package/dist/extensions/pi-powerline-footer/welcome.ts +0 -709
  264. package/dist/extensions/pi-powerline-footer/working-vibes.ts +0 -721
  265. package/dist/extensions/preview-tools-disabled.test.ts +0 -37
  266. package/dist/extensions/preview-tools-disabled.ts +0 -11
  267. package/dist/themes/powerline-footer/theme.json +0 -33
@@ -1,10 +0,0 @@
1
- export function shouldShowStartupWelcome(reason: unknown, welcomeEnabled: boolean): boolean {
2
- return reason === "startup" && welcomeEnabled;
3
- }
4
-
5
- export function isStaleExtensionContextError(error: unknown): boolean {
6
- return error instanceof Error && (
7
- error.message.includes("This extension instance is stale")
8
- || error.message.includes("This extension ctx is stale")
9
- );
10
- }
@@ -1,49 +0,0 @@
1
- {
2
- "name": "pi-powerline-footer",
3
- "version": "0.13.0",
4
- "description": "Powerline-style status bar extension for pi coding agent",
5
- "type": "module",
6
- "files": [
7
- "*.ts",
8
- "*.md",
9
- "*.json",
10
- "!progress.md",
11
- "bash-mode/**/*.ts",
12
- "queue/**/*.ts"
13
- ],
14
- "keywords": [
15
- "pi-package",
16
- "pi",
17
- "coding-agent",
18
- "powerline",
19
- "status-bar",
20
- "extension"
21
- ],
22
- "author": "Nico Bailon",
23
- "license": "MIT",
24
- "repository": {
25
- "type": "git",
26
- "url": "git+https://github.com/nicobailon/pi-powerline-footer.git"
27
- },
28
- "scripts": {
29
- "typecheck": "tsc --noEmit",
30
- "test": "node --experimental-strip-types --test tests/**/*.test.ts"
31
- },
32
- "peerDependencies": {
33
- "@earendil-works/pi-ai": ">=0.84.1 <0.85.0",
34
- "@selesai/code": "*",
35
- "@earendil-works/pi-tui": ">=0.84.1 <0.85.0"
36
- },
37
- "devDependencies": {
38
- "@earendil-works/pi-ai": "^0.84.1",
39
- "@selesai/code": "^0.1.0",
40
- "@earendil-works/pi-tui": "^0.84.1",
41
- "@types/node": "24.13.3",
42
- "typescript": "5.9.3"
43
- },
44
- "pi": {
45
- "extensions": [
46
- "./index.ts"
47
- ]
48
- }
49
- }
@@ -1,22 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
- import { CONFIG_DIR_NAME, getAgentDir } from "@selesai/code";
5
-
6
- export function getHomeDir(): string {
7
- return process.env.HOME || process.env.USERPROFILE || homedir();
8
- }
9
-
10
- export function getAgentPath(...segments: string[]): string {
11
- return join(getAgentDir(), ...segments);
12
- }
13
-
14
- export function getLegacyPiPath(...segments: string[]): string {
15
- return join(getHomeDir(), CONFIG_DIR_NAME, ...segments);
16
- }
17
-
18
- export function getAgentSessionDirs(): string[] {
19
- const primary = getAgentPath("sessions");
20
- const legacy = getLegacyPiPath("sessions");
21
- return existsSync(legacy) && legacy !== primary ? [primary, legacy] : [primary];
22
- }
@@ -1,446 +0,0 @@
1
- import { visibleWidth } from "@earendil-works/pi-tui";
2
- import { normalizeCostCurrency } from "./currency-rates.ts";
3
- import { BUILTIN_STATUS_LINE_SEGMENT_IDS } from "./types.ts";
4
- import type { ColorValue, CustomItemPosition, CustomStatusItem, PowerlinePlacement, PresetDef, StatusLineLayout, StatusLinePreset, StatusLineSegmentId, StatusLineSegmentOptions, StatusLineSeparatorStyle } from "./types.ts";
5
-
6
- export interface PowerlineConfig {
7
- preset: StatusLinePreset;
8
- customItems: CustomStatusItem[];
9
- fixedEditorPromptGlyph: string;
10
- disabledSegments: StatusLineSegmentId[];
11
- invalidDisabledSegments: string[];
12
- layout: StatusLineLayout | null;
13
- invalidLayoutSegments: string[];
14
- separator: StatusLineSeparatorStyle | null;
15
- segmentOptions: StatusLineSegmentOptions;
16
- placement: PowerlinePlacement;
17
- invalidPlacement: string | null;
18
- welcome: boolean;
19
- stashSharpSShortcut: boolean;
20
- }
21
-
22
- function isRecord(value: unknown): value is Record<string, unknown> {
23
- return typeof value === "object" && value !== null && !Array.isArray(value);
24
- }
25
-
26
- function normalizePreset(value: unknown, presets: readonly StatusLinePreset[]): StatusLinePreset | null {
27
- if (typeof value !== "string") return null;
28
- const normalized = value.trim().toLowerCase();
29
- return (presets as readonly string[]).includes(normalized) ? (normalized as StatusLinePreset) : null;
30
- }
31
-
32
- function normalizePlacement(value: unknown): { placement: PowerlinePlacement; invalidPlacement: string | null } {
33
- if (value === undefined) return { placement: "above", invalidPlacement: null };
34
-
35
- const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
36
- if (normalized === "above" || normalized === "below") {
37
- return { placement: normalized, invalidPlacement: null };
38
- }
39
-
40
- return {
41
- placement: "above",
42
- invalidPlacement: typeof value === "string" ? value.trim() : String(value),
43
- };
44
- }
45
-
46
- const SEPARATOR_STYLES = [
47
- "powerline",
48
- "powerline-thin",
49
- "slash",
50
- "pipe",
51
- "block",
52
- "none",
53
- "ascii",
54
- "dot",
55
- "chevron",
56
- "star",
57
- ] as const satisfies readonly StatusLineSeparatorStyle[];
58
-
59
- function normalizeSeparator(value: unknown): StatusLineSeparatorStyle | null {
60
- if (typeof value !== "string") return null;
61
- const normalized = value.trim().toLowerCase();
62
- return (SEPARATOR_STYLES as readonly string[]).includes(normalized)
63
- ? (normalized as StatusLineSeparatorStyle)
64
- : null;
65
- }
66
-
67
- function normalizeCustomItemId(value: unknown): string | null {
68
- if (typeof value !== "string") return null;
69
- const normalized = value.trim();
70
- if (!normalized) return null;
71
- return /^[a-zA-Z0-9_-]+$/.test(normalized) ? normalized : null;
72
- }
73
-
74
- function normalizeCustomItemPosition(value: unknown): CustomItemPosition {
75
- if (value === "left" || value === "right" || value === "secondary") return value;
76
- return "right";
77
- }
78
-
79
- function normalizeCustomColor(value: unknown): ColorValue | undefined {
80
- if (typeof value !== "string") return undefined;
81
- const normalized = value.trim();
82
- return normalized ? (normalized as ColorValue) : undefined;
83
- }
84
-
85
- function normalizeCustomPrefix(value: unknown): string | undefined {
86
- if (typeof value !== "string") return undefined;
87
- const normalized = value.trim();
88
- return normalized ? normalized : undefined;
89
- }
90
-
91
-
92
- function normalizeCustomStatusItem(raw: unknown, idOverride?: string): CustomStatusItem | null {
93
- if (!isRecord(raw)) return null;
94
- const id = normalizeCustomItemId(idOverride ?? raw.id);
95
- if (!id) return null;
96
-
97
- const statusKey = typeof raw.statusKey === "string" && raw.statusKey.trim() ? raw.statusKey.trim() : id;
98
-
99
- return {
100
- id,
101
- statusKey,
102
- position: normalizeCustomItemPosition(raw.position),
103
- color: normalizeCustomColor(raw.color),
104
- prefix: normalizeCustomPrefix(raw.prefix),
105
- hideWhenMissing: raw.hideWhenMissing !== false,
106
- excludeFromExtensionStatuses: raw.excludeFromExtensionStatuses !== false,
107
- };
108
- }
109
-
110
- function normalizeCustomItems(raw: unknown): CustomStatusItem[] {
111
- const normalized: CustomStatusItem[] = [];
112
-
113
- if (Array.isArray(raw)) {
114
- for (const entry of raw) {
115
- const item = normalizeCustomStatusItem(entry);
116
- if (item) normalized.push(item);
117
- }
118
- } else if (isRecord(raw)) {
119
- for (const [id, entry] of Object.entries(raw)) {
120
- const item = normalizeCustomStatusItem(entry, id);
121
- if (item) normalized.push(item);
122
- }
123
- }
124
-
125
- const deduped = new Map<string, CustomStatusItem>();
126
- for (const item of normalized) {
127
- deduped.set(item.id, item);
128
- }
129
-
130
- return [...deduped.values()];
131
- }
132
-
133
- const BUILTIN_STATUS_LINE_SEGMENT_ID_SET = new Set<string>(BUILTIN_STATUS_LINE_SEGMENT_IDS);
134
-
135
- function normalizeStatusLineSegmentId(value: unknown, customItemIds: ReadonlySet<string>): StatusLineSegmentId | null {
136
- if (typeof value !== "string") return null;
137
-
138
- const normalized = value.trim();
139
- if (BUILTIN_STATUS_LINE_SEGMENT_ID_SET.has(normalized)) {
140
- return normalized as StatusLineSegmentId;
141
- }
142
-
143
- const customId = normalized.startsWith("custom:")
144
- ? normalizeCustomItemId(normalized.slice("custom:".length))
145
- : null;
146
- return customId && customItemIds.has(customId) ? `custom:${customId}` : null;
147
- }
148
-
149
- function normalizeDisabledSegments(
150
- raw: unknown,
151
- customItems: readonly CustomStatusItem[],
152
- ): { disabledSegments: StatusLineSegmentId[]; invalidDisabledSegments: string[] } {
153
- if (!Array.isArray(raw)) return { disabledSegments: [], invalidDisabledSegments: [] };
154
-
155
- const disabledSegments: StatusLineSegmentId[] = [];
156
- const invalidDisabledSegments: string[] = [];
157
- const customItemIds = new Set(customItems.map((item) => item.id));
158
- const seen = new Set<StatusLineSegmentId>();
159
-
160
- for (const entry of raw) {
161
- const segmentId = normalizeStatusLineSegmentId(entry, customItemIds);
162
- if (!segmentId) {
163
- invalidDisabledSegments.push(typeof entry === "string" ? entry.trim() : String(entry));
164
- } else if (!seen.has(segmentId)) {
165
- seen.add(segmentId);
166
- disabledSegments.push(segmentId);
167
- }
168
- }
169
-
170
- return { disabledSegments, invalidDisabledSegments };
171
- }
172
-
173
- function normalizeLayout(
174
- raw: unknown,
175
- customItems: readonly CustomStatusItem[],
176
- ): { layout: StatusLineLayout | null; invalidLayoutSegments: string[] } {
177
- if (!isRecord(raw)) return { layout: null, invalidLayoutSegments: [] };
178
-
179
- const layout: StatusLineLayout = {};
180
- const invalidLayoutSegments: string[] = [];
181
- const customItemIds = new Set(customItems.map((item) => item.id));
182
- const globallyPlaced = new Set<StatusLineSegmentId>();
183
-
184
- for (const row of ["left", "right", "secondary"] as const) {
185
- const entries = raw[row];
186
- if (!Array.isArray(entries)) continue;
187
-
188
- const segments: StatusLineSegmentId[] = [];
189
- const seen = new Set<StatusLineSegmentId>();
190
- for (const entry of entries) {
191
- const segmentId = normalizeStatusLineSegmentId(entry, customItemIds);
192
- if (!segmentId) {
193
- invalidLayoutSegments.push(`${row}:${typeof entry === "string" ? entry.trim() : String(entry)}`);
194
- } else if (!seen.has(segmentId)) {
195
- seen.add(segmentId);
196
- if (globallyPlaced.has(segmentId)) {
197
- invalidLayoutSegments.push(`${row}:${segmentId}`);
198
- } else {
199
- globallyPlaced.add(segmentId);
200
- segments.push(segmentId);
201
- }
202
- }
203
- }
204
- layout[row] = segments;
205
- }
206
-
207
- return Object.keys(layout).length > 0
208
- ? { layout, invalidLayoutSegments }
209
- : { layout: null, invalidLayoutSegments };
210
- }
211
-
212
- function normalizeSegmentOptions(raw: Record<string, unknown>): StatusLineSegmentOptions {
213
- const options: StatusLineSegmentOptions = {};
214
-
215
- if (isRecord(raw.model)) {
216
- options.model = {
217
- ...(typeof raw.model.showThinkingLevel === "boolean" ? { showThinkingLevel: raw.model.showThinkingLevel } : {}),
218
- ...(raw.model.display === "name" || raw.model.display === "qualified" ? { display: raw.model.display } : {}),
219
- };
220
- }
221
-
222
- if (isRecord(raw.path)) {
223
- options.path = {
224
- ...(raw.path.mode === "basename" || raw.path.mode === "abbreviated" || raw.path.mode === "full" ? { mode: raw.path.mode } : {}),
225
- ...(typeof raw.path.maxLength === "number" && Number.isFinite(raw.path.maxLength) && raw.path.maxLength > 0
226
- ? { maxLength: Math.floor(raw.path.maxLength) }
227
- : {}),
228
- };
229
- }
230
-
231
- if (isRecord(raw.git)) {
232
- options.git = {
233
- ...(typeof raw.git.showBranch === "boolean" ? { showBranch: raw.git.showBranch } : {}),
234
- ...(typeof raw.git.showStaged === "boolean" ? { showStaged: raw.git.showStaged } : {}),
235
- ...(typeof raw.git.showUnstaged === "boolean" ? { showUnstaged: raw.git.showUnstaged } : {}),
236
- ...(typeof raw.git.showUntracked === "boolean" ? { showUntracked: raw.git.showUntracked } : {}),
237
- ...(raw.git.polling === "full" || raw.git.polling === "branch" || raw.git.polling === "off" ? { polling: raw.git.polling } : {}),
238
- ...(typeof raw.git.hostIcon === "boolean" ? { hostIcon: raw.git.hostIcon } : {}),
239
- };
240
- }
241
-
242
- if (isRecord(raw.time)) {
243
- options.time = {
244
- ...(raw.time.format === "12h" || raw.time.format === "24h" ? { format: raw.time.format } : {}),
245
- ...(typeof raw.time.showSeconds === "boolean" ? { showSeconds: raw.time.showSeconds } : {}),
246
- };
247
- }
248
-
249
- if (isRecord(raw.cost)) {
250
- const currency = normalizeCostCurrency(raw.cost.currency);
251
- options.cost = {
252
- ...(raw.cost.subscriptionDisplay === "subscription"
253
- || raw.cost.subscriptionDisplay === "reported-cost"
254
- || raw.cost.subscriptionDisplay === "both"
255
- ? { subscriptionDisplay: raw.cost.subscriptionDisplay }
256
- : {}),
257
- ...(currency ? { currency } : {}),
258
- };
259
- }
260
-
261
- if (isRecord(raw.context)) {
262
- options.context = {
263
- ...(raw.context.format === "full" || raw.context.format === "percent" ? { format: raw.context.format } : {}),
264
- };
265
- }
266
-
267
- if (isRecord(raw.cache_read)) {
268
- options.cache_read = {
269
- ...(raw.cache_read.format === "tokens" || raw.cache_read.format === "percent" || raw.cache_read.format === "both"
270
- ? { format: raw.cache_read.format }
271
- : {}),
272
- };
273
- }
274
-
275
- return options;
276
- }
277
-
278
- export function mergeSegmentOptions(
279
- defaults: StatusLineSegmentOptions = {},
280
- overrides: StatusLineSegmentOptions = {},
281
- ): StatusLineSegmentOptions {
282
- return {
283
- ...defaults,
284
- ...overrides,
285
- model: { ...defaults.model, ...overrides.model },
286
- path: { ...defaults.path, ...overrides.path },
287
- git: { ...defaults.git, ...overrides.git },
288
- time: { ...defaults.time, ...overrides.time },
289
- cost: { ...defaults.cost, ...overrides.cost },
290
- context: { ...defaults.context, ...overrides.context },
291
- cache_read: { ...defaults.cache_read, ...overrides.cache_read },
292
- };
293
- }
294
-
295
- export function parsePowerlineConfig(value: unknown, presets: readonly StatusLinePreset[]): PowerlineConfig {
296
- const defaultConfig: PowerlineConfig = {
297
- preset: "default",
298
- customItems: [],
299
- fixedEditorPromptGlyph: "",
300
- disabledSegments: [],
301
- invalidDisabledSegments: [],
302
- layout: null,
303
- invalidLayoutSegments: [],
304
- separator: null,
305
- segmentOptions: {},
306
- placement: "above",
307
- invalidPlacement: null,
308
- welcome: true,
309
- stashSharpSShortcut: false,
310
- };
311
-
312
- const directPreset = normalizePreset(value, presets);
313
- if (directPreset) return { ...defaultConfig, preset: directPreset };
314
-
315
- if (!isRecord(value)) return defaultConfig;
316
-
317
- const customItems = normalizeCustomItems(value.customItems);
318
- const { disabledSegments, invalidDisabledSegments } = normalizeDisabledSegments(value.disabledSegments, customItems);
319
- const { layout, invalidLayoutSegments } = normalizeLayout(value.layout, customItems);
320
- const { placement, invalidPlacement } = normalizePlacement(value.placement);
321
-
322
- return {
323
- preset: normalizePreset(value.preset, presets) ?? defaultConfig.preset,
324
- customItems,
325
- fixedEditorPromptGlyph: typeof value.fixedEditorPromptGlyph === "string" ? value.fixedEditorPromptGlyph : defaultConfig.fixedEditorPromptGlyph,
326
- disabledSegments,
327
- invalidDisabledSegments,
328
- layout,
329
- invalidLayoutSegments,
330
- separator: normalizeSeparator(value.separator),
331
- segmentOptions: normalizeSegmentOptions(value),
332
- placement,
333
- invalidPlacement,
334
- welcome: value.welcome !== false,
335
- stashSharpSShortcut: value.stashSharpSShortcut === true,
336
- };
337
- }
338
-
339
- export function mergeSegmentsWithCustomItems(
340
- presetDef: PresetDef,
341
- customItems: readonly CustomStatusItem[],
342
- options: {
343
- layout?: StatusLineLayout | null;
344
- disabledSegments?: readonly StatusLineSegmentId[];
345
- } = {},
346
- ): {
347
- leftSegments: StatusLineSegmentId[];
348
- rightSegments: StatusLineSegmentId[];
349
- secondarySegments: StatusLineSegmentId[];
350
- } {
351
- const layout = options.layout ?? null;
352
- const explicitlyPlaced = new Set([
353
- ...(layout?.left ?? []),
354
- ...(layout?.right ?? []),
355
- ...(layout?.secondary ?? []),
356
- ]);
357
- const disabled = new Set(options.disabledSegments ?? []);
358
-
359
- const buildRow = (
360
- position: CustomItemPosition,
361
- configured: StatusLineSegmentId[] | undefined,
362
- presetSegments: readonly StatusLineSegmentId[],
363
- ): StatusLineSegmentId[] => {
364
- const segments = configured !== undefined
365
- ? [...configured]
366
- : presetSegments.filter((id) => !explicitlyPlaced.has(id));
367
-
368
- if (configured === undefined) {
369
- for (const item of customItems) {
370
- const segmentId: StatusLineSegmentId = `custom:${item.id}`;
371
- if (item.position === position && !explicitlyPlaced.has(segmentId)) {
372
- segments.push(segmentId);
373
- }
374
- }
375
- }
376
-
377
- return segments.filter((id) => !disabled.has(id));
378
- };
379
-
380
- return {
381
- leftSegments: buildRow("left", layout?.left, presetDef.leftSegments),
382
- rightSegments: buildRow("right", layout?.right, presetDef.rightSegments),
383
- secondarySegments: buildRow("secondary", layout?.secondary, presetDef.secondarySegments ?? []),
384
- };
385
- }
386
-
387
- export function nextPowerlineSettingWithPreset(existingPowerlineSetting: unknown, preset: StatusLinePreset): unknown {
388
- if (!isRecord(existingPowerlineSetting)) {
389
- return preset;
390
- }
391
- return { ...existingPowerlineSetting, preset };
392
- }
393
-
394
- export function nextPowerlineSettingWithOptions(
395
- existingPowerlineSetting: unknown,
396
- updates: Partial<Pick<PowerlineConfig, "welcome" | "stashSharpSShortcut" | "placement">>,
397
- currentPreset: StatusLinePreset,
398
- ): unknown {
399
- if (!isRecord(existingPowerlineSetting)) {
400
- return { preset: currentPreset, ...updates };
401
- }
402
- return { ...existingPowerlineSetting, ...updates };
403
- }
404
-
405
- export function collectHiddenExtensionStatusKeys(customItems: readonly CustomStatusItem[]): Set<string> {
406
- const hidden = new Set<string>();
407
- for (const item of customItems) {
408
- if (item.excludeFromExtensionStatuses) hidden.add(item.statusKey);
409
- }
410
- return hidden;
411
- }
412
-
413
- export function isNotificationExtensionStatus(value: string): boolean {
414
- return value.trimStart().startsWith("[");
415
- }
416
-
417
- export function getNotificationExtensionStatuses(
418
- statuses: ReadonlyMap<string, string>,
419
- hiddenKeys: ReadonlySet<string>,
420
- ): string[] {
421
- const notifications: string[] = [];
422
- for (const [statusKey, value] of statuses.entries()) {
423
- if (hiddenKeys.has(statusKey) || !value || !isNotificationExtensionStatus(value)) {
424
- continue;
425
- }
426
- notifications.push(value);
427
- }
428
- return notifications;
429
- }
430
-
431
- export function normalizeExtensionStatusValue(value: string): string | null {
432
- if (!value || visibleWidth(value) <= 0) {
433
- return null;
434
- }
435
-
436
- const stripped = value.replace(/(\x1b\[[0-9;]*m|\s|·|[|])+$/, "");
437
- return visibleWidth(stripped) > 0 ? stripped : null;
438
- }
439
-
440
- export function normalizeCompactExtensionStatus(value: string): string | null {
441
- if (isNotificationExtensionStatus(value)) {
442
- return null;
443
- }
444
-
445
- return normalizeExtensionStatusValue(value);
446
- }
@@ -1,102 +0,0 @@
1
- import type { ColorScheme, PresetDef, StatusLinePreset } from "./types.ts";
2
- import { getDefaultColors } from "./theme.ts";
3
-
4
- // Get base colors from theme.ts (single source of truth)
5
- const DEFAULT_COLORS: ColorScheme = getDefaultColors();
6
-
7
- // Minimal - more muted, less colorful
8
- const MINIMAL_COLORS: ColorScheme = {
9
- ...DEFAULT_COLORS,
10
- model: "text",
11
- path: "text",
12
- gitClean: "dim",
13
- };
14
-
15
- // Nerd - vibrant colors
16
- const NERD_COLORS: ColorScheme = {
17
- ...DEFAULT_COLORS,
18
- model: "accent",
19
- path: "success",
20
- tokens: "muted",
21
- cost: "warning",
22
- };
23
-
24
- export const PRESETS: Record<StatusLinePreset, PresetDef> = {
25
- default: {
26
- leftSegments: ["model", "thinking", "shell_mode", "path", "git", "queue", "context_pct", "cache_read", "cost"],
27
- rightSegments: [],
28
- secondarySegments: ["extension_statuses"],
29
- separator: "powerline-thin",
30
- colors: DEFAULT_COLORS,
31
- segmentOptions: {
32
- model: { showThinkingLevel: false },
33
- path: { mode: "basename" },
34
- git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
35
- },
36
- },
37
-
38
- minimal: {
39
- leftSegments: ["shell_mode", "path", "git"],
40
- rightSegments: ["context_pct"],
41
- separator: "slash",
42
- colors: MINIMAL_COLORS,
43
- segmentOptions: {
44
- path: { mode: "basename" },
45
- git: { showBranch: true, showStaged: false, showUnstaged: false, showUntracked: false },
46
- },
47
- },
48
-
49
- compact: {
50
- leftSegments: ["model", "shell_mode", "git"],
51
- rightSegments: ["queue", "cost", "context_pct"],
52
- separator: "powerline-thin",
53
- colors: DEFAULT_COLORS,
54
- segmentOptions: {
55
- model: { showThinkingLevel: false },
56
- git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: false },
57
- },
58
- },
59
-
60
- full: {
61
- leftSegments: ["hostname", "model", "thinking", "shell_mode", "path", "git", "queue", "subagents"],
62
- rightSegments: ["token_in", "token_out", "cache_read", "cost", "context_pct", "time_spent", "time", "extension_statuses"],
63
- separator: "powerline",
64
- colors: DEFAULT_COLORS,
65
- segmentOptions: {
66
- model: { showThinkingLevel: false },
67
- path: { mode: "abbreviated", maxLength: 50 },
68
- git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
69
- time: { format: "24h", showSeconds: false },
70
- },
71
- },
72
-
73
- nerd: {
74
- leftSegments: ["hostname", "model", "thinking", "shell_mode", "path", "git", "queue", "session", "subagents"],
75
- rightSegments: ["token_in", "token_out", "cache_read", "cache_write", "cost", "context_pct", "context_total", "time_spent", "time", "extension_statuses"],
76
- separator: "powerline",
77
- colors: NERD_COLORS,
78
- segmentOptions: {
79
- model: { showThinkingLevel: false },
80
- path: { mode: "abbreviated", maxLength: 60 },
81
- git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
82
- time: { format: "24h", showSeconds: true },
83
- },
84
- },
85
-
86
- ascii: {
87
- leftSegments: ["model", "shell_mode", "path", "git"],
88
- rightSegments: ["queue", "token_total", "cost", "context_pct"],
89
- separator: "ascii",
90
- colors: MINIMAL_COLORS,
91
- segmentOptions: {
92
- model: { showThinkingLevel: true },
93
- path: { mode: "abbreviated", maxLength: 40 },
94
- git: { showBranch: true, showStaged: true, showUnstaged: true, showUntracked: true },
95
- },
96
- },
97
-
98
- };
99
-
100
- export function getPreset(name: StatusLinePreset): PresetDef {
101
- return PRESETS[name] ?? PRESETS.default;
102
- }