@huseynsnmz/pi-suite 0.0.0-stage → 0.2.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 (274) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +88 -2
  4. package/SECURITY.md +5 -0
  5. package/package.json +112 -4
  6. package/packages/board/CHANGELOG.md +340 -0
  7. package/packages/board/CONTRIBUTING.md +7 -0
  8. package/packages/board/LICENSE +21 -0
  9. package/packages/board/README.md +88 -0
  10. package/packages/board/SECURITY.md +19 -0
  11. package/packages/board/docs/how-it-works.md +31 -0
  12. package/packages/board/docs/reference.md +278 -0
  13. package/packages/board/package.json +81 -0
  14. package/packages/board/runner/job-runner-legacy.mjs +68 -0
  15. package/packages/board/runner/job-runner.mjs +834 -0
  16. package/packages/board/runner/pty-runner-legacy.mjs +50 -0
  17. package/packages/board/runner/pty-runner.mjs +2175 -0
  18. package/packages/board/runner/state-coordinator.mjs +673 -0
  19. package/packages/board/runner/state-runner.mjs +203 -0
  20. package/packages/board/runner/title-runner.mjs +80 -0
  21. package/packages/board/src/commands/agent-board.ts +394 -0
  22. package/packages/board/src/commands/attach-decision.mjs +66 -0
  23. package/packages/board/src/commands/attach-flow.ts +251 -0
  24. package/packages/board/src/commands/bg.ts +103 -0
  25. package/packages/board/src/commands/board-model.ts +21 -0
  26. package/packages/board/src/core/atomic.mjs +184 -0
  27. package/packages/board/src/core/attach-delete.mjs +24 -0
  28. package/packages/board/src/core/attach-frame-proof.mjs +870 -0
  29. package/packages/board/src/core/attach-frame-reporter.mjs +648 -0
  30. package/packages/board/src/core/attach-frame-stream.mjs +266 -0
  31. package/packages/board/src/core/attach-view-proof.mjs +709 -0
  32. package/packages/board/src/core/auto-state.mjs +377 -0
  33. package/packages/board/src/core/background-runs.mjs +273 -0
  34. package/packages/board/src/core/code-refs-store.mjs +315 -0
  35. package/packages/board/src/core/code-refs.mjs +913 -0
  36. package/packages/board/src/core/config.mjs +77 -0
  37. package/packages/board/src/core/control-protocol.mjs +482 -0
  38. package/packages/board/src/core/coordinator-client.mjs +633 -0
  39. package/packages/board/src/core/coordinator-journal.mjs +282 -0
  40. package/packages/board/src/core/coordinator-protocol.mjs +14 -0
  41. package/packages/board/src/core/cwd-stats.mjs +114 -0
  42. package/packages/board/src/core/dashboard-render.mjs +10 -0
  43. package/packages/board/src/core/derive.mjs +117 -0
  44. package/packages/board/src/core/diagnostics.mjs +133 -0
  45. package/packages/board/src/core/double-press.mjs +26 -0
  46. package/packages/board/src/core/editor-state-reporter.mjs +112 -0
  47. package/packages/board/src/core/events.mjs +286 -0
  48. package/packages/board/src/core/evidence.mjs +245 -0
  49. package/packages/board/src/core/follow-up-queue.mjs +211 -0
  50. package/packages/board/src/core/foreground-preview-cache.mjs +117 -0
  51. package/packages/board/src/core/foreground-projection-cache.mjs +99 -0
  52. package/packages/board/src/core/frame-witness-update.mjs +35 -0
  53. package/packages/board/src/core/heuristics.mjs +313 -0
  54. package/packages/board/src/core/hold-input.mjs +27 -0
  55. package/packages/board/src/core/host-coordination.mjs +300 -0
  56. package/packages/board/src/core/host-crash.mjs +79 -0
  57. package/packages/board/src/core/host-probe.mjs +207 -0
  58. package/packages/board/src/core/host-protocol.mjs +73 -0
  59. package/packages/board/src/core/ids.mjs +35 -0
  60. package/packages/board/src/core/ime-cursor-coalesce.mjs +193 -0
  61. package/packages/board/src/core/invocation.mjs +43 -0
  62. package/packages/board/src/core/launch-options.mjs +418 -0
  63. package/packages/board/src/core/launch.mjs +157 -0
  64. package/packages/board/src/core/load-config.mjs +4 -0
  65. package/packages/board/src/core/locks.mjs +530 -0
  66. package/packages/board/src/core/paths.mjs +183 -0
  67. package/packages/board/src/core/pid.mjs +75 -0
  68. package/packages/board/src/core/prewarm-schedule.mjs +41 -0
  69. package/packages/board/src/core/process-identity-probe.mjs +228 -0
  70. package/packages/board/src/core/prompt-transport.mjs +13 -0
  71. package/packages/board/src/core/pty-attach-jiggle-controller.mjs +356 -0
  72. package/packages/board/src/core/pty-attach-jiggle-retry.mjs +109 -0
  73. package/packages/board/src/core/pty-attach-reconnect.mjs +61 -0
  74. package/packages/board/src/core/pty-attach-render.mjs +229 -0
  75. package/packages/board/src/core/pty-links.mjs +81 -0
  76. package/packages/board/src/core/pty-scroll.mjs +522 -0
  77. package/packages/board/src/core/pty-support.mjs +327 -0
  78. package/packages/board/src/core/repo.mjs +103 -0
  79. package/packages/board/src/core/rows.mjs +414 -0
  80. package/packages/board/src/core/screen-log-gc.mjs +198 -0
  81. package/packages/board/src/core/screen-log.mjs +160 -0
  82. package/packages/board/src/core/session-view.mjs +174 -0
  83. package/packages/board/src/core/slash-commands.mjs +52 -0
  84. package/packages/board/src/core/state-commands.mjs +757 -0
  85. package/packages/board/src/core/status-consistency.mjs +98 -0
  86. package/packages/board/src/core/steering-prompts.mjs +34 -0
  87. package/packages/board/src/core/steering.mjs +133 -0
  88. package/packages/board/src/core/stop-latch.mjs +41 -0
  89. package/packages/board/src/core/store.mjs +523 -0
  90. package/packages/board/src/core/suspend.mjs +36 -0
  91. package/packages/board/src/core/terminal-attach-client.mjs +981 -0
  92. package/packages/board/src/core/terminal-attach-protocol.mjs +460 -0
  93. package/packages/board/src/core/terminal-model.mjs +222 -0
  94. package/packages/board/src/core/terminal-query-sequences.mjs +239 -0
  95. package/packages/board/src/core/terminal-reply-guard.mjs +222 -0
  96. package/packages/board/src/core/terminal-snapshot.mjs +440 -0
  97. package/packages/board/src/core/test-knobs.mjs +28 -0
  98. package/packages/board/src/core/title.mjs +43 -0
  99. package/packages/board/src/core/types.mjs +414 -0
  100. package/packages/board/src/core/warm-host-sweeper.mjs +168 -0
  101. package/packages/board/src/core/worktree.mjs +65 -0
  102. package/packages/board/src/index.ts +303 -0
  103. package/packages/board/src/runtime/service.mjs +3222 -0
  104. package/packages/board/src/ui/chrome.ts +20 -0
  105. package/packages/board/src/ui/dashboard-decisions.mjs +55 -0
  106. package/packages/board/src/ui/dashboard-evidence.mjs +85 -0
  107. package/packages/board/src/ui/dashboard.ts +2237 -0
  108. package/packages/board/src/ui/double-left.ts +30 -0
  109. package/packages/board/src/ui/external-editor.ts +25 -0
  110. package/packages/board/src/ui/focus.ts +32 -0
  111. package/packages/board/src/ui/pty-attach.ts +3184 -0
  112. package/packages/board/src/ui/waiting.ts +30 -0
  113. package/packages/commands/LICENSE +21 -0
  114. package/packages/commands/README.md +19 -0
  115. package/packages/commands/package.json +22 -0
  116. package/packages/commands/src/index.ts +43 -0
  117. package/packages/commands/src/security-review.ts +109 -0
  118. package/packages/frame/CHANGELOG.md +113 -0
  119. package/packages/frame/CONTRIBUTING.md +7 -0
  120. package/packages/frame/LICENSE +22 -0
  121. package/packages/frame/README.md +105 -0
  122. package/packages/frame/SECURITY.md +16 -0
  123. package/packages/frame/docs/how-it-works.md +53 -0
  124. package/packages/frame/docs/reference.md +78 -0
  125. package/packages/frame/package.json +72 -0
  126. package/packages/frame/src/data/git.ts +90 -0
  127. package/packages/frame/src/data/github.ts +140 -0
  128. package/packages/frame/src/data/gitlab.ts +63 -0
  129. package/packages/frame/src/data/mode.ts +49 -0
  130. package/packages/frame/src/data/past-prompts.ts +57 -0
  131. package/packages/frame/src/data/runner.ts +32 -0
  132. package/packages/frame/src/data/snapshot.ts +223 -0
  133. package/packages/frame/src/data/start-notes.ts +104 -0
  134. package/packages/frame/src/data/telemetry.ts +337 -0
  135. package/packages/frame/src/data/todos.ts +162 -0
  136. package/packages/frame/src/data/totals.ts +94 -0
  137. package/packages/frame/src/data/visits.ts +45 -0
  138. package/packages/frame/src/index.ts +696 -0
  139. package/packages/frame/src/kit/LICENSE +21 -0
  140. package/packages/frame/src/kit/app/attribution.ts +30 -0
  141. package/packages/frame/src/kit/app/builder.ts +186 -0
  142. package/packages/frame/src/kit/app/claim.ts +27 -0
  143. package/packages/frame/src/kit/app/feature.ts +91 -0
  144. package/packages/frame/src/kit/app/host.ts +214 -0
  145. package/packages/frame/src/kit/app/renderers.ts +62 -0
  146. package/packages/frame/src/kit/app/scope.ts +125 -0
  147. package/packages/frame/src/kit/board/model.ts +337 -0
  148. package/packages/frame/src/kit/contract.ts +79 -0
  149. package/packages/frame/src/kit/contracts/accounts.ts +33 -0
  150. package/packages/frame/src/kit/contracts/ask.ts +120 -0
  151. package/packages/frame/src/kit/contracts/board.ts +6 -0
  152. package/packages/frame/src/kit/contracts/by.ts +22 -0
  153. package/packages/frame/src/kit/contracts/calls.ts +46 -0
  154. package/packages/frame/src/kit/contracts/events.ts +89 -0
  155. package/packages/frame/src/kit/contracts/mode.ts +26 -0
  156. package/packages/frame/src/kit/contracts/names.ts +12 -0
  157. package/packages/frame/src/kit/contracts/peers.ts +77 -0
  158. package/packages/frame/src/kit/contracts/prompts.ts +8 -0
  159. package/packages/frame/src/kit/contracts/screen.ts +75 -0
  160. package/packages/frame/src/kit/contracts/skills.ts +81 -0
  161. package/packages/frame/src/kit/contracts/sources.ts +81 -0
  162. package/packages/frame/src/kit/contracts/views.ts +42 -0
  163. package/packages/frame/src/kit/control.ts +59 -0
  164. package/packages/frame/src/kit/dark-theme.ts +41 -0
  165. package/packages/frame/src/kit/decode.ts +210 -0
  166. package/packages/frame/src/kit/events/log.ts +313 -0
  167. package/packages/frame/src/kit/format.ts +25 -0
  168. package/packages/frame/src/kit/host.ts +4 -0
  169. package/packages/frame/src/kit/index.ts +25 -0
  170. package/packages/frame/src/kit/legacy-tasks.ts +39 -0
  171. package/packages/frame/src/kit/overlay-images.ts +36 -0
  172. package/packages/frame/src/kit/paths.ts +16 -0
  173. package/packages/frame/src/kit/screen/client.ts +74 -0
  174. package/packages/frame/src/kit/screen/feature.ts +64 -0
  175. package/packages/frame/src/kit/screen/model.ts +182 -0
  176. package/packages/frame/src/kit/screen/view.ts +838 -0
  177. package/packages/frame/src/kit/settings/files.ts +90 -0
  178. package/packages/frame/src/kit/settings/setting.ts +57 -0
  179. package/packages/frame/src/kit/settings/store.ts +192 -0
  180. package/packages/frame/src/kit/sources/file.ts +129 -0
  181. package/packages/frame/src/kit/sources/follow.ts +155 -0
  182. package/packages/frame/src/kit/testing.ts +260 -0
  183. package/packages/frame/src/kit/totals.ts +72 -0
  184. package/packages/frame/src/kit/ui/entry.ts +75 -0
  185. package/packages/frame/src/kit/ui/frame.ts +212 -0
  186. package/packages/frame/src/kit/ui/glyphs.ts +132 -0
  187. package/packages/frame/src/kit/ui/scroll.ts +14 -0
  188. package/packages/frame/src/render/diff.ts +157 -0
  189. package/packages/frame/src/render/fit.ts +86 -0
  190. package/packages/frame/src/render/format.ts +108 -0
  191. package/packages/frame/src/render/frame.ts +106 -0
  192. package/packages/frame/src/render/glyphs.ts +189 -0
  193. package/packages/frame/src/render/keys.ts +43 -0
  194. package/packages/frame/src/render/lead.ts +37 -0
  195. package/packages/frame/src/render/paint.ts +135 -0
  196. package/packages/frame/src/render/safe.ts +19 -0
  197. package/packages/frame/src/render/segments.ts +735 -0
  198. package/packages/frame/src/render/streaming.ts +223 -0
  199. package/packages/frame/src/render/timing.ts +106 -0
  200. package/packages/frame/src/render/tools.ts +167 -0
  201. package/packages/frame/src/settings.ts +105 -0
  202. package/packages/frame/src/ui/editor.ts +272 -0
  203. package/packages/frame/src/ui/effort.ts +36 -0
  204. package/packages/frame/src/ui/footer.ts +165 -0
  205. package/packages/frame/src/ui/header.ts +362 -0
  206. package/packages/frame/src/ui/history-search.ts +23 -0
  207. package/packages/frame/src/ui/interrupt.ts +21 -0
  208. package/packages/frame/src/ui/outputs.ts +170 -0
  209. package/packages/frame/src/ui/pi-entries.ts +298 -0
  210. package/packages/frame/src/ui/previews.ts +72 -0
  211. package/packages/frame/src/ui/queue.ts +75 -0
  212. package/packages/frame/src/ui/screen.ts +59 -0
  213. package/packages/frame/src/ui/timings.ts +48 -0
  214. package/packages/frame/src/ui/todos.ts +205 -0
  215. package/packages/frame/src/ui/tool-frame.ts +595 -0
  216. package/packages/frame/src/ui/working.ts +25 -0
  217. package/packages/frame/src/view/state.ts +97 -0
  218. package/packages/frame/src/view/transcript.ts +175 -0
  219. package/packages/frame/src/view/view.ts +162 -0
  220. package/packages/memory/CONTRIBUTING.md +7 -0
  221. package/packages/memory/LICENSE +21 -0
  222. package/packages/memory/README.md +44 -0
  223. package/packages/memory/SECURITY.md +20 -0
  224. package/packages/memory/package.json +55 -0
  225. package/packages/memory/skills/review-memory/SKILL.md +48 -0
  226. package/packages/memory/src/index.ts +163 -0
  227. package/packages/memory/src/prompt.ts +25 -0
  228. package/packages/memory/src/review.ts +150 -0
  229. package/packages/memory/src/secrets.ts +22 -0
  230. package/packages/memory/src/store.ts +173 -0
  231. package/packages/modes/CHANGELOG.md +104 -0
  232. package/packages/modes/CONTRIBUTING.md +7 -0
  233. package/packages/modes/LICENSE +21 -0
  234. package/packages/modes/README.md +174 -0
  235. package/packages/modes/SECURITY.md +17 -0
  236. package/packages/modes/package.json +55 -0
  237. package/packages/modes/skills/review-permissions/SKILL.md +54 -0
  238. package/packages/modes/src/bash.ts +218 -0
  239. package/packages/modes/src/deny-off.ts +62 -0
  240. package/packages/modes/src/git-safety.ts +72 -0
  241. package/packages/modes/src/index.ts +338 -0
  242. package/packages/modes/src/interview.ts +206 -0
  243. package/packages/modes/src/judge-gate.ts +113 -0
  244. package/packages/modes/src/modes.ts +121 -0
  245. package/packages/modes/src/review/apply.mjs +156 -0
  246. package/packages/modes/src/review/collect.mjs +208 -0
  247. package/packages/modes/src/review/tools.ts +71 -0
  248. package/packages/modes/src/sandbox.ts +37 -0
  249. package/packages/router/CHANGELOG.md +8 -0
  250. package/packages/router/LICENSE +21 -0
  251. package/packages/router/README.md +90 -0
  252. package/packages/router/package.json +51 -0
  253. package/packages/router/src/config.ts +65 -0
  254. package/packages/router/src/index.ts +172 -0
  255. package/packages/router/src/judge.ts +51 -0
  256. package/packages/router/src/route.ts +67 -0
  257. package/packages/web/CHANGELOG.md +36 -0
  258. package/packages/web/LICENSE +21 -0
  259. package/packages/web/README.md +87 -0
  260. package/packages/web/SECURITY.md +13 -0
  261. package/packages/web/package.json +59 -0
  262. package/packages/web/src/config.ts +109 -0
  263. package/packages/web/src/dnsfilter.ts +97 -0
  264. package/packages/web/src/extract.ts +65 -0
  265. package/packages/web/src/index.ts +217 -0
  266. package/packages/web/src/markdown.ts +122 -0
  267. package/packages/web/src/net.ts +109 -0
  268. package/packages/web/src/reader.ts +73 -0
  269. package/packages/web/src/sanitize.ts +50 -0
  270. package/packages/web/src/search.ts +76 -0
  271. package/packages/web/src/secrets.ts +22 -0
  272. package/packages/web/src/validate.ts +186 -0
  273. package/src/index.ts +156 -0
  274. package/src/settings.ts +79 -0
@@ -0,0 +1,189 @@
1
+ export type IconMode = "auto" | "nerd" | "unicode" | "ascii";
2
+ export type IconSet = Exclude<IconMode, "auto">;
3
+
4
+ export interface Glyphs {
5
+ set: IconSet;
6
+ folder: string;
7
+ branch: string;
8
+ host: string;
9
+ session: string;
10
+ board: string;
11
+ peers: string;
12
+ waiting: string;
13
+ queued: string;
14
+ version: string;
15
+ model: string;
16
+ effort: string;
17
+ context: string;
18
+ speed: string;
19
+ wait: string;
20
+ running: string;
21
+ done: string;
22
+ sent: string;
23
+ received: string;
24
+ cacheRead: string;
25
+ cacheWrite: string;
26
+ cost: string;
27
+ clock: string;
28
+ plug: string;
29
+ ahead: string;
30
+ behind: string;
31
+ staged: string;
32
+ modified: string;
33
+ untracked: string;
34
+ conflicted: string;
35
+ stashed: string;
36
+ fill: string;
37
+ empty: string;
38
+ ellipsis: string;
39
+ /** Between the folder's agents and each shared room's. */
40
+ apart: string;
41
+ /** How this session stands in a room, as the rooms panel marks it. */
42
+ roomIn: string;
43
+ roomListening: string;
44
+ roomOut: string;
45
+ /** An agent at work and one waiting for work, as the panel and the board mark them. */
46
+ agentWorking: string;
47
+ agentIdle: string;
48
+ }
49
+
50
+ const COMMON = {
51
+ ahead: "↑",
52
+ behind: "↓",
53
+ staged: "+",
54
+ modified: "~",
55
+ untracked: "?",
56
+ conflicted: "!",
57
+ sent: "↑",
58
+ received: "↓",
59
+ apart: "│",
60
+ roomIn: "●",
61
+ roomListening: "◐",
62
+ roomOut: "○",
63
+ agentWorking: "◆",
64
+ agentIdle: "◇",
65
+ };
66
+
67
+ export const NERD: Glyphs = {
68
+ ...COMMON,
69
+ set: "nerd",
70
+ folder: "\u{f07c}", // nf-fa-folder_open
71
+ branch: "\u{e0a0}", // nf-pl-branch
72
+ host: "\u{f108}", // nf-fa-desktop
73
+ session: "\u{f02b}", // nf-fa-tag
74
+ board: "\u{f04fe}", // nf-md-target
75
+ peers: "\u{f0c0}", // nf-fa-users
76
+ waiting: "\u{f024}", // nf-fa-flag
77
+ queued: "\u{f051f}", // nf-md-timer_sand
78
+ version: "π",
79
+ model: "\u{f06a9}", // nf-md-robot
80
+ effort: "\u{f09d1}", // nf-md-brain
81
+ context: "\u{f035b}", // nf-md-memory
82
+ speed: "\u{f04c5}", // nf-md-speedometer
83
+ wait: "\u{f252}", // nf-fa-hourglass_half
84
+ running: "\u{f017}", // nf-fa-clock_o
85
+ done: "\u{f00c}", // nf-fa-check
86
+ cacheRead: "\u{f1c0}", // nf-fa-database
87
+ cacheWrite: "\u{f0c7}", // nf-fa-floppy_o
88
+ cost: "$",
89
+ clock: "\u{f017}", // nf-fa-clock_o
90
+ plug: "\u{f1e6}", // nf-fa-plug
91
+ stashed: "\u{f01c}", // nf-fa-inbox
92
+ fill: "█",
93
+ empty: "░",
94
+ ellipsis: "...",
95
+ };
96
+
97
+ export const UNICODE: Glyphs = {
98
+ ...COMMON,
99
+ set: "unicode",
100
+ folder: "▸",
101
+ branch: "⎇",
102
+ host: "⌂",
103
+ session: "#",
104
+ board: "▸",
105
+ peers: "◆",
106
+ waiting: "⚑",
107
+ queued: "⧗",
108
+ version: "π",
109
+ model: "◆",
110
+ effort: "✦",
111
+ context: "◔",
112
+ speed: "»",
113
+ wait: "⧗",
114
+ running: "◷",
115
+ done: "✓",
116
+ cacheRead: "≋",
117
+ cacheWrite: "≈",
118
+ cost: "$",
119
+ clock: "◷",
120
+ plug: "≫",
121
+ stashed: "≡",
122
+ fill: "█",
123
+ empty: "░",
124
+ ellipsis: "...",
125
+ };
126
+
127
+ export const ASCII: Glyphs = {
128
+ set: "ascii",
129
+ apart: "|",
130
+ roomIn: "+",
131
+ roomListening: "~",
132
+ roomOut: "-",
133
+ agentWorking: ">",
134
+ agentIdle: "-",
135
+ folder: "",
136
+ branch: "",
137
+ host: "@",
138
+ session: "#",
139
+ board: ">",
140
+ peers: "@",
141
+ waiting: "",
142
+ queued: "",
143
+ version: "v",
144
+ model: "",
145
+ effort: "",
146
+ context: "ctx",
147
+ speed: "",
148
+ wait: "ttft",
149
+ running: "",
150
+ done: "",
151
+ sent: "^",
152
+ received: "v",
153
+ cacheRead: "R",
154
+ cacheWrite: "W",
155
+ cost: "$",
156
+ clock: "",
157
+ plug: ">>",
158
+ ahead: "^",
159
+ behind: "v",
160
+ staged: "+",
161
+ modified: "~",
162
+ untracked: "?",
163
+ conflicted: "!",
164
+ stashed: "s",
165
+ fill: "#",
166
+ empty: "-",
167
+ ellipsis: "...",
168
+ };
169
+
170
+ const SETS: Record<IconSet, Glyphs> = { nerd: NERD, unicode: UNICODE, ascii: ASCII };
171
+
172
+ export function resolveIcons(mode: IconMode, env: NodeJS.ProcessEnv = process.env): Glyphs {
173
+ if (mode !== "auto") return SETS[mode];
174
+ if (env.TERM === "dumb") return ASCII;
175
+ const locale = env.LC_ALL ?? env.LC_CTYPE ?? env.LANG;
176
+ if (locale !== undefined && locale !== "" && !/utf-?8/i.test(locale)) return ASCII;
177
+ // Nothing can tell which font the terminal draws with, and a missing icon shows as a box or `[?]`.
178
+ return UNICODE;
179
+ }
180
+
181
+ /** Resolved again only when the setting changes; resolving per drawing was a fifth of typing's cost. */
182
+ export function glyphsOf(modeOf: () => IconMode): () => Glyphs {
183
+ let known: { mode: IconMode; glyphs: Glyphs } | undefined;
184
+ return () => {
185
+ const mode = modeOf();
186
+ if (known?.mode !== mode) known = { mode, glyphs: resolveIcons(mode) };
187
+ return known.glyphs;
188
+ };
189
+ }
@@ -0,0 +1,43 @@
1
+ import { type KeyId, matchesKey } from "@earendil-works/pi-tui";
2
+
3
+ /** Opens the settings. Alt+S belongs to pi-sandbox, which can't be rebound. */
4
+ export const SETTINGS_KEY = "ctrl+s";
5
+
6
+ /**
7
+ * Pi warns at every start about a shortcut on Ctrl+S, which its pickers use for themselves. So the
8
+ * shortcut sits here and the editor passes Ctrl+S on to it, which leaves the pickers their key.
9
+ */
10
+ export const SETTINGS_SHORTCUT = "ctrl+alt+s";
11
+ export const SETTINGS_SHORTCUT_INPUT = "\u001b[115;7u";
12
+
13
+ /** Cmd reaches Pi only through the kitty keyboard protocol, and not every Cmd key: these are free. */
14
+ const CMD_KEYS: Readonly<Record<string, { key: string; sends: string }>> = {
15
+ s: { key: SETTINGS_KEY, sends: "\u0013" },
16
+ o: { key: "alt+o", sends: "\u001b[111;3u" },
17
+ };
18
+
19
+ let reportsCmd: () => boolean = () => false;
20
+
21
+ /** Called with the terminal once there is one. It answers after the first draw. */
22
+ export function watchCmdKey(reports: () => boolean): void {
23
+ reportsCmd = reports;
24
+ }
25
+
26
+ /** A Mac has Option where others have Alt, and Cmd where the terminal can send it. */
27
+ export function keyLabel(
28
+ key: string,
29
+ platform: string = process.platform,
30
+ cmd: boolean = reportsCmd(),
31
+ ): string {
32
+ if (platform !== "darwin") return key;
33
+ const letter = Object.keys(CMD_KEYS).find((name) => CMD_KEYS[name]?.key === key);
34
+ if (cmd && letter !== undefined) return `cmd+${letter}`;
35
+ return key.replace(/\balt\+/g, "option+");
36
+ }
37
+
38
+ /** A Cmd key as the key its shortcut listens for. Undefined for any other input. */
39
+ export function cmdAsKey(data: string): string | undefined {
40
+ for (const [letter, { sends }] of Object.entries(CMD_KEYS))
41
+ if (matchesKey(data, `super+${letter}` as KeyId)) return sends;
42
+ return undefined;
43
+ }
@@ -0,0 +1,37 @@
1
+ /** How much of a prompt Pi will treat as a command: `/name` or `!command`, up to the first space. */
2
+ export function promptLead(text: string): { kind: "command" | "bash"; length: number } | undefined {
3
+ const command = /^\/[\w:.-]+(?=\s|$)/.exec(text);
4
+ if (command) return { kind: "command", length: command[0].length };
5
+ const bash = /^!{1,2}\s*\S*/.exec(text);
6
+ return bash ? { kind: "bash", length: bash[0].length } : undefined;
7
+ }
8
+
9
+ // oxlint-disable-next-line no-control-regex -- a rendered line carries escapes between its characters
10
+ const ESCAPE = /^\x1b(?:\[[0-9;?]*[ -/]*[@-~]|[_\]][^\x07\x1b]*(?:\x07|\x1b\\))/;
11
+
12
+ /** Paints the first characters of a rendered line. Its escapes, like the cursor, stay where they are. */
13
+ export function paintLead(line: string, length: number, paint: (text: string) => string): string {
14
+ let out = "";
15
+ let run = "";
16
+ let left = length;
17
+ let at = 0;
18
+ const flush = () => {
19
+ if (run) out += paint(run);
20
+ run = "";
21
+ };
22
+ while (at < line.length && left > 0) {
23
+ const escape = ESCAPE.exec(line.slice(at));
24
+ if (escape) {
25
+ flush();
26
+ out += escape[0];
27
+ at += escape[0].length;
28
+ continue;
29
+ }
30
+ const char = String.fromCodePoint(line.codePointAt(at) as number);
31
+ run += char;
32
+ at += char.length;
33
+ left--;
34
+ }
35
+ flush();
36
+ return out + line.slice(at);
37
+ }
@@ -0,0 +1,135 @@
1
+ import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
2
+
3
+ export type Role =
4
+ | "path"
5
+ | "branch"
6
+ | "ahead"
7
+ | "behind"
8
+ | "staged"
9
+ | "modified"
10
+ | "untracked"
11
+ | "conflicted"
12
+ | "host"
13
+ | "session"
14
+ | "board"
15
+ | "waiting"
16
+ | "queued"
17
+ | "version"
18
+ | "provider"
19
+ | "model"
20
+ | "sent"
21
+ | "received"
22
+ | "cache"
23
+ | "speed"
24
+ | "wait"
25
+ | "running"
26
+ | "done"
27
+ | "cost"
28
+ | "clock"
29
+ | "brand";
30
+
31
+ export const ROLE_TOKENS: Record<Role, ThemeColor> = {
32
+ path: "accent",
33
+ branch: "syntaxFunction",
34
+ ahead: "success",
35
+ behind: "warning",
36
+ staged: "success",
37
+ modified: "warning",
38
+ untracked: "muted",
39
+ conflicted: "error",
40
+ host: "syntaxType",
41
+ session: "mdHeading",
42
+ board: "accent",
43
+ waiting: "warning",
44
+ queued: "muted",
45
+ version: "muted",
46
+ provider: "syntaxKeyword",
47
+ model: "text",
48
+ sent: "mdLink",
49
+ received: "success",
50
+ cache: "syntaxType",
51
+ speed: "success",
52
+ wait: "syntaxNumber",
53
+ running: "accent",
54
+ done: "success",
55
+ cost: "syntaxNumber",
56
+ clock: "muted",
57
+ brand: "accent",
58
+ };
59
+
60
+ const EFFORT_TOKENS: Record<string, ThemeColor> = {
61
+ off: "thinkingOff",
62
+ minimal: "thinkingMinimal",
63
+ low: "thinkingLow",
64
+ medium: "thinkingMedium",
65
+ high: "thinkingHigh",
66
+ xhigh: "thinkingXhigh",
67
+ max: "thinkingMax",
68
+ };
69
+
70
+ export const EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"] as const;
71
+
72
+ export interface Paint {
73
+ dim(text: string): string;
74
+ muted(text: string): string;
75
+ text(text: string): string;
76
+ bold(text: string): string;
77
+ italic(text: string): string;
78
+ role(role: Role, text: string): string;
79
+ effort(level: string, text: string): string;
80
+ stress(percent: number, text: string): string;
81
+ money(amount: number, text: string): string;
82
+ frame(text: string): string;
83
+ /** A theme color a package named in a contract, like a peer's. */
84
+ raw(color: string, text: string): string;
85
+ }
86
+
87
+ export function themePaint(theme: Theme, frame?: (text: string) => string): Paint {
88
+ return {
89
+ dim: (text) => theme.fg("dim", text),
90
+ muted: (text) => theme.fg("muted", text),
91
+ text: (text) => theme.fg("text", text),
92
+ bold: (text) => theme.bold(text),
93
+ italic: (text) => theme.italic(text),
94
+ role: (role, text) => theme.fg(ROLE_TOKENS[role], text),
95
+ effort: (level, text) => theme.fg(EFFORT_TOKENS[level] ?? "thinkingOff", text),
96
+ stress: (percent, text) => theme.fg(stressToken(percent), text),
97
+ money: (amount, text) => theme.fg(moneyToken(amount), text),
98
+ frame: frame ?? ((text) => theme.fg("border", text)),
99
+ raw: (color, text) =>
100
+ theme.fg(
101
+ theme.colors[color as ThemeColor] === undefined ? "muted" : (color as ThemeColor),
102
+ text,
103
+ ),
104
+ };
105
+ }
106
+
107
+ function stressToken(percent: number): ThemeColor {
108
+ if (percent >= 90) return "error";
109
+ if (percent >= 70) return "warning";
110
+ return "success";
111
+ }
112
+
113
+ function moneyToken(amount: number): ThemeColor {
114
+ if (amount >= 10) return "error";
115
+ if (amount >= 1) return "warning";
116
+ return ROLE_TOKENS.cost;
117
+ }
118
+
119
+ export const PLAIN: Paint = {
120
+ dim: identity,
121
+ muted: identity,
122
+ text: identity,
123
+ bold: identity,
124
+ italic: identity,
125
+ role: (_role, text) => text,
126
+ effort: (_level, text) => text,
127
+ stress: (_percent, text) => text,
128
+ money: (_amount, text) => text,
129
+ frame: identity,
130
+ raw: (_color, text) => text,
131
+ };
132
+
133
+ function identity(text: string): string {
134
+ return text;
135
+ }
@@ -0,0 +1,19 @@
1
+ // Text from a model, a repository or another program must not drive the terminal: no clipboard
2
+ // writes, no moved cursor, no command that reads differently from what runs.
3
+
4
+ // oxlint-disable-next-line no-control-regex -- escape sequences are what this removes
5
+ const ESCAPE = /\u001b(?:\[[0-?]*[ -/]*[@-~]?|[\]PX^_][^\u0007\u001b\n]*(?:\u0007|\u001b\\)?|[ -/]*[0-~]?)/g;
6
+ // oxlint-disable-next-line no-control-regex -- color codes are escape sequences
7
+ const COLOR = /^\u001b\[[0-9;:]*m$/;
8
+ /** Keeps tabs and line breaks. ESCAPE has already taken every escape character. */
9
+ // oxlint-disable-next-line no-control-regex -- control characters are what this removes
10
+ const CONTROLS = /[\u0000-\u0008\u000b-\u001a\u001c-\u001f\u007f-\u009f‪-‮⁦-⁩]/g;
11
+
12
+ export function plainText(text: string): string {
13
+ return text.replace(ESCAPE, "").replace(CONTROLS, "");
14
+ }
15
+
16
+ /** For lines already painted: keeps the colors and nothing else that talks to the terminal. */
17
+ export function styledText(text: string): string {
18
+ return text.replace(ESCAPE, (found) => (COLOR.test(found) ? found : "")).replace(CONTROLS, "");
19
+ }