@tinfoilsh/tinfoil-terminal 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 (369) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/bin/opencode +88 -0
  5. package/bunfig.toml +7 -0
  6. package/package.json +134 -0
  7. package/parsers-config.ts +253 -0
  8. package/script/build.ts +176 -0
  9. package/script/postinstall.mjs +122 -0
  10. package/script/publish-registries.ts +187 -0
  11. package/script/publish.ts +70 -0
  12. package/script/schema.ts +47 -0
  13. package/src/acp/README.md +164 -0
  14. package/src/acp/agent.ts +1124 -0
  15. package/src/acp/session.ts +101 -0
  16. package/src/acp/types.ts +22 -0
  17. package/src/agent/agent.ts +284 -0
  18. package/src/agent/generate.txt +75 -0
  19. package/src/agent/prompt/compaction.txt +12 -0
  20. package/src/agent/prompt/explore.txt +18 -0
  21. package/src/agent/prompt/summary.txt +11 -0
  22. package/src/agent/prompt/title.txt +43 -0
  23. package/src/auth/index.ts +73 -0
  24. package/src/bun/index.ts +130 -0
  25. package/src/bus/bus-event.ts +43 -0
  26. package/src/bus/global.ts +10 -0
  27. package/src/bus/index.ts +105 -0
  28. package/src/cli/bootstrap.ts +17 -0
  29. package/src/cli/cmd/acp.ts +69 -0
  30. package/src/cli/cmd/agent.ts +257 -0
  31. package/src/cli/cmd/auth.ts +400 -0
  32. package/src/cli/cmd/cmd.ts +7 -0
  33. package/src/cli/cmd/debug/agent.ts +29 -0
  34. package/src/cli/cmd/debug/config.ts +16 -0
  35. package/src/cli/cmd/debug/file.ts +97 -0
  36. package/src/cli/cmd/debug/index.ts +48 -0
  37. package/src/cli/cmd/debug/lsp.ts +52 -0
  38. package/src/cli/cmd/debug/ripgrep.ts +87 -0
  39. package/src/cli/cmd/debug/scrap.ts +16 -0
  40. package/src/cli/cmd/debug/skill.ts +16 -0
  41. package/src/cli/cmd/debug/snapshot.ts +52 -0
  42. package/src/cli/cmd/export.ts +88 -0
  43. package/src/cli/cmd/generate.ts +38 -0
  44. package/src/cli/cmd/github.ts +1546 -0
  45. package/src/cli/cmd/import.ts +98 -0
  46. package/src/cli/cmd/mcp.ts +671 -0
  47. package/src/cli/cmd/models.ts +77 -0
  48. package/src/cli/cmd/pr.ts +112 -0
  49. package/src/cli/cmd/run.ts +395 -0
  50. package/src/cli/cmd/serve.ts +16 -0
  51. package/src/cli/cmd/session.ts +135 -0
  52. package/src/cli/cmd/stats.ts +402 -0
  53. package/src/cli/cmd/tui/app.tsx +743 -0
  54. package/src/cli/cmd/tui/attach.ts +31 -0
  55. package/src/cli/cmd/tui/component/border.tsx +21 -0
  56. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  57. package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
  58. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  59. package/src/cli/cmd/tui/component/dialog-model.tsx +168 -0
  60. package/src/cli/cmd/tui/component/dialog-provider.tsx +47 -0
  61. package/src/cli/cmd/tui/component/dialog-session-list.tsx +115 -0
  62. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  63. package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
  64. package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
  65. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  66. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  67. package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
  68. package/src/cli/cmd/tui/component/logo.tsx +33 -0
  69. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +718 -0
  70. package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
  71. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  72. package/src/cli/cmd/tui/component/prompt/index.tsx +1083 -0
  73. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  74. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  75. package/src/cli/cmd/tui/component/tips.ts +103 -0
  76. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  77. package/src/cli/cmd/tui/context/args.tsx +14 -0
  78. package/src/cli/cmd/tui/context/directory.ts +13 -0
  79. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  80. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  81. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  82. package/src/cli/cmd/tui/context/kv.tsx +49 -0
  83. package/src/cli/cmd/tui/context/local.tsx +393 -0
  84. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  85. package/src/cli/cmd/tui/context/route.tsx +46 -0
  86. package/src/cli/cmd/tui/context/sdk.tsx +94 -0
  87. package/src/cli/cmd/tui/context/sync.tsx +427 -0
  88. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  89. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  90. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  91. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  92. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  93. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  94. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  95. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  96. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  97. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  98. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  99. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  100. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  101. package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
  102. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  103. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  104. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  105. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  106. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  107. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  108. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  109. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  110. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  111. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  112. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  113. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  114. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  115. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  116. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  117. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  118. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  119. package/src/cli/cmd/tui/context/theme.tsx +1150 -0
  120. package/src/cli/cmd/tui/event.ts +46 -0
  121. package/src/cli/cmd/tui/routes/home.tsx +138 -0
  122. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  123. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  124. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  125. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  126. package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
  127. package/src/cli/cmd/tui/routes/session/header.tsx +105 -0
  128. package/src/cli/cmd/tui/routes/session/index.tsx +1897 -0
  129. package/src/cli/cmd/tui/routes/session/permission.tsx +416 -0
  130. package/src/cli/cmd/tui/routes/session/question.tsx +368 -0
  131. package/src/cli/cmd/tui/routes/session/sidebar.tsx +279 -0
  132. package/src/cli/cmd/tui/spawn.ts +46 -0
  133. package/src/cli/cmd/tui/thread.ts +174 -0
  134. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  135. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  136. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
  137. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  138. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  139. package/src/cli/cmd/tui/ui/dialog-select.tsx +345 -0
  140. package/src/cli/cmd/tui/ui/dialog.tsx +172 -0
  141. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  142. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  143. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  144. package/src/cli/cmd/tui/util/clipboard.ts +128 -0
  145. package/src/cli/cmd/tui/util/editor.ts +32 -0
  146. package/src/cli/cmd/tui/util/signal.ts +7 -0
  147. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  148. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  149. package/src/cli/cmd/tui/worker.ts +95 -0
  150. package/src/cli/cmd/uninstall.ts +344 -0
  151. package/src/cli/cmd/upgrade.ts +67 -0
  152. package/src/cli/cmd/web.ts +73 -0
  153. package/src/cli/error.ts +57 -0
  154. package/src/cli/network.ts +53 -0
  155. package/src/cli/ui.ts +87 -0
  156. package/src/cli/upgrade.ts +25 -0
  157. package/src/command/index.ts +131 -0
  158. package/src/command/template/initialize.txt +10 -0
  159. package/src/command/template/review.txt +97 -0
  160. package/src/config/config.ts +1226 -0
  161. package/src/config/markdown.ts +41 -0
  162. package/src/env/index.ts +26 -0
  163. package/src/file/ignore.ts +83 -0
  164. package/src/file/index.ts +411 -0
  165. package/src/file/ripgrep.ts +409 -0
  166. package/src/file/time.ts +64 -0
  167. package/src/file/watcher.ts +118 -0
  168. package/src/flag/flag.ts +51 -0
  169. package/src/format/formatter.ts +359 -0
  170. package/src/format/index.ts +137 -0
  171. package/src/global/index.ts +55 -0
  172. package/src/id/id.ts +83 -0
  173. package/src/ide/index.ts +76 -0
  174. package/src/index.ts +161 -0
  175. package/src/installation/index.ts +205 -0
  176. package/src/lsp/client.ts +252 -0
  177. package/src/lsp/index.ts +485 -0
  178. package/src/lsp/language.ts +119 -0
  179. package/src/lsp/server.ts +2032 -0
  180. package/src/mcp/auth.ts +135 -0
  181. package/src/mcp/index.ts +874 -0
  182. package/src/mcp/oauth-callback.ts +200 -0
  183. package/src/mcp/oauth-provider.ts +154 -0
  184. package/src/patch/index.ts +622 -0
  185. package/src/permission/arity.ts +163 -0
  186. package/src/permission/index.ts +210 -0
  187. package/src/permission/next.ts +269 -0
  188. package/src/plugin/codex.ts +524 -0
  189. package/src/plugin/index.ts +118 -0
  190. package/src/project/bootstrap.ts +31 -0
  191. package/src/project/instance.ts +78 -0
  192. package/src/project/project.ts +316 -0
  193. package/src/project/state.ts +65 -0
  194. package/src/project/vcs.ts +76 -0
  195. package/src/provider/auth.ts +147 -0
  196. package/src/provider/models-macro.ts +11 -0
  197. package/src/provider/models.ts +86 -0
  198. package/src/provider/provider.ts +429 -0
  199. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  200. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  201. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  202. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  203. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  204. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  205. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  206. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  207. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
  208. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  209. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  210. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  211. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  212. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  213. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  214. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  215. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  216. package/src/provider/transform.ts +654 -0
  217. package/src/pty/index.ts +229 -0
  218. package/src/question/index.ts +170 -0
  219. package/src/server/error.ts +36 -0
  220. package/src/server/mdns.ts +57 -0
  221. package/src/server/project.ts +79 -0
  222. package/src/server/question.ts +95 -0
  223. package/src/server/server.ts +2878 -0
  224. package/src/server/tui.ts +71 -0
  225. package/src/session/compaction.ts +225 -0
  226. package/src/session/index.ts +476 -0
  227. package/src/session/llm.ts +235 -0
  228. package/src/session/message-v2.ts +683 -0
  229. package/src/session/message.ts +189 -0
  230. package/src/session/processor.ts +406 -0
  231. package/src/session/prompt/anthropic-20250930.txt +166 -0
  232. package/src/session/prompt/anthropic.txt +105 -0
  233. package/src/session/prompt/anthropic_spoof.txt +1 -0
  234. package/src/session/prompt/beast.txt +147 -0
  235. package/src/session/prompt/build-switch.txt +5 -0
  236. package/src/session/prompt/codex.txt +318 -0
  237. package/src/session/prompt/codex_header.txt +318 -0
  238. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  239. package/src/session/prompt/gemini.txt +155 -0
  240. package/src/session/prompt/max-steps.txt +16 -0
  241. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  242. package/src/session/prompt/plan.txt +26 -0
  243. package/src/session/prompt/qwen.txt +109 -0
  244. package/src/session/prompt.ts +1652 -0
  245. package/src/session/retry.ts +90 -0
  246. package/src/session/revert.ts +108 -0
  247. package/src/session/status.ts +76 -0
  248. package/src/session/summary.ts +194 -0
  249. package/src/session/system.ts +138 -0
  250. package/src/session/todo.ts +37 -0
  251. package/src/share/share-next.ts +194 -0
  252. package/src/share/share.ts +87 -0
  253. package/src/shell/shell.ts +67 -0
  254. package/src/skill/index.ts +1 -0
  255. package/src/skill/skill.ts +127 -0
  256. package/src/snapshot/index.ts +199 -0
  257. package/src/storage/storage.ts +226 -0
  258. package/src/tool/bash.ts +258 -0
  259. package/src/tool/bash.txt +115 -0
  260. package/src/tool/batch.ts +175 -0
  261. package/src/tool/batch.txt +24 -0
  262. package/src/tool/codesearch.ts +132 -0
  263. package/src/tool/codesearch.txt +12 -0
  264. package/src/tool/edit.ts +645 -0
  265. package/src/tool/edit.txt +10 -0
  266. package/src/tool/external-directory.ts +33 -0
  267. package/src/tool/glob.ts +77 -0
  268. package/src/tool/glob.txt +6 -0
  269. package/src/tool/grep.ts +136 -0
  270. package/src/tool/grep.txt +8 -0
  271. package/src/tool/invalid.ts +17 -0
  272. package/src/tool/ls.ts +121 -0
  273. package/src/tool/ls.txt +1 -0
  274. package/src/tool/lsp.ts +96 -0
  275. package/src/tool/lsp.txt +19 -0
  276. package/src/tool/multiedit.ts +46 -0
  277. package/src/tool/multiedit.txt +41 -0
  278. package/src/tool/patch.ts +201 -0
  279. package/src/tool/patch.txt +1 -0
  280. package/src/tool/question.ts +33 -0
  281. package/src/tool/question.txt +10 -0
  282. package/src/tool/read.ts +200 -0
  283. package/src/tool/read.txt +12 -0
  284. package/src/tool/registry.ts +141 -0
  285. package/src/tool/skill.ts +75 -0
  286. package/src/tool/task.ts +181 -0
  287. package/src/tool/task.txt +60 -0
  288. package/src/tool/todo.ts +53 -0
  289. package/src/tool/todoread.txt +14 -0
  290. package/src/tool/todowrite.txt +167 -0
  291. package/src/tool/tool.ts +88 -0
  292. package/src/tool/truncation.ts +98 -0
  293. package/src/tool/webfetch.ts +182 -0
  294. package/src/tool/webfetch.txt +13 -0
  295. package/src/tool/websearch.ts +144 -0
  296. package/src/tool/websearch.txt +11 -0
  297. package/src/tool/write.ts +80 -0
  298. package/src/tool/write.txt +8 -0
  299. package/src/util/archive.ts +16 -0
  300. package/src/util/color.ts +19 -0
  301. package/src/util/context.ts +25 -0
  302. package/src/util/defer.ts +12 -0
  303. package/src/util/eventloop.ts +20 -0
  304. package/src/util/filesystem.ts +83 -0
  305. package/src/util/fn.ts +11 -0
  306. package/src/util/iife.ts +3 -0
  307. package/src/util/keybind.ts +102 -0
  308. package/src/util/lazy.ts +18 -0
  309. package/src/util/locale.ts +81 -0
  310. package/src/util/lock.ts +98 -0
  311. package/src/util/log.ts +180 -0
  312. package/src/util/queue.ts +32 -0
  313. package/src/util/rpc.ts +66 -0
  314. package/src/util/scrap.ts +10 -0
  315. package/src/util/signal.ts +12 -0
  316. package/src/util/timeout.ts +14 -0
  317. package/src/util/token.ts +7 -0
  318. package/src/util/wildcard.ts +54 -0
  319. package/src/worktree/index.ts +217 -0
  320. package/sst-env.d.ts +9 -0
  321. package/test/agent/agent.test.ts +511 -0
  322. package/test/bun.test.ts +53 -0
  323. package/test/cli/github-action.test.ts +129 -0
  324. package/test/cli/github-remote.test.ts +80 -0
  325. package/test/cli/tui/transcript.test.ts +297 -0
  326. package/test/config/agent-color.test.ts +66 -0
  327. package/test/config/config.test.ts +1235 -0
  328. package/test/config/markdown.test.ts +89 -0
  329. package/test/file/ignore.test.ts +10 -0
  330. package/test/file/path-traversal.test.ts +115 -0
  331. package/test/fixture/fixture.ts +45 -0
  332. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  333. package/test/ide/ide.test.ts +82 -0
  334. package/test/keybind.test.ts +421 -0
  335. package/test/lsp/client.test.ts +95 -0
  336. package/test/mcp/headers.test.ts +153 -0
  337. package/test/patch/patch.test.ts +348 -0
  338. package/test/permission/arity.test.ts +33 -0
  339. package/test/permission/next.test.ts +652 -0
  340. package/test/permission-task.test.ts +319 -0
  341. package/test/plugin/codex.test.ts +123 -0
  342. package/test/preload.ts +65 -0
  343. package/test/project/project.test.ts +120 -0
  344. package/test/provider/amazon-bedrock.test.ts +205 -0
  345. package/test/provider/provider.test.ts +2127 -0
  346. package/test/provider/transform.test.ts +1155 -0
  347. package/test/question/question.test.ts +300 -0
  348. package/test/server/session-select.test.ts +78 -0
  349. package/test/session/compaction.test.ts +251 -0
  350. package/test/session/message-v2.test.ts +570 -0
  351. package/test/session/retry.test.ts +131 -0
  352. package/test/session/revert-compact.test.ts +285 -0
  353. package/test/session/session.test.ts +71 -0
  354. package/test/skill/skill.test.ts +185 -0
  355. package/test/snapshot/snapshot.test.ts +939 -0
  356. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  357. package/test/tool/bash.test.ts +320 -0
  358. package/test/tool/external-directory.test.ts +126 -0
  359. package/test/tool/fixtures/large-image.png +0 -0
  360. package/test/tool/fixtures/models-api.json +33453 -0
  361. package/test/tool/grep.test.ts +109 -0
  362. package/test/tool/patch.test.ts +261 -0
  363. package/test/tool/read.test.ts +303 -0
  364. package/test/tool/truncation.test.ts +159 -0
  365. package/test/util/iife.test.ts +36 -0
  366. package/test/util/lazy.test.ts +50 -0
  367. package/test/util/timeout.test.ts +21 -0
  368. package/test/util/wildcard.test.ts +55 -0
  369. package/tsconfig.json +16 -0
@@ -0,0 +1,1150 @@
1
+ import { SyntaxStyle, RGBA, type TerminalColors } from "@opentui/core"
2
+ import path from "path"
3
+ import { createEffect, createMemo, onMount } from "solid-js"
4
+ import { useSync } from "@tui/context/sync"
5
+ import { createSimpleContext } from "./helper"
6
+ import aura from "./theme/aura.json" with { type: "json" }
7
+ import ayu from "./theme/ayu.json" with { type: "json" }
8
+ import catppuccin from "./theme/catppuccin.json" with { type: "json" }
9
+ import catppuccinFrappe from "./theme/catppuccin-frappe.json" with { type: "json" }
10
+ import catppuccinMacchiato from "./theme/catppuccin-macchiato.json" with { type: "json" }
11
+ import cobalt2 from "./theme/cobalt2.json" with { type: "json" }
12
+ import cursor from "./theme/cursor.json" with { type: "json" }
13
+ import dracula from "./theme/dracula.json" with { type: "json" }
14
+ import everforest from "./theme/everforest.json" with { type: "json" }
15
+ import flexoki from "./theme/flexoki.json" with { type: "json" }
16
+ import github from "./theme/github.json" with { type: "json" }
17
+ import gruvbox from "./theme/gruvbox.json" with { type: "json" }
18
+ import kanagawa from "./theme/kanagawa.json" with { type: "json" }
19
+ import material from "./theme/material.json" with { type: "json" }
20
+ import matrix from "./theme/matrix.json" with { type: "json" }
21
+ import mercury from "./theme/mercury.json" with { type: "json" }
22
+ import monokai from "./theme/monokai.json" with { type: "json" }
23
+ import nightowl from "./theme/nightowl.json" with { type: "json" }
24
+ import nord from "./theme/nord.json" with { type: "json" }
25
+ import osakaJade from "./theme/osaka-jade.json" with { type: "json" }
26
+ import onedark from "./theme/one-dark.json" with { type: "json" }
27
+ import opencode from "./theme/opencode.json" with { type: "json" }
28
+ import orng from "./theme/orng.json" with { type: "json" }
29
+ import lucentOrng from "./theme/lucent-orng.json" with { type: "json" }
30
+ import palenight from "./theme/palenight.json" with { type: "json" }
31
+ import rosepine from "./theme/rosepine.json" with { type: "json" }
32
+ import solarized from "./theme/solarized.json" with { type: "json" }
33
+ import synthwave84 from "./theme/synthwave84.json" with { type: "json" }
34
+ import tokyonight from "./theme/tokyonight.json" with { type: "json" }
35
+ import vercel from "./theme/vercel.json" with { type: "json" }
36
+ import vesper from "./theme/vesper.json" with { type: "json" }
37
+ import zenburn from "./theme/zenburn.json" with { type: "json" }
38
+ import { useKV } from "./kv"
39
+ import { useRenderer } from "@opentui/solid"
40
+ import { createStore, produce } from "solid-js/store"
41
+ import { Global } from "@/global"
42
+ import { Filesystem } from "@/util/filesystem"
43
+ import { useSDK } from "./sdk"
44
+
45
+ type ThemeColors = {
46
+ primary: RGBA
47
+ secondary: RGBA
48
+ accent: RGBA
49
+ error: RGBA
50
+ warning: RGBA
51
+ success: RGBA
52
+ info: RGBA
53
+ text: RGBA
54
+ textMuted: RGBA
55
+ selectedListItemText: RGBA
56
+ background: RGBA
57
+ backgroundPanel: RGBA
58
+ backgroundElement: RGBA
59
+ backgroundMenu: RGBA
60
+ border: RGBA
61
+ borderActive: RGBA
62
+ borderSubtle: RGBA
63
+ diffAdded: RGBA
64
+ diffRemoved: RGBA
65
+ diffContext: RGBA
66
+ diffHunkHeader: RGBA
67
+ diffHighlightAdded: RGBA
68
+ diffHighlightRemoved: RGBA
69
+ diffAddedBg: RGBA
70
+ diffRemovedBg: RGBA
71
+ diffContextBg: RGBA
72
+ diffLineNumber: RGBA
73
+ diffAddedLineNumberBg: RGBA
74
+ diffRemovedLineNumberBg: RGBA
75
+ markdownText: RGBA
76
+ markdownHeading: RGBA
77
+ markdownLink: RGBA
78
+ markdownLinkText: RGBA
79
+ markdownCode: RGBA
80
+ markdownBlockQuote: RGBA
81
+ markdownEmph: RGBA
82
+ markdownStrong: RGBA
83
+ markdownHorizontalRule: RGBA
84
+ markdownListItem: RGBA
85
+ markdownListEnumeration: RGBA
86
+ markdownImage: RGBA
87
+ markdownImageText: RGBA
88
+ markdownCodeBlock: RGBA
89
+ syntaxComment: RGBA
90
+ syntaxKeyword: RGBA
91
+ syntaxFunction: RGBA
92
+ syntaxVariable: RGBA
93
+ syntaxString: RGBA
94
+ syntaxNumber: RGBA
95
+ syntaxType: RGBA
96
+ syntaxOperator: RGBA
97
+ syntaxPunctuation: RGBA
98
+ }
99
+
100
+ type Theme = ThemeColors & {
101
+ _hasSelectedListItemText: boolean
102
+ thinkingOpacity: number
103
+ }
104
+
105
+ export function selectedForeground(theme: Theme, bg?: RGBA): RGBA {
106
+ // If theme explicitly defines selectedListItemText, use it
107
+ if (theme._hasSelectedListItemText) {
108
+ return theme.selectedListItemText
109
+ }
110
+
111
+ // For transparent backgrounds, calculate contrast based on the actual bg (or fallback to primary)
112
+ if (theme.background.a === 0) {
113
+ const targetColor = bg ?? theme.primary
114
+ const { r, g, b } = targetColor
115
+ const luminance = 0.299 * r + 0.587 * g + 0.114 * b
116
+ return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255)
117
+ }
118
+
119
+ // Fall back to background color
120
+ return theme.background
121
+ }
122
+
123
+ type HexColor = `#${string}`
124
+ type RefName = string
125
+ type Variant = {
126
+ dark: HexColor | RefName
127
+ light: HexColor | RefName
128
+ }
129
+ type ColorValue = HexColor | RefName | Variant | RGBA
130
+ type ThemeJson = {
131
+ $schema?: string
132
+ defs?: Record<string, HexColor | RefName>
133
+ theme: Omit<Record<keyof ThemeColors, ColorValue>, "selectedListItemText" | "backgroundMenu"> & {
134
+ selectedListItemText?: ColorValue
135
+ backgroundMenu?: ColorValue
136
+ thinkingOpacity?: number
137
+ }
138
+ }
139
+
140
+ export const DEFAULT_THEMES: Record<string, ThemeJson> = {
141
+ aura,
142
+ ayu,
143
+ catppuccin,
144
+ ["catppuccin-frappe"]: catppuccinFrappe,
145
+ ["catppuccin-macchiato"]: catppuccinMacchiato,
146
+ cobalt2,
147
+ cursor,
148
+ dracula,
149
+ everforest,
150
+ flexoki,
151
+ github,
152
+ gruvbox,
153
+ kanagawa,
154
+ material,
155
+ matrix,
156
+ mercury,
157
+ monokai,
158
+ nightowl,
159
+ nord,
160
+ ["one-dark"]: onedark,
161
+ ["osaka-jade"]: osakaJade,
162
+ opencode,
163
+ orng,
164
+ ["lucent-orng"]: lucentOrng,
165
+ palenight,
166
+ rosepine,
167
+ solarized,
168
+ synthwave84,
169
+ tokyonight,
170
+ vesper,
171
+ vercel,
172
+ zenburn,
173
+ }
174
+
175
+ function resolveTheme(theme: ThemeJson, mode: "dark" | "light") {
176
+ const defs = theme.defs ?? {}
177
+ function resolveColor(c: ColorValue): RGBA {
178
+ if (c instanceof RGBA) return c
179
+ if (typeof c === "string") {
180
+ if (c === "transparent" || c === "none") return RGBA.fromInts(0, 0, 0, 0)
181
+
182
+ if (c.startsWith("#")) return RGBA.fromHex(c)
183
+
184
+ if (defs[c] != null) {
185
+ return resolveColor(defs[c])
186
+ } else if (theme.theme[c as keyof ThemeColors] !== undefined) {
187
+ return resolveColor(theme.theme[c as keyof ThemeColors]!)
188
+ } else {
189
+ throw new Error(`Color reference "${c}" not found in defs or theme`)
190
+ }
191
+ }
192
+ if (typeof c === "number") {
193
+ return ansiToRgba(c)
194
+ }
195
+ return resolveColor(c[mode])
196
+ }
197
+
198
+ const resolved = Object.fromEntries(
199
+ Object.entries(theme.theme)
200
+ .filter(([key]) => key !== "selectedListItemText" && key !== "backgroundMenu" && key !== "thinkingOpacity")
201
+ .map(([key, value]) => {
202
+ return [key, resolveColor(value as ColorValue)]
203
+ }),
204
+ ) as Partial<ThemeColors>
205
+
206
+ // Handle selectedListItemText separately since it's optional
207
+ const hasSelectedListItemText = theme.theme.selectedListItemText !== undefined
208
+ if (hasSelectedListItemText) {
209
+ resolved.selectedListItemText = resolveColor(theme.theme.selectedListItemText!)
210
+ } else {
211
+ // Backward compatibility: if selectedListItemText is not defined, use background color
212
+ // This preserves the current behavior for all existing themes
213
+ resolved.selectedListItemText = resolved.background
214
+ }
215
+
216
+ // Handle backgroundMenu - optional with fallback to backgroundElement
217
+ if (theme.theme.backgroundMenu !== undefined) {
218
+ resolved.backgroundMenu = resolveColor(theme.theme.backgroundMenu)
219
+ } else {
220
+ resolved.backgroundMenu = resolved.backgroundElement
221
+ }
222
+
223
+ // Handle thinkingOpacity - optional with default of 0.6
224
+ const thinkingOpacity = theme.theme.thinkingOpacity ?? 0.6
225
+
226
+ return {
227
+ ...resolved,
228
+ _hasSelectedListItemText: hasSelectedListItemText,
229
+ thinkingOpacity,
230
+ } as Theme
231
+ }
232
+
233
+ function ansiToRgba(code: number): RGBA {
234
+ // Standard ANSI colors (0-15)
235
+ if (code < 16) {
236
+ const ansiColors = [
237
+ "#000000", // Black
238
+ "#800000", // Red
239
+ "#008000", // Green
240
+ "#808000", // Yellow
241
+ "#000080", // Blue
242
+ "#800080", // Magenta
243
+ "#008080", // Cyan
244
+ "#c0c0c0", // White
245
+ "#808080", // Bright Black
246
+ "#ff0000", // Bright Red
247
+ "#00ff00", // Bright Green
248
+ "#ffff00", // Bright Yellow
249
+ "#0000ff", // Bright Blue
250
+ "#ff00ff", // Bright Magenta
251
+ "#00ffff", // Bright Cyan
252
+ "#ffffff", // Bright White
253
+ ]
254
+ return RGBA.fromHex(ansiColors[code] ?? "#000000")
255
+ }
256
+
257
+ // 6x6x6 Color Cube (16-231)
258
+ if (code < 232) {
259
+ const index = code - 16
260
+ const b = index % 6
261
+ const g = Math.floor(index / 6) % 6
262
+ const r = Math.floor(index / 36)
263
+
264
+ const val = (x: number) => (x === 0 ? 0 : x * 40 + 55)
265
+ return RGBA.fromInts(val(r), val(g), val(b))
266
+ }
267
+
268
+ // Grayscale Ramp (232-255)
269
+ if (code < 256) {
270
+ const gray = (code - 232) * 10 + 8
271
+ return RGBA.fromInts(gray, gray, gray)
272
+ }
273
+
274
+ // Fallback for invalid codes
275
+ return RGBA.fromInts(0, 0, 0)
276
+ }
277
+
278
+ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
279
+ name: "Theme",
280
+ init: (props: { mode: "dark" | "light" }) => {
281
+ const sync = useSync()
282
+ const kv = useKV()
283
+ const [store, setStore] = createStore({
284
+ themes: DEFAULT_THEMES,
285
+ mode: kv.get("theme_mode", props.mode),
286
+ active: (sync.data.config.theme ?? kv.get("theme", "opencode")) as string,
287
+ ready: false,
288
+ })
289
+
290
+ createEffect(() => {
291
+ const theme = sync.data.config.theme
292
+ if (theme) setStore("active", theme)
293
+ })
294
+
295
+ function init() {
296
+ resolveSystemTheme()
297
+ getCustomThemes()
298
+ .then((custom) => {
299
+ setStore(
300
+ produce((draft) => {
301
+ Object.assign(draft.themes, custom)
302
+ }),
303
+ )
304
+ })
305
+ .catch(() => {
306
+ setStore("active", "opencode")
307
+ })
308
+ .finally(() => {
309
+ if (store.active !== "system") {
310
+ setStore("ready", true)
311
+ }
312
+ })
313
+ }
314
+
315
+ onMount(init)
316
+
317
+ function resolveSystemTheme() {
318
+ console.log("resolveSystemTheme")
319
+ renderer
320
+ .getPalette({
321
+ size: 16,
322
+ })
323
+ .then((colors) => {
324
+ console.log(colors.palette)
325
+ if (!colors.palette[0]) {
326
+ if (store.active === "system") {
327
+ setStore(
328
+ produce((draft) => {
329
+ draft.active = "opencode"
330
+ draft.ready = true
331
+ }),
332
+ )
333
+ }
334
+ return
335
+ }
336
+ setStore(
337
+ produce((draft) => {
338
+ draft.themes.system = generateSystem(colors, store.mode)
339
+ if (store.active === "system") {
340
+ draft.ready = true
341
+ }
342
+ }),
343
+ )
344
+ })
345
+ }
346
+
347
+ const renderer = useRenderer()
348
+ process.on("SIGUSR2", async () => {
349
+ renderer.clearPaletteCache()
350
+ init()
351
+ })
352
+
353
+ const values = createMemo(() => {
354
+ return resolveTheme(store.themes[store.active] ?? store.themes.opencode, store.mode)
355
+ })
356
+
357
+ const syntax = createMemo(() => generateSyntax(values()))
358
+ const subtleSyntax = createMemo(() => generateSubtleSyntax(values()))
359
+
360
+ return {
361
+ theme: new Proxy(values(), {
362
+ get(_target, prop) {
363
+ // @ts-expect-error
364
+ return values()[prop]
365
+ },
366
+ }),
367
+ get selected() {
368
+ return store.active
369
+ },
370
+ all() {
371
+ return store.themes
372
+ },
373
+ syntax,
374
+ subtleSyntax,
375
+ mode() {
376
+ return store.mode
377
+ },
378
+ setMode(mode: "dark" | "light") {
379
+ setStore("mode", mode)
380
+ kv.set("theme_mode", mode)
381
+ },
382
+ set(theme: string) {
383
+ setStore("active", theme)
384
+ kv.set("theme", theme)
385
+ },
386
+ get ready() {
387
+ return store.ready
388
+ },
389
+ }
390
+ },
391
+ })
392
+
393
+ const CUSTOM_THEME_GLOB = new Bun.Glob("themes/*.json")
394
+ async function getCustomThemes() {
395
+ const directories = [
396
+ Global.Path.config,
397
+ ...(await Array.fromAsync(
398
+ Filesystem.up({
399
+ targets: [".opencode"],
400
+ start: process.cwd(),
401
+ }),
402
+ )),
403
+ ]
404
+
405
+ const result: Record<string, ThemeJson> = {}
406
+ for (const dir of directories) {
407
+ for await (const item of CUSTOM_THEME_GLOB.scan({
408
+ absolute: true,
409
+ followSymlinks: true,
410
+ dot: true,
411
+ cwd: dir,
412
+ })) {
413
+ const name = path.basename(item, ".json")
414
+ result[name] = await Bun.file(item).json()
415
+ }
416
+ }
417
+ return result
418
+ }
419
+
420
+ function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJson {
421
+ const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0]!)
422
+ const fg = RGBA.fromHex(colors.defaultForeground ?? colors.palette[7]!)
423
+ const isDark = mode == "dark"
424
+
425
+ const col = (i: number) => {
426
+ const value = colors.palette[i]
427
+ if (value) return RGBA.fromHex(value)
428
+ return ansiToRgba(i)
429
+ }
430
+
431
+ const tint = (base: RGBA, overlay: RGBA, alpha: number) => {
432
+ const r = base.r + (overlay.r - base.r) * alpha
433
+ const g = base.g + (overlay.g - base.g) * alpha
434
+ const b = base.b + (overlay.b - base.b) * alpha
435
+ return RGBA.fromInts(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255))
436
+ }
437
+
438
+ // Generate gray scale based on terminal background
439
+ const grays = generateGrayScale(bg, isDark)
440
+ const textMuted = generateMutedTextColor(bg, isDark)
441
+
442
+ // ANSI color references
443
+ const ansiColors = {
444
+ black: col(0),
445
+ red: col(1),
446
+ green: col(2),
447
+ yellow: col(3),
448
+ blue: col(4),
449
+ magenta: col(5),
450
+ cyan: col(6),
451
+ white: col(7),
452
+ redBright: col(9),
453
+ greenBright: col(10),
454
+ }
455
+
456
+ const diffAlpha = isDark ? 0.22 : 0.14
457
+ const diffAddedBg = tint(bg, ansiColors.green, diffAlpha)
458
+ const diffRemovedBg = tint(bg, ansiColors.red, diffAlpha)
459
+ const diffAddedLineNumberBg = tint(grays[3], ansiColors.green, diffAlpha)
460
+ const diffRemovedLineNumberBg = tint(grays[3], ansiColors.red, diffAlpha)
461
+
462
+ return {
463
+ theme: {
464
+ // Primary colors using ANSI
465
+ primary: ansiColors.cyan,
466
+ secondary: ansiColors.magenta,
467
+ accent: ansiColors.cyan,
468
+
469
+ // Status colors using ANSI
470
+ error: ansiColors.red,
471
+ warning: ansiColors.yellow,
472
+ success: ansiColors.green,
473
+ info: ansiColors.cyan,
474
+
475
+ // Text colors
476
+ text: fg,
477
+ textMuted,
478
+ selectedListItemText: bg,
479
+
480
+ // Background colors
481
+ background: bg,
482
+ backgroundPanel: grays[2],
483
+ backgroundElement: grays[3],
484
+ backgroundMenu: grays[3],
485
+
486
+ // Border colors
487
+ borderSubtle: grays[6],
488
+ border: grays[7],
489
+ borderActive: grays[8],
490
+
491
+ // Diff colors
492
+ diffAdded: ansiColors.green,
493
+ diffRemoved: ansiColors.red,
494
+ diffContext: grays[7],
495
+ diffHunkHeader: grays[7],
496
+ diffHighlightAdded: ansiColors.greenBright,
497
+ diffHighlightRemoved: ansiColors.redBright,
498
+ diffAddedBg,
499
+ diffRemovedBg,
500
+ diffContextBg: grays[1],
501
+ diffLineNumber: grays[6],
502
+ diffAddedLineNumberBg,
503
+ diffRemovedLineNumberBg,
504
+
505
+ // Markdown colors
506
+ markdownText: fg,
507
+ markdownHeading: fg,
508
+ markdownLink: ansiColors.blue,
509
+ markdownLinkText: ansiColors.cyan,
510
+ markdownCode: ansiColors.green,
511
+ markdownBlockQuote: ansiColors.yellow,
512
+ markdownEmph: ansiColors.yellow,
513
+ markdownStrong: fg,
514
+ markdownHorizontalRule: grays[7],
515
+ markdownListItem: ansiColors.blue,
516
+ markdownListEnumeration: ansiColors.cyan,
517
+ markdownImage: ansiColors.blue,
518
+ markdownImageText: ansiColors.cyan,
519
+ markdownCodeBlock: fg,
520
+
521
+ // Syntax colors
522
+ syntaxComment: textMuted,
523
+ syntaxKeyword: ansiColors.magenta,
524
+ syntaxFunction: ansiColors.blue,
525
+ syntaxVariable: fg,
526
+ syntaxString: ansiColors.green,
527
+ syntaxNumber: ansiColors.yellow,
528
+ syntaxType: ansiColors.cyan,
529
+ syntaxOperator: ansiColors.cyan,
530
+ syntaxPunctuation: fg,
531
+ },
532
+ }
533
+ }
534
+
535
+ function generateGrayScale(bg: RGBA, isDark: boolean): Record<number, RGBA> {
536
+ const grays: Record<number, RGBA> = {}
537
+
538
+ // RGBA stores floats in range 0-1, convert to 0-255
539
+ const bgR = bg.r * 255
540
+ const bgG = bg.g * 255
541
+ const bgB = bg.b * 255
542
+
543
+ const luminance = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB
544
+
545
+ for (let i = 1; i <= 12; i++) {
546
+ const factor = i / 12.0
547
+
548
+ let grayValue: number
549
+ let newR: number
550
+ let newG: number
551
+ let newB: number
552
+
553
+ if (isDark) {
554
+ if (luminance < 10) {
555
+ grayValue = Math.floor(factor * 0.4 * 255)
556
+ newR = grayValue
557
+ newG = grayValue
558
+ newB = grayValue
559
+ } else {
560
+ const newLum = luminance + (255 - luminance) * factor * 0.4
561
+
562
+ const ratio = newLum / luminance
563
+ newR = Math.min(bgR * ratio, 255)
564
+ newG = Math.min(bgG * ratio, 255)
565
+ newB = Math.min(bgB * ratio, 255)
566
+ }
567
+ } else {
568
+ if (luminance > 245) {
569
+ grayValue = Math.floor(255 - factor * 0.4 * 255)
570
+ newR = grayValue
571
+ newG = grayValue
572
+ newB = grayValue
573
+ } else {
574
+ const newLum = luminance * (1 - factor * 0.4)
575
+
576
+ const ratio = newLum / luminance
577
+ newR = Math.max(bgR * ratio, 0)
578
+ newG = Math.max(bgG * ratio, 0)
579
+ newB = Math.max(bgB * ratio, 0)
580
+ }
581
+ }
582
+
583
+ grays[i] = RGBA.fromInts(Math.floor(newR), Math.floor(newG), Math.floor(newB))
584
+ }
585
+
586
+ return grays
587
+ }
588
+
589
+ function generateMutedTextColor(bg: RGBA, isDark: boolean): RGBA {
590
+ // RGBA stores floats in range 0-1, convert to 0-255
591
+ const bgR = bg.r * 255
592
+ const bgG = bg.g * 255
593
+ const bgB = bg.b * 255
594
+
595
+ const bgLum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB
596
+
597
+ let grayValue: number
598
+
599
+ if (isDark) {
600
+ if (bgLum < 10) {
601
+ // Very dark/black background
602
+ grayValue = 180 // #b4b4b4
603
+ } else {
604
+ // Scale up for lighter dark backgrounds
605
+ grayValue = Math.min(Math.floor(160 + bgLum * 0.3), 200)
606
+ }
607
+ } else {
608
+ if (bgLum > 245) {
609
+ // Very light/white background
610
+ grayValue = 75 // #4b4b4b
611
+ } else {
612
+ // Scale down for darker light backgrounds
613
+ grayValue = Math.max(Math.floor(100 - (255 - bgLum) * 0.2), 60)
614
+ }
615
+ }
616
+
617
+ return RGBA.fromInts(grayValue, grayValue, grayValue)
618
+ }
619
+
620
+ function generateSyntax(theme: Theme) {
621
+ return SyntaxStyle.fromTheme(getSyntaxRules(theme))
622
+ }
623
+
624
+ function generateSubtleSyntax(theme: Theme) {
625
+ const rules = getSyntaxRules(theme)
626
+ return SyntaxStyle.fromTheme(
627
+ rules.map((rule) => {
628
+ if (rule.style.foreground) {
629
+ const fg = rule.style.foreground
630
+ return {
631
+ ...rule,
632
+ style: {
633
+ ...rule.style,
634
+ foreground: RGBA.fromInts(
635
+ Math.round(fg.r * 255),
636
+ Math.round(fg.g * 255),
637
+ Math.round(fg.b * 255),
638
+ Math.round(theme.thinkingOpacity * 255),
639
+ ),
640
+ },
641
+ }
642
+ }
643
+ return rule
644
+ }),
645
+ )
646
+ }
647
+
648
+ function getSyntaxRules(theme: Theme) {
649
+ return [
650
+ {
651
+ scope: ["default"],
652
+ style: {
653
+ foreground: theme.text,
654
+ },
655
+ },
656
+ {
657
+ scope: ["prompt"],
658
+ style: {
659
+ foreground: theme.accent,
660
+ },
661
+ },
662
+ {
663
+ scope: ["extmark.file"],
664
+ style: {
665
+ foreground: theme.warning,
666
+ bold: true,
667
+ },
668
+ },
669
+ {
670
+ scope: ["extmark.agent"],
671
+ style: {
672
+ foreground: theme.secondary,
673
+ bold: true,
674
+ },
675
+ },
676
+ {
677
+ scope: ["extmark.paste"],
678
+ style: {
679
+ foreground: theme.background,
680
+ background: theme.warning,
681
+ bold: true,
682
+ },
683
+ },
684
+ {
685
+ scope: ["comment"],
686
+ style: {
687
+ foreground: theme.syntaxComment,
688
+ italic: true,
689
+ },
690
+ },
691
+ {
692
+ scope: ["comment.documentation"],
693
+ style: {
694
+ foreground: theme.syntaxComment,
695
+ italic: true,
696
+ },
697
+ },
698
+ {
699
+ scope: ["string", "symbol"],
700
+ style: {
701
+ foreground: theme.syntaxString,
702
+ },
703
+ },
704
+ {
705
+ scope: ["number", "boolean"],
706
+ style: {
707
+ foreground: theme.syntaxNumber,
708
+ },
709
+ },
710
+ {
711
+ scope: ["character.special"],
712
+ style: {
713
+ foreground: theme.syntaxString,
714
+ },
715
+ },
716
+ {
717
+ scope: ["keyword.return", "keyword.conditional", "keyword.repeat", "keyword.coroutine"],
718
+ style: {
719
+ foreground: theme.syntaxKeyword,
720
+ italic: true,
721
+ },
722
+ },
723
+ {
724
+ scope: ["keyword.type"],
725
+ style: {
726
+ foreground: theme.syntaxType,
727
+ bold: true,
728
+ italic: true,
729
+ },
730
+ },
731
+ {
732
+ scope: ["keyword.function", "function.method"],
733
+ style: {
734
+ foreground: theme.syntaxFunction,
735
+ },
736
+ },
737
+ {
738
+ scope: ["keyword"],
739
+ style: {
740
+ foreground: theme.syntaxKeyword,
741
+ italic: true,
742
+ },
743
+ },
744
+ {
745
+ scope: ["keyword.import"],
746
+ style: {
747
+ foreground: theme.syntaxKeyword,
748
+ },
749
+ },
750
+ {
751
+ scope: ["operator", "keyword.operator", "punctuation.delimiter"],
752
+ style: {
753
+ foreground: theme.syntaxOperator,
754
+ },
755
+ },
756
+ {
757
+ scope: ["keyword.conditional.ternary"],
758
+ style: {
759
+ foreground: theme.syntaxOperator,
760
+ },
761
+ },
762
+ {
763
+ scope: ["variable", "variable.parameter", "function.method.call", "function.call"],
764
+ style: {
765
+ foreground: theme.syntaxVariable,
766
+ },
767
+ },
768
+ {
769
+ scope: ["variable.member", "function", "constructor"],
770
+ style: {
771
+ foreground: theme.syntaxFunction,
772
+ },
773
+ },
774
+ {
775
+ scope: ["type", "module"],
776
+ style: {
777
+ foreground: theme.syntaxType,
778
+ },
779
+ },
780
+ {
781
+ scope: ["constant"],
782
+ style: {
783
+ foreground: theme.syntaxNumber,
784
+ },
785
+ },
786
+ {
787
+ scope: ["property"],
788
+ style: {
789
+ foreground: theme.syntaxVariable,
790
+ },
791
+ },
792
+ {
793
+ scope: ["class"],
794
+ style: {
795
+ foreground: theme.syntaxType,
796
+ },
797
+ },
798
+ {
799
+ scope: ["parameter"],
800
+ style: {
801
+ foreground: theme.syntaxVariable,
802
+ },
803
+ },
804
+ {
805
+ scope: ["punctuation", "punctuation.bracket"],
806
+ style: {
807
+ foreground: theme.syntaxPunctuation,
808
+ },
809
+ },
810
+ {
811
+ scope: ["variable.builtin", "type.builtin", "function.builtin", "module.builtin", "constant.builtin"],
812
+ style: {
813
+ foreground: theme.error,
814
+ },
815
+ },
816
+ {
817
+ scope: ["variable.super"],
818
+ style: {
819
+ foreground: theme.error,
820
+ },
821
+ },
822
+ {
823
+ scope: ["string.escape", "string.regexp"],
824
+ style: {
825
+ foreground: theme.syntaxKeyword,
826
+ },
827
+ },
828
+ {
829
+ scope: ["keyword.directive"],
830
+ style: {
831
+ foreground: theme.syntaxKeyword,
832
+ italic: true,
833
+ },
834
+ },
835
+ {
836
+ scope: ["punctuation.special"],
837
+ style: {
838
+ foreground: theme.syntaxOperator,
839
+ },
840
+ },
841
+ {
842
+ scope: ["keyword.modifier"],
843
+ style: {
844
+ foreground: theme.syntaxKeyword,
845
+ italic: true,
846
+ },
847
+ },
848
+ {
849
+ scope: ["keyword.exception"],
850
+ style: {
851
+ foreground: theme.syntaxKeyword,
852
+ italic: true,
853
+ },
854
+ },
855
+ // Markdown specific styles
856
+ {
857
+ scope: ["markup.heading"],
858
+ style: {
859
+ foreground: theme.markdownHeading,
860
+ bold: true,
861
+ },
862
+ },
863
+ {
864
+ scope: ["markup.heading.1"],
865
+ style: {
866
+ foreground: theme.markdownHeading,
867
+ bold: true,
868
+ },
869
+ },
870
+ {
871
+ scope: ["markup.heading.2"],
872
+ style: {
873
+ foreground: theme.markdownHeading,
874
+ bold: true,
875
+ },
876
+ },
877
+ {
878
+ scope: ["markup.heading.3"],
879
+ style: {
880
+ foreground: theme.markdownHeading,
881
+ bold: true,
882
+ },
883
+ },
884
+ {
885
+ scope: ["markup.heading.4"],
886
+ style: {
887
+ foreground: theme.markdownHeading,
888
+ bold: true,
889
+ },
890
+ },
891
+ {
892
+ scope: ["markup.heading.5"],
893
+ style: {
894
+ foreground: theme.markdownHeading,
895
+ bold: true,
896
+ },
897
+ },
898
+ {
899
+ scope: ["markup.heading.6"],
900
+ style: {
901
+ foreground: theme.markdownHeading,
902
+ bold: true,
903
+ },
904
+ },
905
+ {
906
+ scope: ["markup.bold", "markup.strong"],
907
+ style: {
908
+ foreground: theme.markdownStrong,
909
+ bold: true,
910
+ },
911
+ },
912
+ {
913
+ scope: ["markup.italic"],
914
+ style: {
915
+ foreground: theme.markdownEmph,
916
+ italic: true,
917
+ },
918
+ },
919
+ {
920
+ scope: ["markup.list"],
921
+ style: {
922
+ foreground: theme.markdownListItem,
923
+ },
924
+ },
925
+ {
926
+ scope: ["markup.quote"],
927
+ style: {
928
+ foreground: theme.markdownBlockQuote,
929
+ italic: true,
930
+ },
931
+ },
932
+ {
933
+ scope: ["markup.raw", "markup.raw.block"],
934
+ style: {
935
+ foreground: theme.markdownCode,
936
+ },
937
+ },
938
+ {
939
+ scope: ["markup.raw.inline"],
940
+ style: {
941
+ foreground: theme.markdownCode,
942
+ background: theme.background,
943
+ },
944
+ },
945
+ {
946
+ scope: ["markup.link"],
947
+ style: {
948
+ foreground: theme.markdownLink,
949
+ underline: true,
950
+ },
951
+ },
952
+ {
953
+ scope: ["markup.link.label"],
954
+ style: {
955
+ foreground: theme.markdownLinkText,
956
+ underline: true,
957
+ },
958
+ },
959
+ {
960
+ scope: ["markup.link.url"],
961
+ style: {
962
+ foreground: theme.markdownLink,
963
+ underline: true,
964
+ },
965
+ },
966
+ {
967
+ scope: ["label"],
968
+ style: {
969
+ foreground: theme.markdownLinkText,
970
+ },
971
+ },
972
+ {
973
+ scope: ["spell", "nospell"],
974
+ style: {
975
+ foreground: theme.text,
976
+ },
977
+ },
978
+ {
979
+ scope: ["conceal"],
980
+ style: {
981
+ foreground: theme.textMuted,
982
+ },
983
+ },
984
+ // Additional common highlight groups
985
+ {
986
+ scope: ["string.special", "string.special.url"],
987
+ style: {
988
+ foreground: theme.markdownLink,
989
+ underline: true,
990
+ },
991
+ },
992
+ {
993
+ scope: ["character"],
994
+ style: {
995
+ foreground: theme.syntaxString,
996
+ },
997
+ },
998
+ {
999
+ scope: ["float"],
1000
+ style: {
1001
+ foreground: theme.syntaxNumber,
1002
+ },
1003
+ },
1004
+ {
1005
+ scope: ["comment.error"],
1006
+ style: {
1007
+ foreground: theme.error,
1008
+ italic: true,
1009
+ bold: true,
1010
+ },
1011
+ },
1012
+ {
1013
+ scope: ["comment.warning"],
1014
+ style: {
1015
+ foreground: theme.warning,
1016
+ italic: true,
1017
+ bold: true,
1018
+ },
1019
+ },
1020
+ {
1021
+ scope: ["comment.todo", "comment.note"],
1022
+ style: {
1023
+ foreground: theme.info,
1024
+ italic: true,
1025
+ bold: true,
1026
+ },
1027
+ },
1028
+ {
1029
+ scope: ["namespace"],
1030
+ style: {
1031
+ foreground: theme.syntaxType,
1032
+ },
1033
+ },
1034
+ {
1035
+ scope: ["field"],
1036
+ style: {
1037
+ foreground: theme.syntaxVariable,
1038
+ },
1039
+ },
1040
+ {
1041
+ scope: ["type.definition"],
1042
+ style: {
1043
+ foreground: theme.syntaxType,
1044
+ bold: true,
1045
+ },
1046
+ },
1047
+ {
1048
+ scope: ["keyword.export"],
1049
+ style: {
1050
+ foreground: theme.syntaxKeyword,
1051
+ },
1052
+ },
1053
+ {
1054
+ scope: ["attribute", "annotation"],
1055
+ style: {
1056
+ foreground: theme.warning,
1057
+ },
1058
+ },
1059
+ {
1060
+ scope: ["tag"],
1061
+ style: {
1062
+ foreground: theme.error,
1063
+ },
1064
+ },
1065
+ {
1066
+ scope: ["tag.attribute"],
1067
+ style: {
1068
+ foreground: theme.syntaxKeyword,
1069
+ },
1070
+ },
1071
+ {
1072
+ scope: ["tag.delimiter"],
1073
+ style: {
1074
+ foreground: theme.syntaxOperator,
1075
+ },
1076
+ },
1077
+ {
1078
+ scope: ["markup.strikethrough"],
1079
+ style: {
1080
+ foreground: theme.textMuted,
1081
+ },
1082
+ },
1083
+ {
1084
+ scope: ["markup.underline"],
1085
+ style: {
1086
+ foreground: theme.text,
1087
+ underline: true,
1088
+ },
1089
+ },
1090
+ {
1091
+ scope: ["markup.list.checked"],
1092
+ style: {
1093
+ foreground: theme.success,
1094
+ },
1095
+ },
1096
+ {
1097
+ scope: ["markup.list.unchecked"],
1098
+ style: {
1099
+ foreground: theme.textMuted,
1100
+ },
1101
+ },
1102
+ {
1103
+ scope: ["diff.plus"],
1104
+ style: {
1105
+ foreground: theme.diffAdded,
1106
+ background: theme.diffAddedBg,
1107
+ },
1108
+ },
1109
+ {
1110
+ scope: ["diff.minus"],
1111
+ style: {
1112
+ foreground: theme.diffRemoved,
1113
+ background: theme.diffRemovedBg,
1114
+ },
1115
+ },
1116
+ {
1117
+ scope: ["diff.delta"],
1118
+ style: {
1119
+ foreground: theme.diffContext,
1120
+ background: theme.diffContextBg,
1121
+ },
1122
+ },
1123
+ {
1124
+ scope: ["error"],
1125
+ style: {
1126
+ foreground: theme.error,
1127
+ bold: true,
1128
+ },
1129
+ },
1130
+ {
1131
+ scope: ["warning"],
1132
+ style: {
1133
+ foreground: theme.warning,
1134
+ bold: true,
1135
+ },
1136
+ },
1137
+ {
1138
+ scope: ["info"],
1139
+ style: {
1140
+ foreground: theme.info,
1141
+ },
1142
+ },
1143
+ {
1144
+ scope: ["debug"],
1145
+ style: {
1146
+ foreground: theme.textMuted,
1147
+ },
1148
+ },
1149
+ ]
1150
+ }