rimuru-ai 1.19.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 (470) hide show
  1. package/.rimuru/AGENTS.md +30 -0
  2. package/.rimuru/agents/backend.md +27 -0
  3. package/.rimuru/agents/database.md +31 -0
  4. package/.rimuru/agents/devops.md +30 -0
  5. package/.rimuru/agents/document-prep.md +49 -0
  6. package/.rimuru/agents/erp-architect.md +41 -0
  7. package/.rimuru/agents/ethical-hacking.md +49 -0
  8. package/.rimuru/agents/frontend.md +31 -0
  9. package/.rimuru/agents/fullstack.md +24 -0
  10. package/.rimuru/agents/system-engineer.md +31 -0
  11. package/.rimuru/agents/veldora-agent-tool-dev.md +30 -0
  12. package/.rimuru/agents/veldora-backend-dev.md +32 -0
  13. package/.rimuru/agents/veldora-cicd.md +32 -0
  14. package/.rimuru/agents/veldora-database.md +32 -0
  15. package/.rimuru/agents/veldora-doc.md +87 -0
  16. package/.rimuru/agents/veldora-frontend-dev.md +32 -0
  17. package/.rimuru/agents/veldora-great-sage.md +33 -0
  18. package/.rimuru/agents/veldora-mcp-creator.md +30 -0
  19. package/.rimuru/agents/veldora-pro.md +224 -0
  20. package/.rimuru/agents/veldora-prompt-enhancer.md +27 -0
  21. package/.rimuru/agents/veldora-skill-creator.md +28 -0
  22. package/.rimuru/agents/veldora.md +225 -0
  23. package/.rimuru/agents/veldorapro-agent-tool-dev.md +29 -0
  24. package/.rimuru/agents/veldorapro-backend-dev.md +29 -0
  25. package/.rimuru/agents/veldorapro-cicd.md +29 -0
  26. package/.rimuru/agents/veldorapro-database.md +29 -0
  27. package/.rimuru/agents/veldorapro-frontend-dev.md +29 -0
  28. package/.rimuru/agents/veldorapro-great-sage.md +33 -0
  29. package/.rimuru/agents/veldorapro-mcp-creator.md +27 -0
  30. package/.rimuru/agents/veldorapro-prompt-enhancer.md +25 -0
  31. package/.rimuru/agents/veldorapro-skill-creator.md +27 -0
  32. package/.rimuru/command/ai-deps.md +24 -0
  33. package/.rimuru/command/changelog.md +49 -0
  34. package/.rimuru/command/commit.md +37 -0
  35. package/.rimuru/command/issues.md +23 -0
  36. package/.rimuru/command/learn.md +42 -0
  37. package/.rimuru/command/rmslop.md +15 -0
  38. package/.rimuru/command/spellcheck.md +5 -0
  39. package/.rimuru/command/translate.md +14 -0
  40. package/.rimuru/glossary/README.md +63 -0
  41. package/.rimuru/glossary/ar.md +28 -0
  42. package/.rimuru/glossary/br.md +34 -0
  43. package/.rimuru/glossary/bs.md +33 -0
  44. package/.rimuru/glossary/da.md +27 -0
  45. package/.rimuru/glossary/de.md +27 -0
  46. package/.rimuru/glossary/es.md +27 -0
  47. package/.rimuru/glossary/fr.md +27 -0
  48. package/.rimuru/glossary/ja.md +33 -0
  49. package/.rimuru/glossary/ko.md +27 -0
  50. package/.rimuru/glossary/no.md +38 -0
  51. package/.rimuru/glossary/pl.md +27 -0
  52. package/.rimuru/glossary/ru.md +27 -0
  53. package/.rimuru/glossary/th.md +34 -0
  54. package/.rimuru/glossary/tr.md +38 -0
  55. package/.rimuru/glossary/zh-cn.md +42 -0
  56. package/.rimuru/glossary/zh-tw.md +42 -0
  57. package/.rimuru/improver/changelog.md +250 -0
  58. package/.rimuru/improver/knowledge.md +172 -0
  59. package/.rimuru/improver/plugins.md +21 -0
  60. package/.rimuru/improver/skills.md +60 -0
  61. package/.rimuru/improver/token-audit.md +21 -0
  62. package/.rimuru/opencode.jsonc +140 -0
  63. package/.rimuru/plugins/smoke-theme.json +223 -0
  64. package/.rimuru/plugins/tui-smoke.tsx +1019 -0
  65. package/.rimuru/skills/effect/SKILL.md +38 -0
  66. package/.rimuru/themes/mytheme.json +223 -0
  67. package/.rimuru/tool/github-pr-search.ts +64 -0
  68. package/.rimuru/tool/github-triage.ts +60 -0
  69. package/README.md +31 -0
  70. package/package.json +167 -0
  71. package/src/account/account.ts +463 -0
  72. package/src/account/repo.ts +173 -0
  73. package/src/account/schema.ts +99 -0
  74. package/src/account/url.ts +8 -0
  75. package/src/acp/agent.ts +95 -0
  76. package/src/acp/config-option.ts +203 -0
  77. package/src/acp/content.ts +250 -0
  78. package/src/acp/directory.ts +210 -0
  79. package/src/acp/error.ts +90 -0
  80. package/src/acp/event.ts +342 -0
  81. package/src/acp/permission.ts +124 -0
  82. package/src/acp/profile.ts +42 -0
  83. package/src/acp/service.ts +1048 -0
  84. package/src/acp/session.ts +231 -0
  85. package/src/acp/tool.ts +367 -0
  86. package/src/acp/usage.ts +232 -0
  87. package/src/agent/agent.ts +459 -0
  88. package/src/agent/generate.txt +75 -0
  89. package/src/agent/prompt/compaction.txt +9 -0
  90. package/src/agent/prompt/explore.txt +18 -0
  91. package/src/agent/prompt/summary.txt +11 -0
  92. package/src/agent/prompt/title.txt +44 -0
  93. package/src/agent/subagent-permissions.ts +27 -0
  94. package/src/audio.d.ts +14 -0
  95. package/src/auth/index.ts +99 -0
  96. package/src/background/job.ts +39 -0
  97. package/src/bus/global.ts +22 -0
  98. package/src/cli/bootstrap.ts +11 -0
  99. package/src/cli/cmd/account.ts +264 -0
  100. package/src/cli/cmd/acp.ts +73 -0
  101. package/src/cli/cmd/agent.ts +259 -0
  102. package/src/cli/cmd/attach.ts +97 -0
  103. package/src/cli/cmd/cmd.ts +7 -0
  104. package/src/cli/cmd/db.ts +62 -0
  105. package/src/cli/cmd/debug/agent.handler.ts +193 -0
  106. package/src/cli/cmd/debug/agent.ts +27 -0
  107. package/src/cli/cmd/debug/config.ts +14 -0
  108. package/src/cli/cmd/debug/file.ts +73 -0
  109. package/src/cli/cmd/debug/index.ts +87 -0
  110. package/src/cli/cmd/debug/lsp.ts +50 -0
  111. package/src/cli/cmd/debug/ripgrep.ts +79 -0
  112. package/src/cli/cmd/debug/scrap.ts +15 -0
  113. package/src/cli/cmd/debug/skill.ts +15 -0
  114. package/src/cli/cmd/debug/snapshot.ts +50 -0
  115. package/src/cli/cmd/debug/startup.ts +11 -0
  116. package/src/cli/cmd/debug/v2.ts +49 -0
  117. package/src/cli/cmd/export.ts +292 -0
  118. package/src/cli/cmd/generate.ts +54 -0
  119. package/src/cli/cmd/github.handler.ts +1593 -0
  120. package/src/cli/cmd/github.shared.ts +30 -0
  121. package/src/cli/cmd/github.ts +42 -0
  122. package/src/cli/cmd/import.ts +224 -0
  123. package/src/cli/cmd/mcp.ts +850 -0
  124. package/src/cli/cmd/models.ts +66 -0
  125. package/src/cli/cmd/plug.ts +230 -0
  126. package/src/cli/cmd/pr.ts +115 -0
  127. package/src/cli/cmd/prompt-display.ts +1 -0
  128. package/src/cli/cmd/providers.ts +534 -0
  129. package/src/cli/cmd/run/demo.ts +1274 -0
  130. package/src/cli/cmd/run/entry.body.ts +205 -0
  131. package/src/cli/cmd/run/footer.command.tsx +1064 -0
  132. package/src/cli/cmd/run/footer.menu.tsx +351 -0
  133. package/src/cli/cmd/run/footer.permission.tsx +472 -0
  134. package/src/cli/cmd/run/footer.prompt.tsx +1306 -0
  135. package/src/cli/cmd/run/footer.question.tsx +573 -0
  136. package/src/cli/cmd/run/footer.subagent.tsx +173 -0
  137. package/src/cli/cmd/run/footer.ts +1129 -0
  138. package/src/cli/cmd/run/footer.view.tsx +943 -0
  139. package/src/cli/cmd/run/footer.width.ts +27 -0
  140. package/src/cli/cmd/run/permission.shared.ts +256 -0
  141. package/src/cli/cmd/run/prompt.editor.ts +157 -0
  142. package/src/cli/cmd/run/prompt.shared.ts +153 -0
  143. package/src/cli/cmd/run/question.shared.ts +340 -0
  144. package/src/cli/cmd/run/runtime.boot.ts +202 -0
  145. package/src/cli/cmd/run/runtime.lifecycle.ts +406 -0
  146. package/src/cli/cmd/run/runtime.queue.ts +349 -0
  147. package/src/cli/cmd/run/runtime.shared.ts +17 -0
  148. package/src/cli/cmd/run/runtime.stdin.ts +37 -0
  149. package/src/cli/cmd/run/runtime.ts +814 -0
  150. package/src/cli/cmd/run/scrollback.shared.ts +92 -0
  151. package/src/cli/cmd/run/scrollback.surface.ts +431 -0
  152. package/src/cli/cmd/run/scrollback.writer.tsx +352 -0
  153. package/src/cli/cmd/run/session-data.ts +1113 -0
  154. package/src/cli/cmd/run/session-replay.ts +374 -0
  155. package/src/cli/cmd/run/session.shared.ts +196 -0
  156. package/src/cli/cmd/run/splash.ts +280 -0
  157. package/src/cli/cmd/run/stream.transport.ts +1462 -0
  158. package/src/cli/cmd/run/stream.ts +175 -0
  159. package/src/cli/cmd/run/subagent-data.ts +876 -0
  160. package/src/cli/cmd/run/theme.ts +690 -0
  161. package/src/cli/cmd/run/tool.ts +1489 -0
  162. package/src/cli/cmd/run/trace.ts +94 -0
  163. package/src/cli/cmd/run/turn-summary.ts +47 -0
  164. package/src/cli/cmd/run/types.ts +350 -0
  165. package/src/cli/cmd/run/variant.shared.ts +215 -0
  166. package/src/cli/cmd/run.ts +894 -0
  167. package/src/cli/cmd/serve.ts +24 -0
  168. package/src/cli/cmd/session.ts +147 -0
  169. package/src/cli/cmd/stats.ts +393 -0
  170. package/src/cli/cmd/tui.ts +224 -0
  171. package/src/cli/cmd/uninstall.ts +353 -0
  172. package/src/cli/cmd/upgrade.ts +74 -0
  173. package/src/cli/cmd/web.ts +84 -0
  174. package/src/cli/effect/prompt.ts +37 -0
  175. package/src/cli/effect-cmd.ts +96 -0
  176. package/src/cli/error.ts +130 -0
  177. package/src/cli/heap.ts +45 -0
  178. package/src/cli/logo.ts +1 -0
  179. package/src/cli/network.ts +64 -0
  180. package/src/cli/tui/layer.ts +7 -0
  181. package/src/cli/tui/validate-session.ts +29 -0
  182. package/src/cli/tui/worker.ts +71 -0
  183. package/src/cli/ui.ts +98 -0
  184. package/src/cli/upgrade.ts +53 -0
  185. package/src/command/index.ts +184 -0
  186. package/src/command/template/initialize.txt +66 -0
  187. package/src/command/template/review.txt +101 -0
  188. package/src/config/agent.ts +59 -0
  189. package/src/config/command.ts +39 -0
  190. package/src/config/config.ts +686 -0
  191. package/src/config/entry-name.ts +19 -0
  192. package/src/config/managed.ts +69 -0
  193. package/src/config/markdown.ts +36 -0
  194. package/src/config/parse.ts +79 -0
  195. package/src/config/paths.ts +45 -0
  196. package/src/config/plugin.ts +79 -0
  197. package/src/config/tui-cwd.ts +5 -0
  198. package/src/config/tui-host-attention.ts +21 -0
  199. package/src/config/tui-migrate.ts +132 -0
  200. package/src/config/tui.ts +274 -0
  201. package/src/config/variable.ts +91 -0
  202. package/src/control-plane/adapters/index.ts +41 -0
  203. package/src/control-plane/adapters/worktree.ts +96 -0
  204. package/src/control-plane/dev/README.md +19 -0
  205. package/src/control-plane/dev/debug-workspace-plugin.ts +73 -0
  206. package/src/control-plane/types.ts +59 -0
  207. package/src/control-plane/util.ts +39 -0
  208. package/src/control-plane/workspace-adapter-runtime.ts +51 -0
  209. package/src/control-plane/workspace-context.ts +26 -0
  210. package/src/control-plane/workspace.ts +989 -0
  211. package/src/effect/app-runtime.ts +132 -0
  212. package/src/effect/bootstrap-runtime.ts +23 -0
  213. package/src/effect/bridge.ts +84 -0
  214. package/src/effect/config-service.ts +67 -0
  215. package/src/effect/instance-ref.ts +11 -0
  216. package/src/effect/instance-registry.ts +12 -0
  217. package/src/effect/instance-state.ts +69 -0
  218. package/src/effect/promise.ts +17 -0
  219. package/src/effect/run-service.ts +47 -0
  220. package/src/effect/runner.ts +217 -0
  221. package/src/effect/runtime-flags.ts +79 -0
  222. package/src/env/index.ts +43 -0
  223. package/src/event-v2-bridge.ts +79 -0
  224. package/src/format/formatter.ts +404 -0
  225. package/src/format/index.ts +205 -0
  226. package/src/git/index.ts +350 -0
  227. package/src/id/id.ts +80 -0
  228. package/src/ide/index.ts +61 -0
  229. package/src/image/image.ts +174 -0
  230. package/src/index.ts +142 -0
  231. package/src/installation/index.ts +350 -0
  232. package/src/lsp/client.ts +650 -0
  233. package/src/lsp/diagnostic.ts +29 -0
  234. package/src/lsp/language.ts +121 -0
  235. package/src/lsp/launch.ts +21 -0
  236. package/src/lsp/lsp.ts +511 -0
  237. package/src/lsp/server.ts +1983 -0
  238. package/src/markdown.d.ts +4 -0
  239. package/src/mcp/auth.ts +174 -0
  240. package/src/mcp/catalog.ts +153 -0
  241. package/src/mcp/index.ts +946 -0
  242. package/src/mcp/oauth-callback.ts +233 -0
  243. package/src/mcp/oauth-provider.ts +206 -0
  244. package/src/node.ts +4 -0
  245. package/src/patch/index.ts +686 -0
  246. package/src/permission/arity.ts +163 -0
  247. package/src/permission/evaluate.ts +1 -0
  248. package/src/permission/index.ts +230 -0
  249. package/src/plugin/azure.ts +26 -0
  250. package/src/plugin/cloudflare.ts +76 -0
  251. package/src/plugin/digitalocean.ts +383 -0
  252. package/src/plugin/github-copilot/copilot.ts +413 -0
  253. package/src/plugin/github-copilot/models.ts +246 -0
  254. package/src/plugin/index.ts +316 -0
  255. package/src/plugin/install.ts +439 -0
  256. package/src/plugin/loader.ts +237 -0
  257. package/src/plugin/meta.ts +188 -0
  258. package/src/plugin/openai/README.md +31 -0
  259. package/src/plugin/openai/codex.ts +641 -0
  260. package/src/plugin/openai/ws-pool.ts +270 -0
  261. package/src/plugin/openai/ws.ts +381 -0
  262. package/src/plugin/pty-environment.ts +24 -0
  263. package/src/plugin/shared.ts +323 -0
  264. package/src/plugin/snowflake-cortex.ts +529 -0
  265. package/src/plugin/tui/internal.ts +10 -0
  266. package/src/plugin/tui/runtime.ts +1130 -0
  267. package/src/plugin/xai.ts +716 -0
  268. package/src/project/bootstrap-service.ts +9 -0
  269. package/src/project/bootstrap.ts +76 -0
  270. package/src/project/instance-context.ts +24 -0
  271. package/src/project/instance-layer.ts +11 -0
  272. package/src/project/instance-runtime.ts +16 -0
  273. package/src/project/instance-store.ts +209 -0
  274. package/src/project/project.ts +519 -0
  275. package/src/project/vcs.ts +431 -0
  276. package/src/provider/auth.ts +233 -0
  277. package/src/provider/error.ts +188 -0
  278. package/src/provider/model-status.ts +8 -0
  279. package/src/provider/provider.ts +1979 -0
  280. package/src/provider/transform.ts +1426 -0
  281. package/src/question/index.ts +229 -0
  282. package/src/question/schema.ts +10 -0
  283. package/src/server/auth.ts +48 -0
  284. package/src/server/event.ts +13 -0
  285. package/src/server/global-lifecycle.ts +28 -0
  286. package/src/server/init-projectors.ts +3 -0
  287. package/src/server/mdns.ts +47 -0
  288. package/src/server/projectors.ts +1 -0
  289. package/src/server/proxy-util.ts +48 -0
  290. package/src/server/routes/instance/httpapi/AGENTS.md +39 -0
  291. package/src/server/routes/instance/httpapi/api.ts +78 -0
  292. package/src/server/routes/instance/httpapi/errors.ts +193 -0
  293. package/src/server/routes/instance/httpapi/groups/config.ts +65 -0
  294. package/src/server/routes/instance/httpapi/groups/control-plane.ts +35 -0
  295. package/src/server/routes/instance/httpapi/groups/control.ts +76 -0
  296. package/src/server/routes/instance/httpapi/groups/event.ts +29 -0
  297. package/src/server/routes/instance/httpapi/groups/experimental.ts +260 -0
  298. package/src/server/routes/instance/httpapi/groups/file.ts +185 -0
  299. package/src/server/routes/instance/httpapi/groups/global.ts +138 -0
  300. package/src/server/routes/instance/httpapi/groups/instance.ts +206 -0
  301. package/src/server/routes/instance/httpapi/groups/mcp.ts +156 -0
  302. package/src/server/routes/instance/httpapi/groups/metadata.ts +18 -0
  303. package/src/server/routes/instance/httpapi/groups/permission.ts +61 -0
  304. package/src/server/routes/instance/httpapi/groups/project-copy.ts +32 -0
  305. package/src/server/routes/instance/httpapi/groups/project.ts +93 -0
  306. package/src/server/routes/instance/httpapi/groups/provider.ts +101 -0
  307. package/src/server/routes/instance/httpapi/groups/pty.ts +172 -0
  308. package/src/server/routes/instance/httpapi/groups/query.ts +12 -0
  309. package/src/server/routes/instance/httpapi/groups/question.ts +74 -0
  310. package/src/server/routes/instance/httpapi/groups/session.ts +462 -0
  311. package/src/server/routes/instance/httpapi/groups/sync.ts +113 -0
  312. package/src/server/routes/instance/httpapi/groups/tui.ts +208 -0
  313. package/src/server/routes/instance/httpapi/groups/workspace.ts +141 -0
  314. package/src/server/routes/instance/httpapi/handlers/config.ts +34 -0
  315. package/src/server/routes/instance/httpapi/handlers/control-plane.ts +37 -0
  316. package/src/server/routes/instance/httpapi/handlers/control.ts +43 -0
  317. package/src/server/routes/instance/httpapi/handlers/event.ts +99 -0
  318. package/src/server/routes/instance/httpapi/handlers/experimental.ts +187 -0
  319. package/src/server/routes/instance/httpapi/handlers/file.ts +139 -0
  320. package/src/server/routes/instance/httpapi/handlers/global.ts +156 -0
  321. package/src/server/routes/instance/httpapi/handlers/instance.ts +110 -0
  322. package/src/server/routes/instance/httpapi/handlers/mcp.ts +111 -0
  323. package/src/server/routes/instance/httpapi/handlers/permission.ts +41 -0
  324. package/src/server/routes/instance/httpapi/handlers/project-copy.ts +83 -0
  325. package/src/server/routes/instance/httpapi/handlers/project.ts +63 -0
  326. package/src/server/routes/instance/httpapi/handlers/provider.ts +113 -0
  327. package/src/server/routes/instance/httpapi/handlers/pty.ts +273 -0
  328. package/src/server/routes/instance/httpapi/handlers/question.ts +54 -0
  329. package/src/server/routes/instance/httpapi/handlers/session-errors.ts +21 -0
  330. package/src/server/routes/instance/httpapi/handlers/session.ts +440 -0
  331. package/src/server/routes/instance/httpapi/handlers/sync.ts +89 -0
  332. package/src/server/routes/instance/httpapi/handlers/tui.ts +131 -0
  333. package/src/server/routes/instance/httpapi/handlers/workspace.ts +102 -0
  334. package/src/server/routes/instance/httpapi/lifecycle.ts +54 -0
  335. package/src/server/routes/instance/httpapi/middleware/authorization.ts +150 -0
  336. package/src/server/routes/instance/httpapi/middleware/compression.ts +64 -0
  337. package/src/server/routes/instance/httpapi/middleware/cors-vary.ts +29 -0
  338. package/src/server/routes/instance/httpapi/middleware/error.ts +43 -0
  339. package/src/server/routes/instance/httpapi/middleware/fence.ts +25 -0
  340. package/src/server/routes/instance/httpapi/middleware/instance-context.ts +43 -0
  341. package/src/server/routes/instance/httpapi/middleware/proxy.ts +108 -0
  342. package/src/server/routes/instance/httpapi/middleware/schema-error.ts +41 -0
  343. package/src/server/routes/instance/httpapi/middleware/workspace-routing.ts +250 -0
  344. package/src/server/routes/instance/httpapi/public.ts +535 -0
  345. package/src/server/routes/instance/httpapi/server.ts +298 -0
  346. package/src/server/routes/instance/httpapi/websocket-tracker.ts +57 -0
  347. package/src/server/server.ts +225 -0
  348. package/src/server/shared/fence.ts +60 -0
  349. package/src/server/shared/pty-ticket.ts +15 -0
  350. package/src/server/shared/public-ui.ts +12 -0
  351. package/src/server/shared/tui-control.ts +28 -0
  352. package/src/server/shared/ui.ts +122 -0
  353. package/src/server/shared/workspace-routing.ts +38 -0
  354. package/src/server/tui-event.ts +53 -0
  355. package/src/session/compaction.ts +620 -0
  356. package/src/session/instruction.ts +241 -0
  357. package/src/session/llm/AGENTS.md +90 -0
  358. package/src/session/llm/ai-sdk.ts +288 -0
  359. package/src/session/llm/native-request.ts +196 -0
  360. package/src/session/llm/native-runtime.ts +196 -0
  361. package/src/session/llm/request.ts +218 -0
  362. package/src/session/llm.ts +415 -0
  363. package/src/session/message-error.ts +14 -0
  364. package/src/session/message-v2.ts +744 -0
  365. package/src/session/message.ts +148 -0
  366. package/src/session/overflow.ts +34 -0
  367. package/src/session/processor.ts +1084 -0
  368. package/src/session/prompt/anthropic.txt +105 -0
  369. package/src/session/prompt/beast.txt +147 -0
  370. package/src/session/prompt/build-switch.txt +5 -0
  371. package/src/session/prompt/codex.txt +79 -0
  372. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  373. package/src/session/prompt/default.txt +95 -0
  374. package/src/session/prompt/gemini.txt +155 -0
  375. package/src/session/prompt/gpt.txt +107 -0
  376. package/src/session/prompt/kimi.txt +95 -0
  377. package/src/session/prompt/max-steps.txt +16 -0
  378. package/src/session/prompt/plan-mode.txt +70 -0
  379. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  380. package/src/session/prompt/plan.txt +26 -0
  381. package/src/session/prompt/trinity.txt +97 -0
  382. package/src/session/prompt.ts +1722 -0
  383. package/src/session/reminders.ts +92 -0
  384. package/src/session/retry.ts +201 -0
  385. package/src/session/revert.ts +160 -0
  386. package/src/session/run-state.ts +156 -0
  387. package/src/session/schema.ts +26 -0
  388. package/src/session/session.ts +1119 -0
  389. package/src/session/status.ts +97 -0
  390. package/src/session/summary.ts +165 -0
  391. package/src/session/system.ts +117 -0
  392. package/src/session/todo.ts +90 -0
  393. package/src/session/tools.ts +207 -0
  394. package/src/share/session.ts +61 -0
  395. package/src/share/share-next.ts +385 -0
  396. package/src/skill/discovery.ts +109 -0
  397. package/src/skill/index.ts +366 -0
  398. package/src/snapshot/index.ts +808 -0
  399. package/src/sql.d.ts +4 -0
  400. package/src/storage/schema.ts +5 -0
  401. package/src/storage/storage.ts +329 -0
  402. package/src/sync/README.md +179 -0
  403. package/src/sync/schema.ts +11 -0
  404. package/src/temporary.ts +31 -0
  405. package/src/tool/apply_patch.ts +313 -0
  406. package/src/tool/apply_patch.txt +33 -0
  407. package/src/tool/edit.ts +737 -0
  408. package/src/tool/edit.txt +10 -0
  409. package/src/tool/external-directory.ts +49 -0
  410. package/src/tool/glob.ts +76 -0
  411. package/src/tool/glob.txt +6 -0
  412. package/src/tool/grep.ts +112 -0
  413. package/src/tool/grep.txt +8 -0
  414. package/src/tool/invalid.ts +21 -0
  415. package/src/tool/json-schema.ts +164 -0
  416. package/src/tool/lsp.ts +113 -0
  417. package/src/tool/lsp.txt +24 -0
  418. package/src/tool/mcp-websearch.ts +96 -0
  419. package/src/tool/plan-enter.txt +14 -0
  420. package/src/tool/plan-exit.txt +13 -0
  421. package/src/tool/plan.ts +79 -0
  422. package/src/tool/question.ts +44 -0
  423. package/src/tool/question.txt +10 -0
  424. package/src/tool/read.ts +386 -0
  425. package/src/tool/read.txt +14 -0
  426. package/src/tool/registry.ts +440 -0
  427. package/src/tool/schema.ts +14 -0
  428. package/src/tool/shell/id.ts +19 -0
  429. package/src/tool/shell/prompt.ts +307 -0
  430. package/src/tool/shell/shell.txt +21 -0
  431. package/src/tool/shell.ts +657 -0
  432. package/src/tool/skill.ts +71 -0
  433. package/src/tool/skill.txt +5 -0
  434. package/src/tool/task.ts +346 -0
  435. package/src/tool/task.txt +19 -0
  436. package/src/tool/todo.ts +57 -0
  437. package/src/tool/todowrite.txt +44 -0
  438. package/src/tool/tool.ts +183 -0
  439. package/src/tool/truncate.ts +158 -0
  440. package/src/tool/truncation-dir.ts +4 -0
  441. package/src/tool/webfetch.ts +192 -0
  442. package/src/tool/webfetch.txt +13 -0
  443. package/src/tool/websearch.ts +143 -0
  444. package/src/tool/websearch.txt +14 -0
  445. package/src/tool/write.ts +104 -0
  446. package/src/tool/write.txt +8 -0
  447. package/src/util/archive.ts +17 -0
  448. package/src/util/bom.ts +27 -0
  449. package/src/util/data-url.ts +9 -0
  450. package/src/util/defer.ts +10 -0
  451. package/src/util/effect-http-client.ts +11 -0
  452. package/src/util/error.ts +1 -0
  453. package/src/util/filesystem.ts +251 -0
  454. package/src/util/html.ts +8 -0
  455. package/src/util/iife.ts +3 -0
  456. package/src/util/lazy.ts +20 -0
  457. package/src/util/local-context.ts +25 -0
  458. package/src/util/locale.ts +2 -0
  459. package/src/util/media.ts +26 -0
  460. package/src/util/process.ts +177 -0
  461. package/src/util/proxy-env.ts +72 -0
  462. package/src/util/queue.ts +32 -0
  463. package/src/util/record.ts +1 -0
  464. package/src/util/repository.ts +232 -0
  465. package/src/util/rpc.ts +66 -0
  466. package/src/util/signal.ts +12 -0
  467. package/src/util/timeout.ts +13 -0
  468. package/src/util/token.ts +1 -0
  469. package/src/util/wildcard.ts +59 -0
  470. package/src/worktree/index.ts +654 -0
@@ -0,0 +1,1019 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import { useTerminalDimensions, type JSX } from "@opentui/solid"
3
+ import { useBindings, useKeymapSelector } from "@opentui/keymap/solid"
4
+ import { RGBA, VignetteEffect, type KeyEvent, type Renderable } from "@opentui/core"
5
+ import { createBindingLookup, type BindingConfig } from "@opentui/keymap/extras"
6
+ import type { TuiPlugin, TuiPluginApi, TuiPluginMeta, TuiPluginModule, TuiSlotPlugin } from "@rimurucode-ai/plugin/tui"
7
+
8
+ const tabs = ["overview", "counter", "help"]
9
+ const command = {
10
+ modal: "smoke_modal",
11
+ screen: "smoke_screen",
12
+ alert: "smoke_alert",
13
+ confirm: "smoke_confirm",
14
+ prompt: "smoke_prompt",
15
+ select: "smoke_select",
16
+ host: "smoke_host",
17
+ home: "smoke_home",
18
+ toast: "smoke_toast",
19
+ dialog_close: "smoke_dialog_close",
20
+ local_push: "smoke_local_push",
21
+ local_pop: "smoke_local_pop",
22
+ screen_home: "smoke_screen_home",
23
+ screen_left: "smoke_screen_left",
24
+ screen_right: "smoke_screen_right",
25
+ screen_up: "smoke_screen_up",
26
+ screen_down: "smoke_screen_down",
27
+ screen_modal: "smoke_screen_modal",
28
+ screen_local: "smoke_screen_local",
29
+ screen_host: "smoke_screen_host",
30
+ screen_alert: "smoke_screen_alert",
31
+ screen_confirm: "smoke_screen_confirm",
32
+ screen_prompt: "smoke_screen_prompt",
33
+ screen_select: "smoke_screen_select",
34
+ modal_accept: "smoke_modal_accept",
35
+ modal_close: "smoke_modal_close",
36
+ }
37
+
38
+ type SmokeBindings = BindingConfig<Renderable, KeyEvent>
39
+
40
+ const defaultKeymap = {
41
+ [command.modal]: "ctrl+shift+m",
42
+ [command.screen]: "ctrl+shift+o",
43
+ [command.dialog_close]: "escape",
44
+ [command.local_push]: "enter,return",
45
+ [command.local_pop]: "escape,q,backspace",
46
+ [command.screen_home]: "escape,ctrl+h",
47
+ [command.screen_left]: "left,h",
48
+ [command.screen_right]: "right,l",
49
+ [command.screen_up]: "up,k",
50
+ [command.screen_down]: "down,j",
51
+ [command.screen_modal]: "ctrl+shift+m",
52
+ [command.screen_local]: "x",
53
+ [command.screen_host]: "z",
54
+ [command.screen_alert]: "a",
55
+ [command.screen_confirm]: "c",
56
+ [command.screen_prompt]: "p",
57
+ [command.screen_select]: "s",
58
+ [command.modal_accept]: "enter,return",
59
+ [command.modal_close]: "escape",
60
+ }
61
+
62
+ const pick = (value: unknown, fallback: string) => {
63
+ if (typeof value !== "string") return fallback
64
+ if (!value.trim()) return fallback
65
+ return value
66
+ }
67
+
68
+ const num = (value: unknown, fallback: number) => {
69
+ if (typeof value !== "number") return fallback
70
+ return value
71
+ }
72
+
73
+ const record = (value: unknown): value is Record<string, unknown> =>
74
+ !!value && typeof value === "object" && !Array.isArray(value)
75
+
76
+ type Cfg = {
77
+ label: string
78
+ route: string
79
+ vignette: number
80
+ keybinds: SmokeBindings | undefined
81
+ }
82
+
83
+ type Route = {
84
+ modal: string
85
+ screen: string
86
+ }
87
+
88
+ type State = {
89
+ tab: number
90
+ count: number
91
+ source: string
92
+ note: string
93
+ selected: string
94
+ local: number
95
+ }
96
+
97
+ const cfg = (options: Record<string, unknown> | undefined) => {
98
+ return {
99
+ label: pick(options?.label, "smoke"),
100
+ route: pick(options?.route, "workspace-smoke"),
101
+ vignette: Math.max(0, num(options?.vignette, 0.35)),
102
+ keybinds: record(options?.keybinds) ? (options.keybinds as SmokeBindings) : undefined,
103
+ }
104
+ }
105
+
106
+ const names = (input: Cfg) => {
107
+ return {
108
+ modal: `${input.route}.modal`,
109
+ screen: `${input.route}.screen`,
110
+ }
111
+ }
112
+
113
+ function createKeys(input: SmokeBindings | undefined) {
114
+ return createBindingLookup({ ...defaultKeymap, ...input })
115
+ }
116
+
117
+ type Keys = ReturnType<typeof createKeys>
118
+
119
+ const ui = {
120
+ panel: "#1d1d1d",
121
+ border: "#4a4a4a",
122
+ text: "#f0f0f0",
123
+ muted: "#a5a5a5",
124
+ accent: "#5f87ff",
125
+ }
126
+
127
+ type Color = RGBA | string
128
+
129
+ const ink = (map: Record<string, unknown>, name: string, fallback: string): Color => {
130
+ const value = map[name]
131
+ if (typeof value === "string") return value
132
+ if (value instanceof RGBA) return value
133
+ return fallback
134
+ }
135
+
136
+ const look = (map: Record<string, unknown>) => {
137
+ return {
138
+ panel: ink(map, "backgroundPanel", ui.panel),
139
+ border: ink(map, "border", ui.border),
140
+ text: ink(map, "text", ui.text),
141
+ muted: ink(map, "textMuted", ui.muted),
142
+ accent: ink(map, "primary", ui.accent),
143
+ selected: ink(map, "selectedListItemText", ui.text),
144
+ }
145
+ }
146
+
147
+ const tone = (api: TuiPluginApi) => {
148
+ return look(api.theme.current)
149
+ }
150
+
151
+ type Skin = {
152
+ panel: Color
153
+ border: Color
154
+ text: Color
155
+ muted: Color
156
+ accent: Color
157
+ selected: Color
158
+ }
159
+
160
+ const Btn = (props: { txt: string; run: () => void; skin: Skin; on?: boolean }) => {
161
+ return (
162
+ <box
163
+ onMouseUp={() => {
164
+ props.run()
165
+ }}
166
+ backgroundColor={props.on ? props.skin.accent : props.skin.border}
167
+ paddingLeft={1}
168
+ paddingRight={1}
169
+ >
170
+ <text fg={props.on ? props.skin.selected : props.skin.text}>{props.txt}</text>
171
+ </box>
172
+ )
173
+ }
174
+
175
+ const parse = (params: Record<string, unknown> | undefined) => {
176
+ const tab = typeof params?.tab === "number" ? params.tab : 0
177
+ const count = typeof params?.count === "number" ? params.count : 0
178
+ const source = typeof params?.source === "string" ? params.source : "unknown"
179
+ const note = typeof params?.note === "string" ? params.note : ""
180
+ const selected = typeof params?.selected === "string" ? params.selected : ""
181
+ const local = typeof params?.local === "number" ? params.local : 0
182
+ return {
183
+ tab: Math.max(0, Math.min(tab, tabs.length - 1)),
184
+ count,
185
+ source,
186
+ note,
187
+ selected,
188
+ local: Math.max(0, local),
189
+ }
190
+ }
191
+
192
+ const current = (api: TuiPluginApi, route: Route) => {
193
+ const value = api.route.current
194
+ const ok = Object.values(route).includes(value.name)
195
+ if (!ok) return parse(undefined)
196
+ if (!("params" in value)) return parse(undefined)
197
+ return parse(value.params)
198
+ }
199
+
200
+ const opts = [
201
+ {
202
+ title: "Overview",
203
+ value: 0,
204
+ description: "Switch to overview tab",
205
+ },
206
+ {
207
+ title: "Counter",
208
+ value: 1,
209
+ description: "Switch to counter tab",
210
+ },
211
+ {
212
+ title: "Help",
213
+ value: 2,
214
+ description: "Switch to help tab",
215
+ },
216
+ ]
217
+
218
+ const host = (api: TuiPluginApi, input: Cfg, skin: Skin) => {
219
+ api.ui.dialog.setSize("medium")
220
+ api.ui.dialog.replace(() => (
221
+ <box paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1} flexDirection="column">
222
+ <text fg={skin.text}>
223
+ <b>{input.label} host overlay</b>
224
+ </text>
225
+ <text fg={skin.muted}>Using api.ui.dialog stack with built-in backdrop</text>
226
+ <text fg={skin.muted}>esc closes · depth {api.ui.dialog.depth}</text>
227
+ <box flexDirection="row" gap={1}>
228
+ <Btn txt="close" run={() => api.ui.dialog.clear()} skin={skin} on />
229
+ </box>
230
+ </box>
231
+ ))
232
+ }
233
+
234
+ const warn = (api: TuiPluginApi, route: Route, value: State) => {
235
+ const DialogAlert = api.ui.DialogAlert
236
+ api.ui.dialog.setSize("medium")
237
+ api.ui.dialog.replace(() => (
238
+ <DialogAlert
239
+ title="Smoke alert"
240
+ message="Testing built-in alert dialog"
241
+ onConfirm={() => api.route.navigate(route.screen, { ...value, source: "alert" })}
242
+ />
243
+ ))
244
+ }
245
+
246
+ const check = (api: TuiPluginApi, route: Route, value: State) => {
247
+ const DialogConfirm = api.ui.DialogConfirm
248
+ api.ui.dialog.setSize("medium")
249
+ api.ui.dialog.replace(() => (
250
+ <DialogConfirm
251
+ title="Smoke confirm"
252
+ message="Apply +1 to counter?"
253
+ onConfirm={() => api.route.navigate(route.screen, { ...value, count: value.count + 1, source: "confirm" })}
254
+ onCancel={() => api.route.navigate(route.screen, { ...value, source: "confirm-cancel" })}
255
+ />
256
+ ))
257
+ }
258
+
259
+ const entry = (api: TuiPluginApi, route: Route, value: State) => {
260
+ const DialogPrompt = api.ui.DialogPrompt
261
+ api.ui.dialog.setSize("medium")
262
+ api.ui.dialog.replace(() => (
263
+ <DialogPrompt
264
+ title="Smoke prompt"
265
+ value={value.note}
266
+ onConfirm={(note) => {
267
+ api.ui.dialog.clear()
268
+ api.route.navigate(route.screen, { ...value, note, source: "prompt" })
269
+ }}
270
+ onCancel={() => {
271
+ api.ui.dialog.clear()
272
+ api.route.navigate(route.screen, value)
273
+ }}
274
+ />
275
+ ))
276
+ }
277
+
278
+ const picker = (api: TuiPluginApi, route: Route, value: State) => {
279
+ const DialogSelect = api.ui.DialogSelect
280
+ api.ui.dialog.setSize("medium")
281
+ api.ui.dialog.replace(() => (
282
+ <DialogSelect
283
+ title="Smoke select"
284
+ options={opts}
285
+ current={value.tab}
286
+ onSelect={(item) => {
287
+ api.ui.dialog.clear()
288
+ api.route.navigate(route.screen, {
289
+ ...value,
290
+ tab: typeof item.value === "number" ? item.value : value.tab,
291
+ selected: item.title,
292
+ source: "select",
293
+ })
294
+ }}
295
+ />
296
+ ))
297
+ }
298
+
299
+ const Screen = (props: {
300
+ api: TuiPluginApi
301
+ input: Cfg
302
+ route: Route
303
+ keys: Keys
304
+ meta: TuiPluginMeta
305
+ params?: Record<string, unknown>
306
+ }) => {
307
+ const dim = useTerminalDimensions()
308
+ const value = parse(props.params)
309
+ const skin = tone(props.api)
310
+ const set = (local: number, base?: State) => {
311
+ const next = base ?? current(props.api, props.route)
312
+ props.api.route.navigate(props.route.screen, { ...next, local: Math.max(0, local), source: "local" })
313
+ }
314
+ const push = (base?: State) => {
315
+ const next = base ?? current(props.api, props.route)
316
+ set(next.local + 1, next)
317
+ }
318
+ const open = () => {
319
+ const next = current(props.api, props.route)
320
+ if (next.local > 0) return
321
+ set(1, next)
322
+ }
323
+ const pop = (base?: State) => {
324
+ const next = base ?? current(props.api, props.route)
325
+ set(Math.max(0, next.local - 1), next)
326
+ }
327
+ const show = () => {
328
+ setTimeout(() => {
329
+ open()
330
+ }, 0)
331
+ }
332
+ const screenActive = () => props.api.route.current.name === props.route.screen
333
+
334
+ useBindings(() => ({
335
+ enabled: () => screenActive() && props.api.ui.dialog.open,
336
+ commands: [
337
+ {
338
+ name: command.dialog_close,
339
+ run() {
340
+ props.api.ui.dialog.clear()
341
+ },
342
+ },
343
+ ],
344
+ bindings: props.keys.gather("smoke.dialog", [command.dialog_close]),
345
+ }))
346
+
347
+ useBindings(() => ({
348
+ enabled: () => screenActive() && !props.api.ui.dialog.open && current(props.api, props.route).local > 0,
349
+ commands: [
350
+ {
351
+ name: command.local_push,
352
+ run() {
353
+ push(current(props.api, props.route))
354
+ },
355
+ },
356
+ {
357
+ name: command.local_pop,
358
+ run() {
359
+ pop(current(props.api, props.route))
360
+ },
361
+ },
362
+ ],
363
+ bindings: props.keys.gather("smoke.local", [command.local_push, command.local_pop]),
364
+ }))
365
+
366
+ useBindings(() => ({
367
+ enabled: () => screenActive() && !props.api.ui.dialog.open && current(props.api, props.route).local === 0,
368
+ commands: [
369
+ {
370
+ name: command.screen_home,
371
+ run() {
372
+ props.api.route.navigate("home")
373
+ },
374
+ },
375
+ {
376
+ name: command.screen_left,
377
+ run() {
378
+ const next = current(props.api, props.route)
379
+ props.api.route.navigate(props.route.screen, { ...next, tab: (next.tab - 1 + tabs.length) % tabs.length })
380
+ },
381
+ },
382
+ {
383
+ name: command.screen_right,
384
+ run() {
385
+ const next = current(props.api, props.route)
386
+ props.api.route.navigate(props.route.screen, { ...next, tab: (next.tab + 1) % tabs.length })
387
+ },
388
+ },
389
+ {
390
+ name: command.screen_up,
391
+ run() {
392
+ const next = current(props.api, props.route)
393
+ props.api.route.navigate(props.route.screen, { ...next, count: next.count + 1 })
394
+ },
395
+ },
396
+ {
397
+ name: command.screen_down,
398
+ run() {
399
+ const next = current(props.api, props.route)
400
+ props.api.route.navigate(props.route.screen, { ...next, count: next.count - 1 })
401
+ },
402
+ },
403
+ {
404
+ name: command.screen_modal,
405
+ run() {
406
+ props.api.route.navigate(props.route.modal, current(props.api, props.route))
407
+ },
408
+ },
409
+ {
410
+ name: command.screen_local,
411
+ run() {
412
+ open()
413
+ },
414
+ },
415
+ {
416
+ name: command.screen_host,
417
+ run() {
418
+ host(props.api, props.input, skin)
419
+ },
420
+ },
421
+ {
422
+ name: command.screen_alert,
423
+ run() {
424
+ warn(props.api, props.route, current(props.api, props.route))
425
+ },
426
+ },
427
+ {
428
+ name: command.screen_confirm,
429
+ run() {
430
+ check(props.api, props.route, current(props.api, props.route))
431
+ },
432
+ },
433
+ {
434
+ name: command.screen_prompt,
435
+ run() {
436
+ entry(props.api, props.route, current(props.api, props.route))
437
+ },
438
+ },
439
+ {
440
+ name: command.screen_select,
441
+ run() {
442
+ picker(props.api, props.route, current(props.api, props.route))
443
+ },
444
+ },
445
+ ],
446
+ bindings: props.keys.gather("smoke.screen", [
447
+ command.screen_home,
448
+ command.screen_left,
449
+ command.screen_right,
450
+ command.screen_up,
451
+ command.screen_down,
452
+ command.screen_modal,
453
+ command.screen_local,
454
+ command.screen_host,
455
+ command.screen_alert,
456
+ command.screen_confirm,
457
+ command.screen_prompt,
458
+ command.screen_select,
459
+ ]),
460
+ }))
461
+ const shortcuts = useKeymapSelector((keymap) => {
462
+ const bindings = keymap.getCommandBindings({
463
+ visibility: "registered",
464
+ commands: [
465
+ command.screen_home,
466
+ command.screen_up,
467
+ command.screen_down,
468
+ command.screen_modal,
469
+ command.screen_alert,
470
+ command.screen_confirm,
471
+ command.screen_prompt,
472
+ command.screen_select,
473
+ command.screen_local,
474
+ command.screen_host,
475
+ command.local_push,
476
+ command.local_pop,
477
+ ],
478
+ })
479
+
480
+ return {
481
+ screen_home: props.api.keys.formatBindings(bindings.get(command.screen_home)) ?? "",
482
+ screen_up: props.api.keys.formatBindings(bindings.get(command.screen_up)) ?? "",
483
+ screen_down: props.api.keys.formatBindings(bindings.get(command.screen_down)) ?? "",
484
+ screen_modal: props.api.keys.formatBindings(bindings.get(command.screen_modal)) ?? "",
485
+ screen_alert: props.api.keys.formatBindings(bindings.get(command.screen_alert)) ?? "",
486
+ screen_confirm: props.api.keys.formatBindings(bindings.get(command.screen_confirm)) ?? "",
487
+ screen_prompt: props.api.keys.formatBindings(bindings.get(command.screen_prompt)) ?? "",
488
+ screen_select: props.api.keys.formatBindings(bindings.get(command.screen_select)) ?? "",
489
+ screen_local: props.api.keys.formatBindings(bindings.get(command.screen_local)) ?? "",
490
+ screen_host: props.api.keys.formatBindings(bindings.get(command.screen_host)) ?? "",
491
+ local_push: props.api.keys.formatBindings(bindings.get(command.local_push)) ?? "",
492
+ local_pop: props.api.keys.formatBindings(bindings.get(command.local_pop)) ?? "",
493
+ }
494
+ })
495
+
496
+ return (
497
+ <box width={dim().width} height={dim().height} backgroundColor={skin.panel} position="relative">
498
+ <box
499
+ flexDirection="column"
500
+ width="100%"
501
+ height="100%"
502
+ paddingTop={1}
503
+ paddingBottom={1}
504
+ paddingLeft={2}
505
+ paddingRight={2}
506
+ >
507
+ <box flexDirection="row" justifyContent="space-between" paddingBottom={1}>
508
+ <text fg={skin.text}>
509
+ <b>{props.input.label} screen</b>
510
+ <span style={{ fg: skin.muted }}> plugin route</span>
511
+ </text>
512
+ <text fg={skin.muted}>{shortcuts().screen_home} home</text>
513
+ </box>
514
+
515
+ <box flexDirection="row" gap={1} paddingBottom={1}>
516
+ {tabs.map((item, i) => {
517
+ const on = value.tab === i
518
+ return (
519
+ <Btn
520
+ txt={item}
521
+ run={() => props.api.route.navigate(props.route.screen, { ...value, tab: i })}
522
+ skin={skin}
523
+ on={on}
524
+ />
525
+ )
526
+ })}
527
+ </box>
528
+
529
+ <box
530
+ border
531
+ borderColor={skin.border}
532
+ paddingTop={1}
533
+ paddingBottom={1}
534
+ paddingLeft={2}
535
+ paddingRight={2}
536
+ flexGrow={1}
537
+ >
538
+ {value.tab === 0 ? (
539
+ <box flexDirection="column" gap={1}>
540
+ <text fg={skin.text}>Route: {props.route.screen}</text>
541
+ <text fg={skin.muted}>plugin state: {props.meta.state}</text>
542
+ <text fg={skin.muted}>
543
+ first: {props.meta.state === "first" ? "yes" : "no"} · updated:{" "}
544
+ {props.meta.state === "updated" ? "yes" : "no"} · loads: {props.meta.load_count}
545
+ </text>
546
+ <text fg={skin.muted}>plugin source: {props.meta.source}</text>
547
+ <text fg={skin.muted}>source: {value.source}</text>
548
+ <text fg={skin.muted}>note: {value.note || "(none)"}</text>
549
+ <text fg={skin.muted}>selected: {value.selected || "(none)"}</text>
550
+ <text fg={skin.muted}>local stack depth: {value.local}</text>
551
+ <text fg={skin.muted}>host stack open: {props.api.ui.dialog.open ? "yes" : "no"}</text>
552
+ </box>
553
+ ) : null}
554
+
555
+ {value.tab === 1 ? (
556
+ <box flexDirection="column" gap={1}>
557
+ <text fg={skin.text}>Counter: {value.count}</text>
558
+ <text fg={skin.muted}>
559
+ {shortcuts().screen_up} / {shortcuts().screen_down} change value
560
+ </text>
561
+ </box>
562
+ ) : null}
563
+
564
+ {value.tab === 2 ? (
565
+ <box flexDirection="column" gap={1}>
566
+ <text fg={skin.muted}>
567
+ {shortcuts().screen_modal} modal | {shortcuts().screen_alert} alert | {shortcuts().screen_confirm}{" "}
568
+ confirm | {shortcuts().screen_prompt} prompt | {shortcuts().screen_select} select
569
+ </text>
570
+ <text fg={skin.muted}>
571
+ {shortcuts().screen_local} local stack | {shortcuts().screen_host} host stack
572
+ </text>
573
+ <text fg={skin.muted}>
574
+ local open: {shortcuts().local_push} push nested · {shortcuts().local_pop} close
575
+ </text>
576
+ <text fg={skin.muted}>{shortcuts().screen_home} returns home</text>
577
+ </box>
578
+ ) : null}
579
+ </box>
580
+
581
+ <box flexDirection="row" gap={1} paddingTop={1}>
582
+ <Btn txt="go home" run={() => props.api.route.navigate("home")} skin={skin} />
583
+ <Btn txt="modal" run={() => props.api.route.navigate(props.route.modal, value)} skin={skin} on />
584
+ <Btn txt="local overlay" run={show} skin={skin} />
585
+ <Btn txt="host overlay" run={() => host(props.api, props.input, skin)} skin={skin} />
586
+ <Btn txt="alert" run={() => warn(props.api, props.route, value)} skin={skin} />
587
+ <Btn txt="confirm" run={() => check(props.api, props.route, value)} skin={skin} />
588
+ <Btn txt="prompt" run={() => entry(props.api, props.route, value)} skin={skin} />
589
+ <Btn txt="select" run={() => picker(props.api, props.route, value)} skin={skin} />
590
+ </box>
591
+ </box>
592
+
593
+ <box
594
+ visible={value.local > 0}
595
+ width={dim().width}
596
+ height={dim().height}
597
+ alignItems="center"
598
+ position="absolute"
599
+ zIndex={3000}
600
+ paddingTop={dim().height / 4}
601
+ left={0}
602
+ top={0}
603
+ backgroundColor={RGBA.fromInts(0, 0, 0, 160)}
604
+ onMouseUp={() => {
605
+ pop()
606
+ }}
607
+ >
608
+ <box
609
+ onMouseUp={(evt) => {
610
+ evt.stopPropagation()
611
+ }}
612
+ width={60}
613
+ maxWidth={dim().width - 2}
614
+ backgroundColor={skin.panel}
615
+ border
616
+ borderColor={skin.border}
617
+ paddingTop={1}
618
+ paddingBottom={1}
619
+ paddingLeft={2}
620
+ paddingRight={2}
621
+ gap={1}
622
+ flexDirection="column"
623
+ >
624
+ <text fg={skin.text}>
625
+ <b>{props.input.label} local overlay</b>
626
+ </text>
627
+ <text fg={skin.muted}>Plugin-owned stack depth: {value.local}</text>
628
+ <text fg={skin.muted}>
629
+ {shortcuts().local_push} push nested · {shortcuts().local_pop} pop/close
630
+ </text>
631
+ <box flexDirection="row" gap={1}>
632
+ <Btn txt="push" run={push} skin={skin} on />
633
+ <Btn txt="pop" run={pop} skin={skin} />
634
+ </box>
635
+ </box>
636
+ </box>
637
+ </box>
638
+ )
639
+ }
640
+
641
+ const Modal = (props: {
642
+ api: TuiPluginApi
643
+ input: Cfg
644
+ route: Route
645
+ keys: Keys
646
+ params?: Record<string, unknown>
647
+ }) => {
648
+ const Dialog = props.api.ui.Dialog
649
+ const value = parse(props.params)
650
+ const skin = tone(props.api)
651
+
652
+ useBindings(() => ({
653
+ enabled: () => props.api.route.current.name === props.route.modal,
654
+ commands: [
655
+ {
656
+ name: command.modal_accept,
657
+ run() {
658
+ props.api.route.navigate(props.route.screen, { ...parse(props.params), source: "modal" })
659
+ },
660
+ },
661
+ {
662
+ name: command.modal_close,
663
+ run() {
664
+ props.api.route.navigate("home")
665
+ },
666
+ },
667
+ ],
668
+ bindings: props.keys.gather("smoke.modal", [command.modal_accept, command.modal_close]),
669
+ }))
670
+ const shortcuts = useKeymapSelector((keymap) => {
671
+ const bindings = keymap.getCommandBindings({
672
+ visibility: "registered",
673
+ commands: [command.modal, command.screen, command.modal_accept, command.modal_close],
674
+ })
675
+
676
+ return {
677
+ modal: props.api.keys.formatBindings(bindings.get(command.modal)) ?? "",
678
+ screen: props.api.keys.formatBindings(bindings.get(command.screen)) ?? "",
679
+ modal_accept: props.api.keys.formatBindings(bindings.get(command.modal_accept)) ?? "",
680
+ modal_close: props.api.keys.formatBindings(bindings.get(command.modal_close)) ?? "",
681
+ }
682
+ })
683
+
684
+ return (
685
+ <box width="100%" height="100%" backgroundColor={skin.panel}>
686
+ <Dialog onClose={() => props.api.route.navigate("home")}>
687
+ <box paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1} flexDirection="column">
688
+ <text fg={skin.text}>
689
+ <b>{props.input.label} modal</b>
690
+ </text>
691
+ <text fg={skin.muted}>{shortcuts().modal} modal command</text>
692
+ <text fg={skin.muted}>{shortcuts().screen} screen command</text>
693
+ <text fg={skin.muted}>
694
+ {shortcuts().modal_accept} opens screen · {shortcuts().modal_close} closes
695
+ </text>
696
+ <box flexDirection="row" gap={1}>
697
+ <Btn
698
+ txt="open screen"
699
+ run={() => props.api.route.navigate(props.route.screen, { ...value, source: "modal" })}
700
+ skin={skin}
701
+ on
702
+ />
703
+ <Btn txt="cancel" run={() => props.api.route.navigate("home")} skin={skin} />
704
+ </box>
705
+ </box>
706
+ </Dialog>
707
+ </box>
708
+ )
709
+ }
710
+
711
+ const home = (api: TuiPluginApi, input: Cfg) => ({
712
+ slots: {
713
+ home_logo(ctx) {
714
+ const map = ctx.theme.current
715
+ const skin = look(map)
716
+ const art = [
717
+ " $$\\",
718
+ " $$ |",
719
+ " $$$$$$$\\ $$$$$$\\$$$$\\ $$$$$$\\ $$ | $$\\ $$$$$$\\",
720
+ "$$ _____|$$ _$$ _$$\\ $$ __$$\\ $$ | $$ |$$ __$$\\",
721
+ "\\$$$$$$\\ $$ / $$ / $$ |$$ / $$ |$$$$$$ / $$$$$$$$ |",
722
+ " \\____$$\\ $$ | $$ | $$ |$$ | $$ |$$ _$$< $$ ____|",
723
+ "$$$$$$$ |$$ | $$ | $$ |\\$$$$$$ |$$ | \\$$\\ \\$$$$$$$\\",
724
+ "\\_______/ \\__| \\__| \\__| \\______/ \\__| \\__| \\_______|",
725
+ ]
726
+ const fill = [
727
+ skin.accent,
728
+ skin.muted,
729
+ ink(map, "info", ui.accent),
730
+ skin.text,
731
+ ink(map, "success", ui.accent),
732
+ ink(map, "warning", ui.accent),
733
+ ink(map, "secondary", ui.accent),
734
+ ink(map, "error", ui.accent),
735
+ ]
736
+
737
+ return (
738
+ <box flexDirection="column">
739
+ {art.map((line, i) => (
740
+ <text fg={fill[i]}>{line}</text>
741
+ ))}
742
+ </box>
743
+ )
744
+ },
745
+ home_prompt(ctx, value) {
746
+ const skin = look(ctx.theme.current)
747
+ const Prompt = api.ui.Prompt
748
+ const Slot = api.ui.Slot
749
+ const normal = [
750
+ `[SMOKE] route check for ${input.label}`,
751
+ "[SMOKE] confirm home_prompt slot override",
752
+ "[SMOKE] verify prompt-right slot passthrough",
753
+ ]
754
+ const shell = ["printf '[SMOKE] home prompt\n'", "git status --short", "bun --version"]
755
+ const hint = (
756
+ <box flexShrink={0} flexDirection="row" gap={1}>
757
+ <text fg={skin.muted}>
758
+ <span style={{ fg: skin.accent }}>•</span> smoke home prompt
759
+ </text>
760
+ </box>
761
+ )
762
+
763
+ return (
764
+ <Prompt
765
+ workspaceID={value.workspace_id}
766
+ hint={hint}
767
+ right={
768
+ <box flexDirection="row" gap={1}>
769
+ <Slot name="home_prompt_right" workspace_id={value.workspace_id} />
770
+ <Slot name="smoke_prompt_right" workspace_id={value.workspace_id} label={input.label} />
771
+ </box>
772
+ }
773
+ placeholders={{ normal, shell }}
774
+ />
775
+ )
776
+ },
777
+ home_prompt_right(ctx, value) {
778
+ const skin = look(ctx.theme.current)
779
+ const id = value.workspace_id?.slice(0, 8) ?? "none"
780
+ return (
781
+ <text fg={skin.muted}>
782
+ <span style={{ fg: skin.accent }}>{input.label}</span> home:{id}
783
+ </text>
784
+ )
785
+ },
786
+ session_prompt_right(ctx, value) {
787
+ const skin = look(ctx.theme.current)
788
+ return (
789
+ <text fg={skin.muted}>
790
+ <span style={{ fg: skin.accent }}>{input.label}</span> session:{value.session_id.slice(0, 8)}
791
+ </text>
792
+ )
793
+ },
794
+ smoke_prompt_right(ctx, value) {
795
+ const skin = look(ctx.theme.current)
796
+ const id = typeof value.workspace_id === "string" ? value.workspace_id.slice(0, 8) : "none"
797
+ const label = typeof value.label === "string" ? value.label : input.label
798
+ return (
799
+ <text fg={skin.muted}>
800
+ <span style={{ fg: skin.accent }}>{label}</span> custom:{id}
801
+ </text>
802
+ )
803
+ },
804
+ home_bottom(ctx) {
805
+ const skin = look(ctx.theme.current)
806
+ const text = "extra content in the unified home bottom slot"
807
+
808
+ return (
809
+ <box width="100%" maxWidth={75} alignItems="center" paddingTop={1} flexShrink={0} gap={1}>
810
+ <box
811
+ border
812
+ borderColor={skin.border}
813
+ backgroundColor={skin.panel}
814
+ paddingTop={1}
815
+ paddingBottom={1}
816
+ paddingLeft={2}
817
+ paddingRight={2}
818
+ width="100%"
819
+ >
820
+ <text fg={skin.muted}>
821
+ <span style={{ fg: skin.accent }}>{input.label}</span> {text}
822
+ </text>
823
+ </box>
824
+ </box>
825
+ )
826
+ },
827
+ },
828
+ })
829
+
830
+ const block = (input: Cfg, order: number, title: string, text: string): TuiSlotPlugin => ({
831
+ order,
832
+ slots: {
833
+ sidebar_content(ctx, value) {
834
+ const skin = look(ctx.theme.current)
835
+
836
+ return (
837
+ <box
838
+ border
839
+ borderColor={skin.border}
840
+ backgroundColor={skin.panel}
841
+ paddingTop={1}
842
+ paddingBottom={1}
843
+ paddingLeft={2}
844
+ paddingRight={2}
845
+ flexDirection="column"
846
+ gap={1}
847
+ >
848
+ <text fg={skin.accent}>
849
+ <b>{title}</b>
850
+ </text>
851
+ <text fg={skin.text}>{text}</text>
852
+ <text fg={skin.muted}>
853
+ {input.label} order {order} · session {value.session_id.slice(0, 8)}
854
+ </text>
855
+ </box>
856
+ )
857
+ },
858
+ },
859
+ })
860
+
861
+ const slot = (api: TuiPluginApi, input: Cfg): TuiSlotPlugin[] => [
862
+ home(api, input),
863
+ block(input, 50, "Smoke above", "renders above internal sidebar blocks"),
864
+ block(input, 250, "Smoke between", "renders between internal sidebar blocks"),
865
+ block(input, 650, "Smoke below", "renders below internal sidebar blocks"),
866
+ ]
867
+
868
+ const reg = (api: TuiPluginApi, input: Cfg, keys: Keys) => {
869
+ const route = names(input)
870
+ api.keymap.registerLayer({
871
+ commands: [
872
+ {
873
+ name: command.modal,
874
+ title: `${input.label} modal`,
875
+ category: "Plugin",
876
+ namespace: "palette",
877
+ slashName: "smoke",
878
+ run() {
879
+ api.route.navigate(route.modal, { source: "command" })
880
+ },
881
+ },
882
+ {
883
+ name: command.screen,
884
+ title: `${input.label} screen`,
885
+ category: "Plugin",
886
+ namespace: "palette",
887
+ slashName: "smoke-screen",
888
+ run() {
889
+ api.route.navigate(route.screen, { source: "command", tab: 0, count: 0 })
890
+ },
891
+ },
892
+ {
893
+ name: command.alert,
894
+ title: `${input.label} alert dialog`,
895
+ category: "Plugin",
896
+ namespace: "palette",
897
+ slashName: "smoke-alert",
898
+ run() {
899
+ warn(api, route, current(api, route))
900
+ },
901
+ },
902
+ {
903
+ name: command.confirm,
904
+ title: `${input.label} confirm dialog`,
905
+ category: "Plugin",
906
+ namespace: "palette",
907
+ slashName: "smoke-confirm",
908
+ run() {
909
+ check(api, route, current(api, route))
910
+ },
911
+ },
912
+ {
913
+ name: command.prompt,
914
+ title: `${input.label} prompt dialog`,
915
+ category: "Plugin",
916
+ namespace: "palette",
917
+ slashName: "smoke-prompt",
918
+ run() {
919
+ entry(api, route, current(api, route))
920
+ },
921
+ },
922
+ {
923
+ name: command.select,
924
+ title: `${input.label} select dialog`,
925
+ category: "Plugin",
926
+ namespace: "palette",
927
+ slashName: "smoke-select",
928
+ run() {
929
+ picker(api, route, current(api, route))
930
+ },
931
+ },
932
+ {
933
+ name: command.host,
934
+ title: `${input.label} host overlay`,
935
+ category: "Plugin",
936
+ namespace: "palette",
937
+ slashName: "smoke-host",
938
+ run() {
939
+ host(api, input, tone(api))
940
+ },
941
+ },
942
+ {
943
+ name: command.home,
944
+ title: `${input.label} go home`,
945
+ category: "Plugin",
946
+ namespace: "palette",
947
+ enabled: () => api.route.current.name !== "home",
948
+ run() {
949
+ api.route.navigate("home")
950
+ },
951
+ },
952
+ {
953
+ name: command.toast,
954
+ title: `${input.label} toast`,
955
+ category: "Plugin",
956
+ namespace: "palette",
957
+ run() {
958
+ api.ui.toast({
959
+ variant: "info",
960
+ title: "Smoke",
961
+ message: "Plugin toast works",
962
+ duration: 2000,
963
+ })
964
+ },
965
+ },
966
+ ],
967
+ bindings: keys.gather("smoke.global", [
968
+ command.modal,
969
+ command.screen,
970
+ command.alert,
971
+ command.confirm,
972
+ command.prompt,
973
+ command.select,
974
+ command.host,
975
+ command.home,
976
+ command.toast,
977
+ ]),
978
+ })
979
+ }
980
+
981
+ const tui: TuiPlugin = async (api, options, meta) => {
982
+ if (options?.enabled === false) return
983
+
984
+ await api.theme.install("./smoke-theme.json")
985
+ api.theme.set("smoke-theme")
986
+
987
+ const value = cfg(options)
988
+ const route = names(value)
989
+ const keys = createKeys(value.keybinds)
990
+ const fx = new VignetteEffect(value.vignette)
991
+ const post = fx.apply.bind(fx)
992
+ api.renderer.addPostProcessFn(post)
993
+ api.lifecycle.onDispose(() => {
994
+ api.renderer.removePostProcessFn(post)
995
+ })
996
+
997
+ api.route.register([
998
+ {
999
+ name: route.screen,
1000
+ render: ({ params }) => <Screen api={api} input={value} route={route} keys={keys} meta={meta} params={params} />,
1001
+ },
1002
+ {
1003
+ name: route.modal,
1004
+ render: ({ params }) => <Modal api={api} input={value} route={route} keys={keys} params={params} />,
1005
+ },
1006
+ ])
1007
+
1008
+ reg(api, value, keys)
1009
+ for (const item of slot(api, value)) {
1010
+ api.slots.register(item)
1011
+ }
1012
+ }
1013
+
1014
+ const plugin: TuiPluginModule & { id: string } = {
1015
+ id: "tui-smoke",
1016
+ tui,
1017
+ }
1018
+
1019
+ export default plugin