wepscli 0.1.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 (130) hide show
  1. package/README.md +293 -0
  2. package/dist/WEPSCLI-shell/agent-runtime.js +824 -0
  3. package/dist/WEPSCLI-shell/agent-runtime.js.map +1 -0
  4. package/dist/WEPSCLI-shell/approval-overlay.js +275 -0
  5. package/dist/WEPSCLI-shell/approval-overlay.js.map +1 -0
  6. package/dist/WEPSCLI-shell/chat-components.js +760 -0
  7. package/dist/WEPSCLI-shell/chat-components.js.map +1 -0
  8. package/dist/WEPSCLI-shell/components.js +850 -0
  9. package/dist/WEPSCLI-shell/components.js.map +1 -0
  10. package/dist/WEPSCLI-shell/config-overlays.js +205 -0
  11. package/dist/WEPSCLI-shell/config-overlays.js.map +1 -0
  12. package/dist/WEPSCLI-shell/debug-log.js +16 -0
  13. package/dist/WEPSCLI-shell/debug-log.js.map +1 -0
  14. package/dist/WEPSCLI-shell/file-change-preview.js +261 -0
  15. package/dist/WEPSCLI-shell/file-change-preview.js.map +1 -0
  16. package/dist/WEPSCLI-shell/helpers.js +112 -0
  17. package/dist/WEPSCLI-shell/helpers.js.map +1 -0
  18. package/dist/WEPSCLI-shell/index.js +3 -0
  19. package/dist/WEPSCLI-shell/index.js.map +1 -0
  20. package/dist/WEPSCLI-shell/provider-add-flow.js +406 -0
  21. package/dist/WEPSCLI-shell/provider-add-flow.js.map +1 -0
  22. package/dist/WEPSCLI-shell/run-wepscli-shell.js +21 -0
  23. package/dist/WEPSCLI-shell/run-wepscli-shell.js.map +1 -0
  24. package/dist/WEPSCLI-shell/runtime-recovery.js +37 -0
  25. package/dist/WEPSCLI-shell/runtime-recovery.js.map +1 -0
  26. package/dist/WEPSCLI-shell/runtime-status.js +66 -0
  27. package/dist/WEPSCLI-shell/runtime-status.js.map +1 -0
  28. package/dist/WEPSCLI-shell/shell-app.js +1047 -0
  29. package/dist/WEPSCLI-shell/shell-app.js.map +1 -0
  30. package/dist/WEPSCLI-shell/shell-modes.js +77 -0
  31. package/dist/WEPSCLI-shell/shell-modes.js.map +1 -0
  32. package/dist/WEPSCLI-shell/slash-commands.js +135 -0
  33. package/dist/WEPSCLI-shell/slash-commands.js.map +1 -0
  34. package/dist/WEPSCLI-shell/theme.js +19 -0
  35. package/dist/WEPSCLI-shell/theme.js.map +1 -0
  36. package/dist/WEPSCLI-shell/tool-approval.js +85 -0
  37. package/dist/WEPSCLI-shell/tool-approval.js.map +1 -0
  38. package/dist/WEPSCLI-shell/tool-diff.js +76 -0
  39. package/dist/WEPSCLI-shell/tool-diff.js.map +1 -0
  40. package/dist/WEPSCLI-shell/tool-file-changes.js +268 -0
  41. package/dist/WEPSCLI-shell/tool-file-changes.js.map +1 -0
  42. package/dist/WEPSCLI-shell/tool-message-detail.js +138 -0
  43. package/dist/WEPSCLI-shell/tool-message-detail.js.map +1 -0
  44. package/dist/WEPSCLI-shell/tool-messages.js +145 -0
  45. package/dist/WEPSCLI-shell/tool-messages.js.map +1 -0
  46. package/dist/WEPSCLI-shell/transcript-panel.js +372 -0
  47. package/dist/WEPSCLI-shell/transcript-panel.js.map +1 -0
  48. package/dist/WEPSCLI-shell/transcript-state.js +62 -0
  49. package/dist/WEPSCLI-shell/transcript-state.js.map +1 -0
  50. package/dist/WEPSCLI-shell/types.js +1 -0
  51. package/dist/WEPSCLI-shell/types.js.map +1 -0
  52. package/dist/cli.js +11 -0
  53. package/dist/cli.js.map +1 -0
  54. package/dist/config.js +40 -0
  55. package/dist/config.js.map +1 -0
  56. package/dist/index.js +4 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/main.js +140 -0
  59. package/dist/main.js.map +1 -0
  60. package/dist/onboarding/action-screen.js +90 -0
  61. package/dist/onboarding/action-screen.js.map +1 -0
  62. package/dist/onboarding/framed-screen.js +35 -0
  63. package/dist/onboarding/framed-screen.js.map +1 -0
  64. package/dist/onboarding/onboarding-app.js +312 -0
  65. package/dist/onboarding/onboarding-app.js.map +1 -0
  66. package/dist/onboarding/run-onboarding.js +23 -0
  67. package/dist/onboarding/run-onboarding.js.map +1 -0
  68. package/dist/onboarding/select-screen.js +21 -0
  69. package/dist/onboarding/select-screen.js.map +1 -0
  70. package/dist/onboarding/summary-screen.js +23 -0
  71. package/dist/onboarding/summary-screen.js.map +1 -0
  72. package/dist/onboarding/text-input-screen.js +55 -0
  73. package/dist/onboarding/text-input-screen.js.map +1 -0
  74. package/dist/onboarding/theme.js +26 -0
  75. package/dist/onboarding/theme.js.map +1 -0
  76. package/dist/provider-profiles/api-key-store.js +51 -0
  77. package/dist/provider-profiles/api-key-store.js.map +1 -0
  78. package/dist/provider-profiles/defaults.js +18 -0
  79. package/dist/provider-profiles/defaults.js.map +1 -0
  80. package/dist/provider-profiles/fetch-models.js +53 -0
  81. package/dist/provider-profiles/fetch-models.js.map +1 -0
  82. package/dist/provider-profiles/index.js +6 -0
  83. package/dist/provider-profiles/index.js.map +1 -0
  84. package/dist/provider-profiles/provider-profile-service.js +223 -0
  85. package/dist/provider-profiles/provider-profile-service.js.map +1 -0
  86. package/dist/provider-profiles/providers-config-store.js +17 -0
  87. package/dist/provider-profiles/providers-config-store.js.map +1 -0
  88. package/dist/provider-profiles/types.js +1 -0
  89. package/dist/provider-profiles/types.js.map +1 -0
  90. package/dist/session-history/session-history-service.js +142 -0
  91. package/dist/session-history/session-history-service.js.map +1 -0
  92. package/dist/shell/animator.js +30 -0
  93. package/dist/shell/animator.js.map +1 -0
  94. package/dist/shell/clickables.js +101 -0
  95. package/dist/shell/clickables.js.map +1 -0
  96. package/dist/shell/dashboard-shell.js +292 -0
  97. package/dist/shell/dashboard-shell.js.map +1 -0
  98. package/dist/shell/index.js +5 -0
  99. package/dist/shell/index.js.map +1 -0
  100. package/dist/shell/keymap.js +14 -0
  101. package/dist/shell/keymap.js.map +1 -0
  102. package/dist/shell/mouse.js +39 -0
  103. package/dist/shell/mouse.js.map +1 -0
  104. package/dist/shell/render.js +122 -0
  105. package/dist/shell/render.js.map +1 -0
  106. package/dist/shell/run-shell.js +36 -0
  107. package/dist/shell/run-shell.js.map +1 -0
  108. package/dist/shell/theme.js +56 -0
  109. package/dist/shell/theme.js.map +1 -0
  110. package/dist/storage/locked-json-file.js +88 -0
  111. package/dist/storage/locked-json-file.js.map +1 -0
  112. package/dist/workbench/animator.js +30 -0
  113. package/dist/workbench/animator.js.map +1 -0
  114. package/dist/workbench/index.js +6 -0
  115. package/dist/workbench/index.js.map +1 -0
  116. package/dist/workbench/mouse.js +39 -0
  117. package/dist/workbench/mouse.js.map +1 -0
  118. package/dist/workbench/render.js +82 -0
  119. package/dist/workbench/render.js.map +1 -0
  120. package/dist/workbench/renderer.js +364 -0
  121. package/dist/workbench/renderer.js.map +1 -0
  122. package/dist/workbench/run-workbench.js +36 -0
  123. package/dist/workbench/run-workbench.js.map +1 -0
  124. package/dist/workbench/theme.js +63 -0
  125. package/dist/workbench/theme.js.map +1 -0
  126. package/dist/workbench/types.js +1 -0
  127. package/dist/workbench/types.js.map +1 -0
  128. package/dist/workbench/workbench-shell.js +649 -0
  129. package/dist/workbench/workbench-shell.js.map +1 -0
  130. package/package.json +65 -0
@@ -0,0 +1,122 @@
1
+ import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";
2
+ export function blankLine(width) {
3
+ return " ".repeat(Math.max(0, width));
4
+ }
5
+ export function padLine(text, width) {
6
+ const trimmed = truncateToWidth(text, width, "");
7
+ const pad = Math.max(0, width - visibleWidth(trimmed));
8
+ return trimmed + " ".repeat(pad);
9
+ }
10
+ export function fitLines(lines, width, height) {
11
+ const fitted = lines.slice(0, Math.max(0, height)).map(line => padLine(line, width));
12
+ while (fitted.length < height) {
13
+ fitted.push(blankLine(width));
14
+ }
15
+ return fitted;
16
+ }
17
+ export function framePanel(title, bodyLines, width, height, style) {
18
+ if (width <= 2 || height <= 0) {
19
+ return fitLines([], width, height);
20
+ }
21
+ const innerWidth = Math.max(1, width - 2);
22
+ const titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), "");
23
+ const borderPad = "-".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));
24
+ const top = style.border(`+${titleText}${borderPad}+`);
25
+ const bottom = style.border(`+${"-".repeat(innerWidth)}+`);
26
+ const wrappedBody = bodyLines.flatMap(line => wrapTextWithAnsi(line, innerWidth));
27
+ const usableBodyHeight = Math.max(0, height - 2);
28
+ const body = fitLines(wrappedBody.map(line => style.body(`|${padLine(line, innerWidth)}|`)), width, usableBodyHeight);
29
+ return fitLines([top, ...body, bottom], width, height);
30
+ }
31
+ export function framePanelFixed(title, bodyLines, width, height, style) {
32
+ if (width <= 2 || height <= 0) {
33
+ return fitLines([], width, height);
34
+ }
35
+ const innerWidth = Math.max(1, width - 2);
36
+ const titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), "");
37
+ const borderPad = "-".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));
38
+ const top = style.border(`+${titleText}${borderPad}+`);
39
+ const bottom = style.border(`+${"-".repeat(innerWidth)}+`);
40
+ const usableBodyHeight = Math.max(0, height - 2);
41
+ const body = fitLines(bodyLines.slice(0, usableBodyHeight).map(line => style.body(`|${padLine(line, innerWidth)}|`)), width, usableBodyHeight);
42
+ return fitLines([top, ...body, bottom], width, height);
43
+ }
44
+ export function joinColumns(leftLines, leftWidth, rightLines, rightWidth, gap) {
45
+ const height = Math.max(leftLines.length, rightLines.length);
46
+ const gapText = " ".repeat(Math.max(0, gap));
47
+ const lines = [];
48
+ for (let i = 0; i < height; i++) {
49
+ const left = padLine(leftLines[i] ?? "", leftWidth);
50
+ const right = padLine(rightLines[i] ?? "", rightWidth);
51
+ lines.push(`${left}${gapText}${right}`);
52
+ }
53
+ return lines;
54
+ }
55
+ export function computeShellLayout(width, height) {
56
+ const showStatusPanel = width >= 108;
57
+ const gap = showStatusPanel ? 1 : 0;
58
+ if (height <= 16) {
59
+ const headerHeight = 2;
60
+ const dockHeight = 4;
61
+ const bodyHeight = Math.max(4, height - headerHeight - dockHeight);
62
+ const statusWidth = showStatusPanel ? Math.max(24, Math.floor(width * 0.28)) : 0;
63
+ const mainWidth = showStatusPanel ? width - statusWidth - gap : width;
64
+ return {
65
+ headerHeight,
66
+ bodyHeight,
67
+ dockHeight,
68
+ showStatusPanel,
69
+ mainWidth,
70
+ statusWidth,
71
+ gap
72
+ };
73
+ }
74
+ const headerHeight = 3;
75
+ const dockHeight = width >= 120 ? 7 : 6;
76
+ const bodyHeight = Math.max(6, height - headerHeight - dockHeight);
77
+ const statusWidth = showStatusPanel ? Math.max(28, Math.floor(width * 0.28)) : 0;
78
+ const mainWidth = showStatusPanel ? width - statusWidth - gap : width;
79
+ return {
80
+ headerHeight,
81
+ bodyHeight,
82
+ dockHeight,
83
+ showStatusPanel,
84
+ mainWidth,
85
+ statusWidth,
86
+ gap
87
+ };
88
+ }
89
+ export function computeShellRegions(width, height, providerListLineCount) {
90
+ const layout = computeShellLayout(width, height);
91
+ const bodyStartRow = layout.headerHeight + 1;
92
+ const main = {
93
+ row: bodyStartRow,
94
+ col: 1,
95
+ width: layout.mainWidth,
96
+ height: layout.bodyHeight
97
+ };
98
+ const status = layout.showStatusPanel ? {
99
+ row: bodyStartRow,
100
+ col: layout.mainWidth + layout.gap + 1,
101
+ width: layout.statusWidth,
102
+ height: layout.bodyHeight
103
+ } : undefined;
104
+ const dock = {
105
+ row: bodyStartRow + layout.bodyHeight,
106
+ col: 1,
107
+ width,
108
+ height: layout.dockHeight
109
+ };
110
+ const providerList = {
111
+ row: main.row + 6,
112
+ col: main.col + 1,
113
+ width: Math.max(1, main.width - 2),
114
+ height: providerListLineCount
115
+ };
116
+ return {
117
+ main,
118
+ status,
119
+ dock,
120
+ providerList
121
+ };
122
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["truncateToWidth","visibleWidth","wrapTextWithAnsi","blankLine","width","repeat","Math","max","padLine","text","trimmed","pad","fitLines","lines","height","fitted","slice","map","line","length","push","framePanel","title","bodyLines","style","innerWidth","titleText","borderPad","top","border","bottom","wrappedBody","flatMap","usableBodyHeight","body","framePanelFixed","joinColumns","leftLines","leftWidth","rightLines","rightWidth","gap","gapText","i","left","right","computeShellLayout","showStatusPanel","headerHeight","dockHeight","bodyHeight","statusWidth","floor","mainWidth","computeShellRegions","providerListLineCount","layout","bodyStartRow","main","row","col","status","undefined","dock","providerList"],"sources":["render.ts"],"sourcesContent":["import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from \"@mariozechner/pi-tui\";\r\nimport type { PanelVisualStyle } from \"./theme.js\";\r\n\r\nexport function blankLine(width: number): string {\r\n\treturn \" \".repeat(Math.max(0, width));\r\n}\r\n\r\nexport function padLine(text: string, width: number): string {\r\n\tconst trimmed = truncateToWidth(text, width, \"\");\r\n\tconst pad = Math.max(0, width - visibleWidth(trimmed));\r\n\treturn trimmed + \" \".repeat(pad);\r\n}\r\n\r\nexport function fitLines(lines: string[], width: number, height: number): string[] {\r\n\tconst fitted = lines.slice(0, Math.max(0, height)).map((line) => padLine(line, width));\r\n\twhile (fitted.length < height) {\r\n\t\tfitted.push(blankLine(width));\r\n\t}\r\n\treturn fitted;\r\n}\r\n\r\nexport function framePanel(\r\n\ttitle: string,\r\n\tbodyLines: string[],\r\n\twidth: number,\r\n\theight: number,\r\n\tstyle: PanelVisualStyle,\r\n): string[] {\r\n\tif (width <= 2 || height <= 0) {\r\n\t\treturn fitLines([], width, height);\r\n\t}\r\n\r\n\tconst innerWidth = Math.max(1, width - 2);\r\n\tconst titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), \"\");\r\n\tconst borderPad = \"-\".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));\r\n\tconst top = style.border(`+${titleText}${borderPad}+`);\r\n\tconst bottom = style.border(`+${\"-\".repeat(innerWidth)}+`);\r\n\r\n\tconst wrappedBody = bodyLines.flatMap((line) => wrapTextWithAnsi(line, innerWidth));\r\n\tconst usableBodyHeight = Math.max(0, height - 2);\r\n\tconst body = fitLines(\r\n\t\twrappedBody.map((line) => style.body(`|${padLine(line, innerWidth)}|`)),\r\n\t\twidth,\r\n\t\tusableBodyHeight,\r\n\t);\r\n\r\n\treturn fitLines([top, ...body, bottom], width, height);\r\n}\r\n\r\nexport function framePanelFixed(\r\n\ttitle: string,\r\n\tbodyLines: string[],\r\n\twidth: number,\r\n\theight: number,\r\n\tstyle: PanelVisualStyle,\r\n): string[] {\r\n\tif (width <= 2 || height <= 0) {\r\n\t\treturn fitLines([], width, height);\r\n\t}\r\n\r\n\tconst innerWidth = Math.max(1, width - 2);\r\n\tconst titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), \"\");\r\n\tconst borderPad = \"-\".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));\r\n\tconst top = style.border(`+${titleText}${borderPad}+`);\r\n\tconst bottom = style.border(`+${\"-\".repeat(innerWidth)}+`);\r\n\tconst usableBodyHeight = Math.max(0, height - 2);\r\n\tconst body = fitLines(\r\n\t\tbodyLines.slice(0, usableBodyHeight).map((line) => style.body(`|${padLine(line, innerWidth)}|`)),\r\n\t\twidth,\r\n\t\tusableBodyHeight,\r\n\t);\r\n\r\n\treturn fitLines([top, ...body, bottom], width, height);\r\n}\r\n\r\nexport function joinColumns(\r\n\tleftLines: string[],\r\n\tleftWidth: number,\r\n\trightLines: string[],\r\n\trightWidth: number,\r\n\tgap: number,\r\n): string[] {\r\n\tconst height = Math.max(leftLines.length, rightLines.length);\r\n\tconst gapText = \" \".repeat(Math.max(0, gap));\r\n\tconst lines: string[] = [];\r\n\r\n\tfor (let i = 0; i < height; i++) {\r\n\t\tconst left = padLine(leftLines[i] ?? \"\", leftWidth);\r\n\t\tconst right = padLine(rightLines[i] ?? \"\", rightWidth);\r\n\t\tlines.push(`${left}${gapText}${right}`);\r\n\t}\r\n\r\n\treturn lines;\r\n}\r\n\r\nexport function computeShellLayout(width: number, height: number): {\r\n\theaderHeight: number;\r\n\tbodyHeight: number;\r\n\tdockHeight: number;\r\n\tshowStatusPanel: boolean;\r\n\tmainWidth: number;\r\n\tstatusWidth: number;\r\n\tgap: number;\r\n} {\r\n\tconst showStatusPanel = width >= 108;\r\n\tconst gap = showStatusPanel ? 1 : 0;\r\n\r\n\tif (height <= 16) {\r\n\t\tconst headerHeight = 2;\r\n\t\tconst dockHeight = 4;\r\n\t\tconst bodyHeight = Math.max(4, height - headerHeight - dockHeight);\r\n\t\tconst statusWidth = showStatusPanel ? Math.max(24, Math.floor(width * 0.28)) : 0;\r\n\t\tconst mainWidth = showStatusPanel ? width - statusWidth - gap : width;\r\n\t\treturn { headerHeight, bodyHeight, dockHeight, showStatusPanel, mainWidth, statusWidth, gap };\r\n\t}\r\n\r\n\tconst headerHeight = 3;\r\n\tconst dockHeight = width >= 120 ? 7 : 6;\r\n\tconst bodyHeight = Math.max(6, height - headerHeight - dockHeight);\r\n\tconst statusWidth = showStatusPanel ? Math.max(28, Math.floor(width * 0.28)) : 0;\r\n\tconst mainWidth = showStatusPanel ? width - statusWidth - gap : width;\r\n\treturn { headerHeight, bodyHeight, dockHeight, showStatusPanel, mainWidth, statusWidth, gap };\r\n}\r\n\r\nexport interface ShellRect {\r\n\trow: number;\r\n\tcol: number;\r\n\twidth: number;\r\n\theight: number;\r\n}\r\n\r\nexport interface ShellRegions {\r\n\tmain: ShellRect;\r\n\tstatus?: ShellRect;\r\n\tdock: ShellRect;\r\n\tproviderList: ShellRect;\r\n}\r\n\r\nexport function computeShellRegions(width: number, height: number, providerListLineCount: number): ShellRegions {\r\n\tconst layout = computeShellLayout(width, height);\r\n\tconst bodyStartRow = layout.headerHeight + 1;\r\n\r\n\tconst main: ShellRect = {\r\n\t\trow: bodyStartRow,\r\n\t\tcol: 1,\r\n\t\twidth: layout.mainWidth,\r\n\t\theight: layout.bodyHeight,\r\n\t};\r\n\r\n\tconst status = layout.showStatusPanel\r\n\t\t? {\r\n\t\t\t\trow: bodyStartRow,\r\n\t\t\t\tcol: layout.mainWidth + layout.gap + 1,\r\n\t\t\t\twidth: layout.statusWidth,\r\n\t\t\t\theight: layout.bodyHeight,\r\n\t\t\t}\r\n\t\t: undefined;\r\n\r\n\tconst dock: ShellRect = {\r\n\t\trow: bodyStartRow + layout.bodyHeight,\r\n\t\tcol: 1,\r\n\t\twidth,\r\n\t\theight: layout.dockHeight,\r\n\t};\r\n\r\n\tconst providerList: ShellRect = {\r\n\t\trow: main.row + 6,\r\n\t\tcol: main.col + 1,\r\n\t\twidth: Math.max(1, main.width - 2),\r\n\t\theight: providerListLineCount,\r\n\t};\r\n\r\n\treturn {\r\n\t\tmain,\r\n\t\tstatus,\r\n\t\tdock,\r\n\t\tproviderList,\r\n\t};\r\n}\r\n"],"mappings":"AAAA,SAASA,eAAe,EAAEC,YAAY,EAAEC,gBAAgB,QAAQ,sBAAsB;AAGtF,OAAO,SAASC,SAASA,CAACC,KAAa,EAAU;EAChD,OAAO,GAAG,CAACC,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEH,KAAK,CAAC,CAAC;AACtC;AAEA,OAAO,SAASI,OAAOA,CAACC,IAAY,EAAEL,KAAa,EAAU;EAC5D,MAAMM,OAAO,GAAGV,eAAe,CAACS,IAAI,EAAEL,KAAK,EAAE,EAAE,CAAC;EAChD,MAAMO,GAAG,GAAGL,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEH,KAAK,GAAGH,YAAY,CAACS,OAAO,CAAC,CAAC;EACtD,OAAOA,OAAO,GAAG,GAAG,CAACL,MAAM,CAACM,GAAG,CAAC;AACjC;AAEA,OAAO,SAASC,QAAQA,CAACC,KAAe,EAAET,KAAa,EAAEU,MAAc,EAAY;EAClF,MAAMC,MAAM,GAAGF,KAAK,CAACG,KAAK,CAAC,CAAC,EAAEV,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEO,MAAM,CAAC,CAAC,CAACG,GAAG,CAAEC,IAAI,IAAKV,OAAO,CAACU,IAAI,EAAEd,KAAK,CAAC,CAAC;EACtF,OAAOW,MAAM,CAACI,MAAM,GAAGL,MAAM,EAAE;IAC9BC,MAAM,CAACK,IAAI,CAACjB,SAAS,CAACC,KAAK,CAAC,CAAC;EAC9B;EACA,OAAOW,MAAM;AACd;AAEA,OAAO,SAASM,UAAUA,CACzBC,KAAa,EACbC,SAAmB,EACnBnB,KAAa,EACbU,MAAc,EACdU,KAAuB,EACZ;EACX,IAAIpB,KAAK,IAAI,CAAC,IAAIU,MAAM,IAAI,CAAC,EAAE;IAC9B,OAAOF,QAAQ,CAAC,EAAE,EAAER,KAAK,EAAEU,MAAM,CAAC;EACnC;EAEA,MAAMW,UAAU,GAAGnB,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEH,KAAK,GAAG,CAAC,CAAC;EACzC,MAAMsB,SAAS,GAAG1B,eAAe,CAAC,IAAIsB,KAAK,GAAG,EAAEhB,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEkB,UAAU,CAAC,EAAE,EAAE,CAAC;EAC5E,MAAME,SAAS,GAAG,GAAG,CAACtB,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEkB,UAAU,GAAGxB,YAAY,CAACyB,SAAS,CAAC,CAAC,CAAC;EAC/E,MAAME,GAAG,GAAGJ,KAAK,CAACK,MAAM,CAAC,IAAIH,SAAS,GAAGC,SAAS,GAAG,CAAC;EACtD,MAAMG,MAAM,GAAGN,KAAK,CAACK,MAAM,CAAC,IAAI,GAAG,CAACxB,MAAM,CAACoB,UAAU,CAAC,GAAG,CAAC;EAE1D,MAAMM,WAAW,GAAGR,SAAS,CAACS,OAAO,CAAEd,IAAI,IAAKhB,gBAAgB,CAACgB,IAAI,EAAEO,UAAU,CAAC,CAAC;EACnF,MAAMQ,gBAAgB,GAAG3B,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEO,MAAM,GAAG,CAAC,CAAC;EAChD,MAAMoB,IAAI,GAAGtB,QAAQ,CACpBmB,WAAW,CAACd,GAAG,CAAEC,IAAI,IAAKM,KAAK,CAACU,IAAI,CAAC,IAAI1B,OAAO,CAACU,IAAI,EAAEO,UAAU,CAAC,GAAG,CAAC,CAAC,EACvErB,KAAK,EACL6B,gBACD,CAAC;EAED,OAAOrB,QAAQ,CAAC,CAACgB,GAAG,EAAE,GAAGM,IAAI,EAAEJ,MAAM,CAAC,EAAE1B,KAAK,EAAEU,MAAM,CAAC;AACvD;AAEA,OAAO,SAASqB,eAAeA,CAC9Bb,KAAa,EACbC,SAAmB,EACnBnB,KAAa,EACbU,MAAc,EACdU,KAAuB,EACZ;EACX,IAAIpB,KAAK,IAAI,CAAC,IAAIU,MAAM,IAAI,CAAC,EAAE;IAC9B,OAAOF,QAAQ,CAAC,EAAE,EAAER,KAAK,EAAEU,MAAM,CAAC;EACnC;EAEA,MAAMW,UAAU,GAAGnB,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEH,KAAK,GAAG,CAAC,CAAC;EACzC,MAAMsB,SAAS,GAAG1B,eAAe,CAAC,IAAIsB,KAAK,GAAG,EAAEhB,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEkB,UAAU,CAAC,EAAE,EAAE,CAAC;EAC5E,MAAME,SAAS,GAAG,GAAG,CAACtB,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEkB,UAAU,GAAGxB,YAAY,CAACyB,SAAS,CAAC,CAAC,CAAC;EAC/E,MAAME,GAAG,GAAGJ,KAAK,CAACK,MAAM,CAAC,IAAIH,SAAS,GAAGC,SAAS,GAAG,CAAC;EACtD,MAAMG,MAAM,GAAGN,KAAK,CAACK,MAAM,CAAC,IAAI,GAAG,CAACxB,MAAM,CAACoB,UAAU,CAAC,GAAG,CAAC;EAC1D,MAAMQ,gBAAgB,GAAG3B,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEO,MAAM,GAAG,CAAC,CAAC;EAChD,MAAMoB,IAAI,GAAGtB,QAAQ,CACpBW,SAAS,CAACP,KAAK,CAAC,CAAC,EAAEiB,gBAAgB,CAAC,CAAChB,GAAG,CAAEC,IAAI,IAAKM,KAAK,CAACU,IAAI,CAAC,IAAI1B,OAAO,CAACU,IAAI,EAAEO,UAAU,CAAC,GAAG,CAAC,CAAC,EAChGrB,KAAK,EACL6B,gBACD,CAAC;EAED,OAAOrB,QAAQ,CAAC,CAACgB,GAAG,EAAE,GAAGM,IAAI,EAAEJ,MAAM,CAAC,EAAE1B,KAAK,EAAEU,MAAM,CAAC;AACvD;AAEA,OAAO,SAASsB,WAAWA,CAC1BC,SAAmB,EACnBC,SAAiB,EACjBC,UAAoB,EACpBC,UAAkB,EAClBC,GAAW,EACA;EACX,MAAM3B,MAAM,GAAGR,IAAI,CAACC,GAAG,CAAC8B,SAAS,CAAClB,MAAM,EAAEoB,UAAU,CAACpB,MAAM,CAAC;EAC5D,MAAMuB,OAAO,GAAG,GAAG,CAACrC,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEkC,GAAG,CAAC,CAAC;EAC5C,MAAM5B,KAAe,GAAG,EAAE;EAE1B,KAAK,IAAI8B,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG7B,MAAM,EAAE6B,CAAC,EAAE,EAAE;IAChC,MAAMC,IAAI,GAAGpC,OAAO,CAAC6B,SAAS,CAACM,CAAC,CAAC,IAAI,EAAE,EAAEL,SAAS,CAAC;IACnD,MAAMO,KAAK,GAAGrC,OAAO,CAAC+B,UAAU,CAACI,CAAC,CAAC,IAAI,EAAE,EAAEH,UAAU,CAAC;IACtD3B,KAAK,CAACO,IAAI,CAAC,GAAGwB,IAAI,GAAGF,OAAO,GAAGG,KAAK,EAAE,CAAC;EACxC;EAEA,OAAOhC,KAAK;AACb;AAEA,OAAO,SAASiC,kBAAkBA,CAAC1C,KAAa,EAAEU,MAAc,EAQ9D;EACD,MAAMiC,eAAe,GAAG3C,KAAK,IAAI,GAAG;EACpC,MAAMqC,GAAG,GAAGM,eAAe,GAAG,CAAC,GAAG,CAAC;EAEnC,IAAIjC,MAAM,IAAI,EAAE,EAAE;IACjB,MAAMkC,YAAY,GAAG,CAAC;IACtB,MAAMC,UAAU,GAAG,CAAC;IACpB,MAAMC,UAAU,GAAG5C,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEO,MAAM,GAAGkC,YAAY,GAAGC,UAAU,CAAC;IAClE,MAAME,WAAW,GAAGJ,eAAe,GAAGzC,IAAI,CAACC,GAAG,CAAC,EAAE,EAAED,IAAI,CAAC8C,KAAK,CAAChD,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;IAChF,MAAMiD,SAAS,GAAGN,eAAe,GAAG3C,KAAK,GAAG+C,WAAW,GAAGV,GAAG,GAAGrC,KAAK;IACrE,OAAO;MAAE4C,YAAY;MAAEE,UAAU;MAAED,UAAU;MAAEF,eAAe;MAAEM,SAAS;MAAEF,WAAW;MAAEV;IAAI,CAAC;EAC9F;EAEA,MAAMO,YAAY,GAAG,CAAC;EACtB,MAAMC,UAAU,GAAG7C,KAAK,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC;EACvC,MAAM8C,UAAU,GAAG5C,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEO,MAAM,GAAGkC,YAAY,GAAGC,UAAU,CAAC;EAClE,MAAME,WAAW,GAAGJ,eAAe,GAAGzC,IAAI,CAACC,GAAG,CAAC,EAAE,EAAED,IAAI,CAAC8C,KAAK,CAAChD,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;EAChF,MAAMiD,SAAS,GAAGN,eAAe,GAAG3C,KAAK,GAAG+C,WAAW,GAAGV,GAAG,GAAGrC,KAAK;EACrE,OAAO;IAAE4C,YAAY;IAAEE,UAAU;IAAED,UAAU;IAAEF,eAAe;IAAEM,SAAS;IAAEF,WAAW;IAAEV;EAAI,CAAC;AAC9F;AAgBA,OAAO,SAASa,mBAAmBA,CAAClD,KAAa,EAAEU,MAAc,EAAEyC,qBAA6B,EAAgB;EAC/G,MAAMC,MAAM,GAAGV,kBAAkB,CAAC1C,KAAK,EAAEU,MAAM,CAAC;EAChD,MAAM2C,YAAY,GAAGD,MAAM,CAACR,YAAY,GAAG,CAAC;EAE5C,MAAMU,IAAe,GAAG;IACvBC,GAAG,EAAEF,YAAY;IACjBG,GAAG,EAAE,CAAC;IACNxD,KAAK,EAAEoD,MAAM,CAACH,SAAS;IACvBvC,MAAM,EAAE0C,MAAM,CAACN;EAChB,CAAC;EAED,MAAMW,MAAM,GAAGL,MAAM,CAACT,eAAe,GAClC;IACAY,GAAG,EAAEF,YAAY;IACjBG,GAAG,EAAEJ,MAAM,CAACH,SAAS,GAAGG,MAAM,CAACf,GAAG,GAAG,CAAC;IACtCrC,KAAK,EAAEoD,MAAM,CAACL,WAAW;IACzBrC,MAAM,EAAE0C,MAAM,CAACN;EAChB,CAAC,GACAY,SAAS;EAEZ,MAAMC,IAAe,GAAG;IACvBJ,GAAG,EAAEF,YAAY,GAAGD,MAAM,CAACN,UAAU;IACrCU,GAAG,EAAE,CAAC;IACNxD,KAAK;IACLU,MAAM,EAAE0C,MAAM,CAACP;EAChB,CAAC;EAED,MAAMe,YAAuB,GAAG;IAC/BL,GAAG,EAAED,IAAI,CAACC,GAAG,GAAG,CAAC;IACjBC,GAAG,EAAEF,IAAI,CAACE,GAAG,GAAG,CAAC;IACjBxD,KAAK,EAAEE,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEmD,IAAI,CAACtD,KAAK,GAAG,CAAC,CAAC;IAClCU,MAAM,EAAEyC;EACT,CAAC;EAED,OAAO;IACNG,IAAI;IACJG,MAAM;IACNE,IAAI;IACJC;EACD,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
2
+ import { DashboardShell } from "./dashboard-shell.js";
3
+ import { DISABLE_MOUSE_SEQUENCE, ENABLE_MOUSE_SEQUENCE, parseMouseSequence } from "./mouse.js";
4
+ export async function runShell(profileService) {
5
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
6
+ return;
7
+ }
8
+ return new Promise(resolve => {
9
+ const ui = new TUI(new ProcessTerminal());
10
+ let closed = false;
11
+ let removeMouseListener;
12
+ const shell = new DashboardShell(ui, profileService, () => {
13
+ if (closed) return;
14
+ closed = true;
15
+ removeMouseListener?.();
16
+ shell.dispose();
17
+ ui.terminal.write(DISABLE_MOUSE_SEQUENCE);
18
+ ui.stop();
19
+ resolve();
20
+ });
21
+ ui.terminal.write(ENABLE_MOUSE_SEQUENCE);
22
+ removeMouseListener = ui.addInputListener(data => {
23
+ const event = parseMouseSequence(data);
24
+ if (!event) {
25
+ return undefined;
26
+ }
27
+ const consumed = shell.handleMouseEvent(event);
28
+ return {
29
+ consume: consumed || true
30
+ };
31
+ });
32
+ ui.addChild(shell);
33
+ ui.setFocus(shell);
34
+ ui.start();
35
+ });
36
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ProcessTerminal","TUI","DashboardShell","DISABLE_MOUSE_SEQUENCE","ENABLE_MOUSE_SEQUENCE","parseMouseSequence","runShell","profileService","process","stdin","isTTY","stdout","Promise","resolve","ui","closed","removeMouseListener","shell","dispose","terminal","write","stop","addInputListener","data","event","undefined","consumed","handleMouseEvent","consume","addChild","setFocus","start"],"sources":["run-shell.ts"],"sourcesContent":["import { ProcessTerminal, TUI } from \"@mariozechner/pi-tui\";\r\nimport { ProviderProfileService } from \"../provider-profiles/index.js\";\r\nimport { DashboardShell } from \"./dashboard-shell.js\";\r\nimport { DISABLE_MOUSE_SEQUENCE, ENABLE_MOUSE_SEQUENCE, parseMouseSequence } from \"./mouse.js\";\r\n\r\nexport async function runShell(profileService: ProviderProfileService): Promise<void> {\r\n\tif (!process.stdin.isTTY || !process.stdout.isTTY) {\r\n\t\treturn;\r\n\t}\r\n\r\n\treturn new Promise<void>((resolve) => {\r\n\t\tconst ui = new TUI(new ProcessTerminal());\r\n\t\tlet closed = false;\r\n\t\tlet removeMouseListener: (() => void) | undefined;\r\n\r\n\t\tconst shell = new DashboardShell(ui, profileService, () => {\r\n\t\t\tif (closed) return;\r\n\t\t\tclosed = true;\r\n\t\t\tremoveMouseListener?.();\r\n\t\t\tshell.dispose();\r\n\t\t\tui.terminal.write(DISABLE_MOUSE_SEQUENCE);\r\n\t\t\tui.stop();\r\n\t\t\tresolve();\r\n\t\t});\r\n\r\n\t\tui.terminal.write(ENABLE_MOUSE_SEQUENCE);\r\n\t\tremoveMouseListener = ui.addInputListener((data) => {\r\n\t\t\tconst event = parseMouseSequence(data);\r\n\t\t\tif (!event) {\r\n\t\t\t\treturn undefined;\r\n\t\t\t}\r\n\r\n\t\t\tconst consumed = shell.handleMouseEvent(event);\r\n\t\t\treturn { consume: consumed || true };\r\n\t\t});\r\n\r\n\t\tui.addChild(shell);\r\n\t\tui.setFocus(shell);\r\n\t\tui.start();\r\n\t});\r\n}\r\n"],"mappings":"AAAA,SAASA,eAAe,EAAEC,GAAG,QAAQ,sBAAsB;AAE3D,SAASC,cAAc,QAAQ,sBAAsB;AACrD,SAASC,sBAAsB,EAAEC,qBAAqB,EAAEC,kBAAkB,QAAQ,YAAY;AAE9F,OAAO,eAAeC,QAAQA,CAACC,cAAsC,EAAiB;EACrF,IAAI,CAACC,OAAO,CAACC,KAAK,CAACC,KAAK,IAAI,CAACF,OAAO,CAACG,MAAM,CAACD,KAAK,EAAE;IAClD;EACD;EAEA,OAAO,IAAIE,OAAO,CAAQC,OAAO,IAAK;IACrC,MAAMC,EAAE,GAAG,IAAIb,GAAG,CAAC,IAAID,eAAe,CAAC,CAAC,CAAC;IACzC,IAAIe,MAAM,GAAG,KAAK;IAClB,IAAIC,mBAA6C;IAEjD,MAAMC,KAAK,GAAG,IAAIf,cAAc,CAACY,EAAE,EAAEP,cAAc,EAAE,MAAM;MAC1D,IAAIQ,MAAM,EAAE;MACZA,MAAM,GAAG,IAAI;MACbC,mBAAmB,GAAG,CAAC;MACvBC,KAAK,CAACC,OAAO,CAAC,CAAC;MACfJ,EAAE,CAACK,QAAQ,CAACC,KAAK,CAACjB,sBAAsB,CAAC;MACzCW,EAAE,CAACO,IAAI,CAAC,CAAC;MACTR,OAAO,CAAC,CAAC;IACV,CAAC,CAAC;IAEFC,EAAE,CAACK,QAAQ,CAACC,KAAK,CAAChB,qBAAqB,CAAC;IACxCY,mBAAmB,GAAGF,EAAE,CAACQ,gBAAgB,CAAEC,IAAI,IAAK;MACnD,MAAMC,KAAK,GAAGnB,kBAAkB,CAACkB,IAAI,CAAC;MACtC,IAAI,CAACC,KAAK,EAAE;QACX,OAAOC,SAAS;MACjB;MAEA,MAAMC,QAAQ,GAAGT,KAAK,CAACU,gBAAgB,CAACH,KAAK,CAAC;MAC9C,OAAO;QAAEI,OAAO,EAAEF,QAAQ,IAAI;MAAK,CAAC;IACrC,CAAC,CAAC;IAEFZ,EAAE,CAACe,QAAQ,CAACZ,KAAK,CAAC;IAClBH,EAAE,CAACgB,QAAQ,CAACb,KAAK,CAAC;IAClBH,EAAE,CAACiB,KAAK,CAAC,CAAC;EACX,CAAC,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,56 @@
1
+ import chalk from "chalk";
2
+ const bgApp = "#051018";
3
+ const bgHeader = "#082236";
4
+ const bgMain = "#071927";
5
+ const bgStatus = "#08131f";
6
+ const bgDock = "#09283d";
7
+ const fgText = "#e2f4ff";
8
+ const fgMuted = "#88a9bd";
9
+ const fgAccent = "#7dd3fc";
10
+ const fgAccentStrong = "#38bdf8";
11
+ const fgAccentSoft = "#67e8f9";
12
+ const fgSuccess = "#5eead4";
13
+ const fgWarning = "#fde68a";
14
+ export const shellTheme = {
15
+ headerBackground: text => chalk.bgHex(bgHeader)(text),
16
+ appBackground: text => chalk.bgHex(bgApp)(text),
17
+ panelMainBackground: text => chalk.bgHex(bgMain)(text),
18
+ panelStatusBackground: text => chalk.bgHex(bgStatus)(text),
19
+ panelDockBackground: text => chalk.bgHex(bgDock)(text),
20
+ text: text => chalk.hex(fgText)(text),
21
+ muted: text => chalk.hex(fgMuted)(text),
22
+ accent: text => chalk.bold(chalk.hex(fgAccent)(text)),
23
+ accentStrong: text => chalk.bold(chalk.hex(fgAccentStrong)(text)),
24
+ accentSoft: text => chalk.hex(fgAccentSoft)(text),
25
+ success: text => chalk.hex(fgSuccess)(text),
26
+ warning: text => chalk.hex(fgWarning)(text)
27
+ };
28
+ export function getPanelStyle(tone, active, pulsing) {
29
+ const background = tone === "main" ? shellTheme.panelMainBackground : tone === "status" ? shellTheme.panelStatusBackground : shellTheme.panelDockBackground;
30
+ const borderBase = active ? shellTheme.accentStrong : shellTheme.accentSoft;
31
+ const border = pulsing ? text => chalk.bold(chalk.hex("#bae6fd")(text)) : borderBase;
32
+ return {
33
+ border: text => background(border(text)),
34
+ body: text => background(shellTheme.text(text))
35
+ };
36
+ }
37
+ export function pulseDot(frame) {
38
+ const glyphs = ["o", "O", "0", "O"];
39
+ return glyphs[frame % glyphs.length] ?? "o";
40
+ }
41
+ export function shimmerText(text, frame) {
42
+ if (!text) return text;
43
+ const hotspot = frame % text.length;
44
+ let output = "";
45
+ for (let i = 0; i < text.length; i++) {
46
+ const char = text[i];
47
+ if (i === hotspot) {
48
+ output += shellTheme.accentStrong(char);
49
+ } else if (Math.abs(i - hotspot) === 1) {
50
+ output += shellTheme.accent(char);
51
+ } else {
52
+ output += shellTheme.text(char);
53
+ }
54
+ }
55
+ return output;
56
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["chalk","bgApp","bgHeader","bgMain","bgStatus","bgDock","fgText","fgMuted","fgAccent","fgAccentStrong","fgAccentSoft","fgSuccess","fgWarning","shellTheme","headerBackground","text","bgHex","appBackground","panelMainBackground","panelStatusBackground","panelDockBackground","hex","muted","accent","bold","accentStrong","accentSoft","success","warning","getPanelStyle","tone","active","pulsing","background","borderBase","border","body","pulseDot","frame","glyphs","length","shimmerText","hotspot","output","i","char","Math","abs"],"sources":["theme.ts"],"sourcesContent":["import chalk from \"chalk\";\r\n\r\nexport type PanelTone = \"main\" | \"status\" | \"dock\";\r\n\r\nexport interface PanelVisualStyle {\r\n\tborder: (text: string) => string;\r\n\tbody: (text: string) => string;\r\n}\r\n\r\nconst bgApp = \"#051018\";\r\nconst bgHeader = \"#082236\";\r\nconst bgMain = \"#071927\";\r\nconst bgStatus = \"#08131f\";\r\nconst bgDock = \"#09283d\";\r\nconst fgText = \"#e2f4ff\";\r\nconst fgMuted = \"#88a9bd\";\r\nconst fgAccent = \"#7dd3fc\";\r\nconst fgAccentStrong = \"#38bdf8\";\r\nconst fgAccentSoft = \"#67e8f9\";\r\nconst fgSuccess = \"#5eead4\";\r\nconst fgWarning = \"#fde68a\";\r\n\r\nexport const shellTheme = {\r\n\theaderBackground: (text: string) => chalk.bgHex(bgHeader)(text),\r\n\tappBackground: (text: string) => chalk.bgHex(bgApp)(text),\r\n\tpanelMainBackground: (text: string) => chalk.bgHex(bgMain)(text),\r\n\tpanelStatusBackground: (text: string) => chalk.bgHex(bgStatus)(text),\r\n\tpanelDockBackground: (text: string) => chalk.bgHex(bgDock)(text),\r\n\ttext: (text: string) => chalk.hex(fgText)(text),\r\n\tmuted: (text: string) => chalk.hex(fgMuted)(text),\r\n\taccent: (text: string) => chalk.bold(chalk.hex(fgAccent)(text)),\r\n\taccentStrong: (text: string) => chalk.bold(chalk.hex(fgAccentStrong)(text)),\r\n\taccentSoft: (text: string) => chalk.hex(fgAccentSoft)(text),\r\n\tsuccess: (text: string) => chalk.hex(fgSuccess)(text),\r\n\twarning: (text: string) => chalk.hex(fgWarning)(text),\r\n};\r\n\r\nexport function getPanelStyle(tone: PanelTone, active: boolean, pulsing: boolean): PanelVisualStyle {\r\n\tconst background =\r\n\t\ttone === \"main\"\r\n\t\t\t? shellTheme.panelMainBackground\r\n\t\t\t: tone === \"status\"\r\n\t\t\t\t? shellTheme.panelStatusBackground\r\n\t\t\t\t: shellTheme.panelDockBackground;\r\n\r\n\tconst borderBase = active ? shellTheme.accentStrong : shellTheme.accentSoft;\r\n\tconst border = pulsing ? (text: string) => chalk.bold(chalk.hex(\"#bae6fd\")(text)) : borderBase;\r\n\r\n\treturn {\r\n\t\tborder: (text: string) => background(border(text)),\r\n\t\tbody: (text: string) => background(shellTheme.text(text)),\r\n\t};\r\n}\r\n\r\nexport function pulseDot(frame: number): string {\r\n\tconst glyphs = [\"o\", \"O\", \"0\", \"O\"];\r\n\treturn glyphs[frame % glyphs.length] ?? \"o\";\r\n}\r\n\r\nexport function shimmerText(text: string, frame: number): string {\r\n\tif (!text) return text;\r\n\r\n\tconst hotspot = frame % text.length;\r\n\tlet output = \"\";\r\n\tfor (let i = 0; i < text.length; i++) {\r\n\t\tconst char = text[i]!;\r\n\t\tif (i === hotspot) {\r\n\t\t\toutput += shellTheme.accentStrong(char);\r\n\t\t} else if (Math.abs(i - hotspot) === 1) {\r\n\t\t\toutput += shellTheme.accent(char);\r\n\t\t} else {\r\n\t\t\toutput += shellTheme.text(char);\r\n\t\t}\r\n\t}\r\n\treturn output;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,88 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
+ import { dirname } from "path";
3
+ import lockfile from "proper-lockfile";
4
+ export class LockedJsonFile {
5
+ constructor(filePath, defaultValue, options = {}) {
6
+ this.filePath = filePath;
7
+ this.defaultValue = defaultValue;
8
+ this.dirMode = options.dirMode ?? 0o700;
9
+ this.fileMode = options.fileMode;
10
+ }
11
+ read() {
12
+ return this.withLock(current => ({
13
+ result: current
14
+ }));
15
+ }
16
+ write(next) {
17
+ this.withLock(() => ({
18
+ result: undefined,
19
+ next
20
+ }));
21
+ }
22
+ withLock(fn) {
23
+ this.ensureFileExists();
24
+ let release;
25
+ try {
26
+ release = this.acquireLockSyncWithRetry(this.filePath);
27
+ const currentRaw = readFileSync(this.filePath, "utf-8");
28
+ const current = this.parseValue(currentRaw);
29
+ const {
30
+ result,
31
+ next
32
+ } = fn(current);
33
+ if (next !== undefined) {
34
+ this.writeValue(next);
35
+ }
36
+ return result;
37
+ } finally {
38
+ release?.();
39
+ }
40
+ }
41
+ ensureFileExists() {
42
+ const dir = dirname(this.filePath);
43
+ if (!existsSync(dir)) {
44
+ mkdirSync(dir, {
45
+ recursive: true,
46
+ mode: this.dirMode
47
+ });
48
+ }
49
+ if (!existsSync(this.filePath)) {
50
+ this.writeValue(this.defaultValue);
51
+ }
52
+ }
53
+ writeValue(value) {
54
+ writeFileSync(this.filePath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
55
+ if (this.fileMode !== undefined) {
56
+ chmodSync(this.filePath, this.fileMode);
57
+ }
58
+ }
59
+ parseValue(content) {
60
+ if (!content.trim()) {
61
+ return structuredClone(this.defaultValue);
62
+ }
63
+ return JSON.parse(content);
64
+ }
65
+ acquireLockSyncWithRetry(path) {
66
+ const maxAttempts = 10;
67
+ const delayMs = 20;
68
+ let lastError;
69
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
70
+ try {
71
+ return lockfile.lockSync(path, {
72
+ realpath: false
73
+ });
74
+ } catch (error) {
75
+ const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : undefined;
76
+ if (code !== "ELOCKED" || attempt === maxAttempts) {
77
+ throw error;
78
+ }
79
+ lastError = error;
80
+ const start = Date.now();
81
+ while (Date.now() - start < delayMs) {
82
+ // busy wait to keep API synchronous and match existing repo style
83
+ }
84
+ }
85
+ }
86
+ throw lastError ?? new Error("Failed to acquire JSON file lock");
87
+ }
88
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["chmodSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","lockfile","LockedJsonFile","constructor","filePath","defaultValue","options","dirMode","fileMode","read","withLock","current","result","write","next","undefined","fn","ensureFileExists","release","acquireLockSyncWithRetry","currentRaw","parseValue","writeValue","dir","recursive","mode","value","JSON","stringify","content","trim","structuredClone","parse","path","maxAttempts","delayMs","lastError","attempt","lockSync","realpath","error","code","String","start","Date","now","Error"],"sources":["locked-json-file.ts"],"sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\r\nimport { dirname } from \"path\";\r\nimport lockfile from \"proper-lockfile\";\r\n\r\ntype LockResult<TValue, TResult> = {\r\n\tresult: TResult;\r\n\tnext?: TValue;\r\n};\r\n\r\ninterface LockedJsonFileOptions {\r\n\tdirMode?: number;\r\n\tfileMode?: number;\r\n}\r\n\r\nexport class LockedJsonFile<TValue> {\r\n\tprivate readonly dirMode: number;\r\n\tprivate readonly fileMode: number | undefined;\r\n\r\n\tconstructor(\r\n\t\tprivate readonly filePath: string,\r\n\t\tprivate readonly defaultValue: TValue,\r\n\t\toptions: LockedJsonFileOptions = {},\r\n\t) {\r\n\t\tthis.dirMode = options.dirMode ?? 0o700;\r\n\t\tthis.fileMode = options.fileMode;\r\n\t}\r\n\r\n\tread(): TValue {\r\n\t\treturn this.withLock((current) => ({ result: current }));\r\n\t}\r\n\r\n\twrite(next: TValue): void {\r\n\t\tthis.withLock(() => ({ result: undefined, next }));\r\n\t}\r\n\r\n\twithLock<TResult>(fn: (current: TValue) => LockResult<TValue, TResult>): TResult {\r\n\t\tthis.ensureFileExists();\r\n\r\n\t\tlet release: (() => void) | undefined;\r\n\t\ttry {\r\n\t\t\trelease = this.acquireLockSyncWithRetry(this.filePath);\r\n\t\t\tconst currentRaw = readFileSync(this.filePath, \"utf-8\");\r\n\t\t\tconst current = this.parseValue(currentRaw);\r\n\t\t\tconst { result, next } = fn(current);\r\n\r\n\t\t\tif (next !== undefined) {\r\n\t\t\t\tthis.writeValue(next);\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\t\t} finally {\r\n\t\t\trelease?.();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate ensureFileExists(): void {\r\n\t\tconst dir = dirname(this.filePath);\r\n\t\tif (!existsSync(dir)) {\r\n\t\t\tmkdirSync(dir, { recursive: true, mode: this.dirMode });\r\n\t\t}\r\n\r\n\t\tif (!existsSync(this.filePath)) {\r\n\t\t\tthis.writeValue(this.defaultValue);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate writeValue(value: TValue): void {\r\n\t\twriteFileSync(this.filePath, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\");\r\n\t\tif (this.fileMode !== undefined) {\r\n\t\t\tchmodSync(this.filePath, this.fileMode);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate parseValue(content: string): TValue {\r\n\t\tif (!content.trim()) {\r\n\t\t\treturn structuredClone(this.defaultValue);\r\n\t\t}\r\n\r\n\t\treturn JSON.parse(content) as TValue;\r\n\t}\r\n\r\n\tprivate acquireLockSyncWithRetry(path: string): () => void {\r\n\t\tconst maxAttempts = 10;\r\n\t\tconst delayMs = 20;\r\n\t\tlet lastError: unknown;\r\n\r\n\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\r\n\t\t\ttry {\r\n\t\t\t\treturn lockfile.lockSync(path, { realpath: false });\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconst code =\r\n\t\t\t\t\ttypeof error === \"object\" && error !== null && \"code\" in error\r\n\t\t\t\t\t\t? String((error as { code?: unknown }).code)\r\n\t\t\t\t\t\t: undefined;\r\n\t\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\r\n\t\t\t\t\tthrow error;\r\n\t\t\t\t}\r\n\t\t\t\tlastError = error;\r\n\t\t\t\tconst start = Date.now();\r\n\t\t\t\twhile (Date.now() - start < delayMs) {\r\n\t\t\t\t\t// busy wait to keep API synchronous and match existing repo style\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthrow (lastError as Error) ?? new Error(\"Failed to acquire JSON file lock\");\r\n\t}\r\n}\r\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,30 @@
1
+ export class WorkbenchAnimator {
2
+ frame = 0;
3
+ startedAt = Date.now();
4
+ focusPulseUntil = 0;
5
+ constructor(ui) {
6
+ this.ui = ui;
7
+ this.interval = setInterval(() => {
8
+ this.frame += 1;
9
+ this.ui.requestRender();
10
+ }, 120);
11
+ }
12
+ dispose() {
13
+ if (!this.interval) return;
14
+ clearInterval(this.interval);
15
+ this.interval = undefined;
16
+ }
17
+ markFocusPulse() {
18
+ this.focusPulseUntil = Date.now() + 550;
19
+ }
20
+ getSnapshot() {
21
+ const elapsed = Date.now() - this.startedAt;
22
+ return {
23
+ frame: this.frame,
24
+ showBody: elapsed >= 160,
25
+ showInspector: elapsed >= 320,
26
+ showDock: elapsed >= 480,
27
+ focusPulseActive: Date.now() < this.focusPulseUntil
28
+ };
29
+ }
30
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WorkbenchAnimator","frame","startedAt","Date","now","focusPulseUntil","constructor","ui","interval","setInterval","requestRender","dispose","clearInterval","undefined","markFocusPulse","getSnapshot","elapsed","showBody","showInspector","showDock","focusPulseActive"],"sources":["animator.ts"],"sourcesContent":["import type { TUI } from \"@mariozechner/pi-tui\";\r\n\r\nexport interface WorkbenchAnimationSnapshot {\r\n\tframe: number;\r\n\tshowBody: boolean;\r\n\tshowInspector: boolean;\r\n\tshowDock: boolean;\r\n\tfocusPulseActive: boolean;\r\n}\r\n\r\nexport class WorkbenchAnimator {\r\n\tprivate frame = 0;\r\n\tprivate interval: NodeJS.Timeout | undefined;\r\n\tprivate readonly startedAt = Date.now();\r\n\tprivate focusPulseUntil = 0;\r\n\r\n\tconstructor(private readonly ui: TUI) {\r\n\t\tthis.interval = setInterval(() => {\r\n\t\t\tthis.frame += 1;\r\n\t\t\tthis.ui.requestRender();\r\n\t\t}, 120);\r\n\t}\r\n\r\n\tdispose(): void {\r\n\t\tif (!this.interval) return;\r\n\t\tclearInterval(this.interval);\r\n\t\tthis.interval = undefined;\r\n\t}\r\n\r\n\tmarkFocusPulse(): void {\r\n\t\tthis.focusPulseUntil = Date.now() + 550;\r\n\t}\r\n\r\n\tgetSnapshot(): WorkbenchAnimationSnapshot {\r\n\t\tconst elapsed = Date.now() - this.startedAt;\r\n\t\treturn {\r\n\t\t\tframe: this.frame,\r\n\t\t\tshowBody: elapsed >= 160,\r\n\t\t\tshowInspector: elapsed >= 320,\r\n\t\t\tshowDock: elapsed >= 480,\r\n\t\t\tfocusPulseActive: Date.now() < this.focusPulseUntil,\r\n\t\t};\r\n\t}\r\n}\r\n"],"mappings":"AAUA,OAAO,MAAMA,iBAAiB,CAAC;EACtBC,KAAK,GAAG,CAAC;EAEAC,SAAS,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;EAC/BC,eAAe,GAAG,CAAC;EAE3BC,WAAWA,CAAkBC,EAAO,EAAE;IAAA,KAATA,EAAO,GAAPA,EAAO;IACnC,IAAI,CAACC,QAAQ,GAAGC,WAAW,CAAC,MAAM;MACjC,IAAI,CAACR,KAAK,IAAI,CAAC;MACf,IAAI,CAACM,EAAE,CAACG,aAAa,CAAC,CAAC;IACxB,CAAC,EAAE,GAAG,CAAC;EACR;EAEAC,OAAOA,CAAA,EAAS;IACf,IAAI,CAAC,IAAI,CAACH,QAAQ,EAAE;IACpBI,aAAa,CAAC,IAAI,CAACJ,QAAQ,CAAC;IAC5B,IAAI,CAACA,QAAQ,GAAGK,SAAS;EAC1B;EAEAC,cAAcA,CAAA,EAAS;IACtB,IAAI,CAACT,eAAe,GAAGF,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,GAAG;EACxC;EAEAW,WAAWA,CAAA,EAA+B;IACzC,MAAMC,OAAO,GAAGb,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAACF,SAAS;IAC3C,OAAO;MACND,KAAK,EAAE,IAAI,CAACA,KAAK;MACjBgB,QAAQ,EAAED,OAAO,IAAI,GAAG;MACxBE,aAAa,EAAEF,OAAO,IAAI,GAAG;MAC7BG,QAAQ,EAAEH,OAAO,IAAI,GAAG;MACxBI,gBAAgB,EAAEjB,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAACC;IACrC,CAAC;EACF;AACD","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ export * from "./animator.js";
2
+ export * from "./mouse.js";
3
+ export * from "./render.js";
4
+ export * from "./run-workbench.js";
5
+ export * from "./theme.js";
6
+ export * from "./workbench-shell.js";
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./animator.js\";\r\nexport * from \"./mouse.js\";\r\nexport * from \"./render.js\";\r\nexport * from \"./run-workbench.js\";\r\nexport * from \"./theme.js\";\r\nexport * from \"./workbench-shell.js\";\r\n"],"mappings":"AAAA,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,aAAa;AAC3B,cAAc,oBAAoB;AAClC,cAAc,YAAY;AAC1B,cAAc,sBAAsB","ignoreList":[]}
@@ -0,0 +1,39 @@
1
+ const SGR_MOUSE_PATTERN = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/;
2
+ export const ENABLE_MOUSE_SEQUENCE = "\x1b[?1000h\x1b[?1006h";
3
+ export const DISABLE_MOUSE_SEQUENCE = "\x1b[?1000l\x1b[?1006l";
4
+ export function parseMouseSequence(data) {
5
+ const match = data.match(SGR_MOUSE_PATTERN);
6
+ if (!match) {
7
+ return null;
8
+ }
9
+ const code = Number(match[1]);
10
+ const col = Number(match[2]);
11
+ const row = Number(match[3]);
12
+ const terminator = match[4];
13
+ const shift = (code & 4) !== 0;
14
+ const alt = (code & 8) !== 0;
15
+ const ctrl = (code & 16) !== 0;
16
+ const motion = (code & 32) !== 0;
17
+ const wheel = (code & 64) !== 0;
18
+ const baseButton = code & 3;
19
+ if (wheel) {
20
+ return {
21
+ button: baseButton === 0 ? "wheel-up" : baseButton === 1 ? "wheel-down" : "unknown",
22
+ action: "scroll",
23
+ row,
24
+ col,
25
+ shift,
26
+ alt,
27
+ ctrl
28
+ };
29
+ }
30
+ return {
31
+ button: baseButton === 0 ? "left" : baseButton === 1 ? "middle" : baseButton === 2 ? "right" : "unknown",
32
+ action: motion ? terminator === "M" ? "drag" : "move" : terminator === "M" ? "press" : "release",
33
+ row,
34
+ col,
35
+ shift,
36
+ alt,
37
+ ctrl
38
+ };
39
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SGR_MOUSE_PATTERN","ENABLE_MOUSE_SEQUENCE","DISABLE_MOUSE_SEQUENCE","parseMouseSequence","data","match","code","Number","col","row","terminator","shift","alt","ctrl","motion","wheel","baseButton","button","action"],"sources":["mouse.ts"],"sourcesContent":["export type MouseButton = \"left\" | \"middle\" | \"right\" | \"wheel-up\" | \"wheel-down\" | \"unknown\";\r\nexport type MouseAction = \"press\" | \"release\" | \"drag\" | \"move\" | \"scroll\";\r\n\r\nexport interface ParsedMouseEvent {\r\n\tbutton: MouseButton;\r\n\taction: MouseAction;\r\n\trow: number;\r\n\tcol: number;\r\n\tshift: boolean;\r\n\talt: boolean;\r\n\tctrl: boolean;\r\n}\r\n\r\nconst SGR_MOUSE_PATTERN = /^\\x1b\\[<(\\d+);(\\d+);(\\d+)([Mm])$/;\r\n\r\nexport const ENABLE_MOUSE_SEQUENCE = \"\\x1b[?1000h\\x1b[?1006h\";\r\nexport const DISABLE_MOUSE_SEQUENCE = \"\\x1b[?1000l\\x1b[?1006l\";\r\n\r\nexport function parseMouseSequence(data: string): ParsedMouseEvent | null {\r\n\tconst match = data.match(SGR_MOUSE_PATTERN);\r\n\tif (!match) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst code = Number(match[1]);\r\n\tconst col = Number(match[2]);\r\n\tconst row = Number(match[3]);\r\n\tconst terminator = match[4];\r\n\r\n\tconst shift = (code & 4) !== 0;\r\n\tconst alt = (code & 8) !== 0;\r\n\tconst ctrl = (code & 16) !== 0;\r\n\tconst motion = (code & 32) !== 0;\r\n\tconst wheel = (code & 64) !== 0;\r\n\tconst baseButton = code & 3;\r\n\r\n\tif (wheel) {\r\n\t\treturn {\r\n\t\t\tbutton: baseButton === 0 ? \"wheel-up\" : baseButton === 1 ? \"wheel-down\" : \"unknown\",\r\n\t\t\taction: \"scroll\",\r\n\t\t\trow,\r\n\t\t\tcol,\r\n\t\t\tshift,\r\n\t\t\talt,\r\n\t\t\tctrl,\r\n\t\t};\r\n\t}\r\n\r\n\treturn {\r\n\t\tbutton: baseButton === 0 ? \"left\" : baseButton === 1 ? \"middle\" : baseButton === 2 ? \"right\" : \"unknown\",\r\n\t\taction: motion ? (terminator === \"M\" ? \"drag\" : \"move\") : terminator === \"M\" ? \"press\" : \"release\",\r\n\t\trow,\r\n\t\tcol,\r\n\t\tshift,\r\n\t\talt,\r\n\t\tctrl,\r\n\t};\r\n}\r\n"],"mappings":"AAaA,MAAMA,iBAAiB,GAAG,kCAAkC;AAE5D,OAAO,MAAMC,qBAAqB,GAAG,wBAAwB;AAC7D,OAAO,MAAMC,sBAAsB,GAAG,wBAAwB;AAE9D,OAAO,SAASC,kBAAkBA,CAACC,IAAY,EAA2B;EACzE,MAAMC,KAAK,GAAGD,IAAI,CAACC,KAAK,CAACL,iBAAiB,CAAC;EAC3C,IAAI,CAACK,KAAK,EAAE;IACX,OAAO,IAAI;EACZ;EAEA,MAAMC,IAAI,GAAGC,MAAM,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;EAC7B,MAAMG,GAAG,GAAGD,MAAM,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;EAC5B,MAAMI,GAAG,GAAGF,MAAM,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;EAC5B,MAAMK,UAAU,GAAGL,KAAK,CAAC,CAAC,CAAC;EAE3B,MAAMM,KAAK,GAAG,CAACL,IAAI,GAAG,CAAC,MAAM,CAAC;EAC9B,MAAMM,GAAG,GAAG,CAACN,IAAI,GAAG,CAAC,MAAM,CAAC;EAC5B,MAAMO,IAAI,GAAG,CAACP,IAAI,GAAG,EAAE,MAAM,CAAC;EAC9B,MAAMQ,MAAM,GAAG,CAACR,IAAI,GAAG,EAAE,MAAM,CAAC;EAChC,MAAMS,KAAK,GAAG,CAACT,IAAI,GAAG,EAAE,MAAM,CAAC;EAC/B,MAAMU,UAAU,GAAGV,IAAI,GAAG,CAAC;EAE3B,IAAIS,KAAK,EAAE;IACV,OAAO;MACNE,MAAM,EAAED,UAAU,KAAK,CAAC,GAAG,UAAU,GAAGA,UAAU,KAAK,CAAC,GAAG,YAAY,GAAG,SAAS;MACnFE,MAAM,EAAE,QAAQ;MAChBT,GAAG;MACHD,GAAG;MACHG,KAAK;MACLC,GAAG;MACHC;IACD,CAAC;EACF;EAEA,OAAO;IACNI,MAAM,EAAED,UAAU,KAAK,CAAC,GAAG,MAAM,GAAGA,UAAU,KAAK,CAAC,GAAG,QAAQ,GAAGA,UAAU,KAAK,CAAC,GAAG,OAAO,GAAG,SAAS;IACxGE,MAAM,EAAEJ,MAAM,GAAIJ,UAAU,KAAK,GAAG,GAAG,MAAM,GAAG,MAAM,GAAIA,UAAU,KAAK,GAAG,GAAG,OAAO,GAAG,SAAS;IAClGD,GAAG;IACHD,GAAG;IACHG,KAAK;IACLC,GAAG;IACHC;EACD,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,82 @@
1
+ import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
2
+ export function blankLine(width) {
3
+ return " ".repeat(Math.max(0, width));
4
+ }
5
+ export function padLine(text, width) {
6
+ const trimmed = truncateToWidth(text, width, "");
7
+ const pad = Math.max(0, width - visibleWidth(trimmed));
8
+ return trimmed + " ".repeat(pad);
9
+ }
10
+ export function fitLines(lines, width, height) {
11
+ const fitted = lines.slice(0, Math.max(0, height)).map(line => padLine(line, width));
12
+ while (fitted.length < height) {
13
+ fitted.push(blankLine(width));
14
+ }
15
+ return fitted;
16
+ }
17
+ export function framePanelFixed(title, bodyLines, width, height, style) {
18
+ if (width <= 2 || height <= 0) {
19
+ return fitLines([], width, height);
20
+ }
21
+ const innerWidth = Math.max(1, width - 2);
22
+ const titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), "");
23
+ const borderPad = "-".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));
24
+ const top = style.border(`+${titleText}${borderPad}+`);
25
+ const bottom = style.border(`+${"-".repeat(innerWidth)}+`);
26
+ const usableBodyHeight = Math.max(0, height - 2);
27
+ const body = fitLines(bodyLines.slice(0, usableBodyHeight).map(line => style.body(`|${padLine(line, innerWidth)}|`)), width, usableBodyHeight);
28
+ return fitLines([top, ...body, bottom], width, height);
29
+ }
30
+ export function joinColumns(leftLines, leftWidth, rightLines, rightWidth, gap) {
31
+ const height = Math.max(leftLines.length, rightLines.length);
32
+ const gapText = " ".repeat(Math.max(0, gap));
33
+ const lines = [];
34
+ for (let i = 0; i < height; i += 1) {
35
+ const left = padLine(leftLines[i] ?? "", leftWidth);
36
+ const right = padLine(rightLines[i] ?? "", rightWidth);
37
+ lines.push(`${left}${gapText}${right}`);
38
+ }
39
+ return lines;
40
+ }
41
+ export function computeWorkbenchLayout(width, height) {
42
+ const headerHeight = height <= 18 ? 2 : 3;
43
+ const dockHeight = height <= 18 ? 5 : width >= 120 ? 7 : 6;
44
+ const bodyHeight = Math.max(6, height - headerHeight - dockHeight);
45
+ const gap = 1;
46
+ let showRail = width >= 84;
47
+ let showInspector = width >= 124;
48
+ let railWidth = showRail ? 24 : 0;
49
+ let inspectorWidth = showInspector ? 30 : 0;
50
+ let mainWidth = width - railWidth - inspectorWidth - (showRail ? gap : 0) - (showInspector ? gap : 0);
51
+ if (showInspector && mainWidth < 48) {
52
+ showInspector = false;
53
+ inspectorWidth = 0;
54
+ mainWidth = width - railWidth - (showRail ? gap : 0);
55
+ }
56
+ if (showRail && mainWidth < 42) {
57
+ showRail = false;
58
+ railWidth = 0;
59
+ mainWidth = width - inspectorWidth - (showInspector ? gap : 0);
60
+ }
61
+ return {
62
+ headerHeight,
63
+ bodyHeight,
64
+ dockHeight,
65
+ showRail,
66
+ showInspector,
67
+ railWidth,
68
+ mainWidth,
69
+ inspectorWidth,
70
+ gap
71
+ };
72
+ }
73
+ export function computeCenteredRect(viewportWidth, viewportHeight, width, height) {
74
+ const safeWidth = Math.max(10, Math.min(width, viewportWidth));
75
+ const safeHeight = Math.max(6, Math.min(height, viewportHeight));
76
+ return {
77
+ row: Math.max(1, Math.floor((viewportHeight - safeHeight) / 2) + 1),
78
+ col: Math.max(1, Math.floor((viewportWidth - safeWidth) / 2) + 1),
79
+ width: safeWidth,
80
+ height: safeHeight
81
+ };
82
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"names":["truncateToWidth","visibleWidth","blankLine","width","repeat","Math","max","padLine","text","trimmed","pad","fitLines","lines","height","fitted","slice","map","line","length","push","framePanelFixed","title","bodyLines","style","innerWidth","titleText","borderPad","top","border","bottom","usableBodyHeight","body","joinColumns","leftLines","leftWidth","rightLines","rightWidth","gap","gapText","i","left","right","computeWorkbenchLayout","headerHeight","dockHeight","bodyHeight","showRail","showInspector","railWidth","inspectorWidth","mainWidth","computeCenteredRect","viewportWidth","viewportHeight","safeWidth","min","safeHeight","row","floor","col"],"sources":["render.ts"],"sourcesContent":["import { truncateToWidth, visibleWidth } from \"@mariozechner/pi-tui\";\r\nimport type { PanelVisualStyle } from \"./theme.js\";\r\n\r\nexport interface Rect {\r\n\trow: number;\r\n\tcol: number;\r\n\twidth: number;\r\n\theight: number;\r\n}\r\n\r\nexport function blankLine(width: number): string {\r\n\treturn \" \".repeat(Math.max(0, width));\r\n}\r\n\r\nexport function padLine(text: string, width: number): string {\r\n\tconst trimmed = truncateToWidth(text, width, \"\");\r\n\tconst pad = Math.max(0, width - visibleWidth(trimmed));\r\n\treturn trimmed + \" \".repeat(pad);\r\n}\r\n\r\nexport function fitLines(lines: string[], width: number, height: number): string[] {\r\n\tconst fitted = lines.slice(0, Math.max(0, height)).map((line) => padLine(line, width));\r\n\twhile (fitted.length < height) {\r\n\t\tfitted.push(blankLine(width));\r\n\t}\r\n\treturn fitted;\r\n}\r\n\r\nexport function framePanelFixed(\r\n\ttitle: string,\r\n\tbodyLines: string[],\r\n\twidth: number,\r\n\theight: number,\r\n\tstyle: PanelVisualStyle,\r\n): string[] {\r\n\tif (width <= 2 || height <= 0) {\r\n\t\treturn fitLines([], width, height);\r\n\t}\r\n\r\n\tconst innerWidth = Math.max(1, width - 2);\r\n\tconst titleText = truncateToWidth(` ${title} `, Math.max(1, innerWidth), \"\");\r\n\tconst borderPad = \"-\".repeat(Math.max(0, innerWidth - visibleWidth(titleText)));\r\n\tconst top = style.border(`+${titleText}${borderPad}+`);\r\n\tconst bottom = style.border(`+${\"-\".repeat(innerWidth)}+`);\r\n\tconst usableBodyHeight = Math.max(0, height - 2);\r\n\tconst body = fitLines(\r\n\t\tbodyLines.slice(0, usableBodyHeight).map((line) => style.body(`|${padLine(line, innerWidth)}|`)),\r\n\t\twidth,\r\n\t\tusableBodyHeight,\r\n\t);\r\n\r\n\treturn fitLines([top, ...body, bottom], width, height);\r\n}\r\n\r\nexport function joinColumns(\r\n\tleftLines: string[],\r\n\tleftWidth: number,\r\n\trightLines: string[],\r\n\trightWidth: number,\r\n\tgap: number,\r\n): string[] {\r\n\tconst height = Math.max(leftLines.length, rightLines.length);\r\n\tconst gapText = \" \".repeat(Math.max(0, gap));\r\n\tconst lines: string[] = [];\r\n\r\n\tfor (let i = 0; i < height; i += 1) {\r\n\t\tconst left = padLine(leftLines[i] ?? \"\", leftWidth);\r\n\t\tconst right = padLine(rightLines[i] ?? \"\", rightWidth);\r\n\t\tlines.push(`${left}${gapText}${right}`);\r\n\t}\r\n\r\n\treturn lines;\r\n}\r\n\r\nexport function computeWorkbenchLayout(width: number, height: number): {\r\n\theaderHeight: number;\r\n\tbodyHeight: number;\r\n\tdockHeight: number;\r\n\tshowRail: boolean;\r\n\tshowInspector: boolean;\r\n\trailWidth: number;\r\n\tmainWidth: number;\r\n\tinspectorWidth: number;\r\n\tgap: number;\r\n} {\r\n\tconst headerHeight = height <= 18 ? 2 : 3;\r\n\tconst dockHeight = height <= 18 ? 5 : width >= 120 ? 7 : 6;\r\n\tconst bodyHeight = Math.max(6, height - headerHeight - dockHeight);\r\n\tconst gap = 1;\r\n\r\n\tlet showRail = width >= 84;\r\n\tlet showInspector = width >= 124;\r\n\tlet railWidth = showRail ? 24 : 0;\r\n\tlet inspectorWidth = showInspector ? 30 : 0;\r\n\r\n\tlet mainWidth = width - railWidth - inspectorWidth - (showRail ? gap : 0) - (showInspector ? gap : 0);\r\n\tif (showInspector && mainWidth < 48) {\r\n\t\tshowInspector = false;\r\n\t\tinspectorWidth = 0;\r\n\t\tmainWidth = width - railWidth - (showRail ? gap : 0);\r\n\t}\r\n\r\n\tif (showRail && mainWidth < 42) {\r\n\t\tshowRail = false;\r\n\t\trailWidth = 0;\r\n\t\tmainWidth = width - inspectorWidth - (showInspector ? gap : 0);\r\n\t}\r\n\r\n\treturn {\r\n\t\theaderHeight,\r\n\t\tbodyHeight,\r\n\t\tdockHeight,\r\n\t\tshowRail,\r\n\t\tshowInspector,\r\n\t\trailWidth,\r\n\t\tmainWidth,\r\n\t\tinspectorWidth,\r\n\t\tgap,\r\n\t};\r\n}\r\n\r\nexport function computeCenteredRect(viewportWidth: number, viewportHeight: number, width: number, height: number): Rect {\r\n\tconst safeWidth = Math.max(10, Math.min(width, viewportWidth));\r\n\tconst safeHeight = Math.max(6, Math.min(height, viewportHeight));\r\n\treturn {\r\n\t\trow: Math.max(1, Math.floor((viewportHeight - safeHeight) / 2) + 1),\r\n\t\tcol: Math.max(1, Math.floor((viewportWidth - safeWidth) / 2) + 1),\r\n\t\twidth: safeWidth,\r\n\t\theight: safeHeight,\r\n\t};\r\n}\r\n"],"mappings":"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","ignoreList":[]}