@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,86 @@
1
+ import { Global } from "../global"
2
+ import path from "path"
3
+ import z from "zod"
4
+ import { data } from "./models-macro" with { type: "macro" }
5
+
6
+ export namespace ModelsDev {
7
+ const filepath = path.join(Global.Path.cache, "models.json")
8
+
9
+ export const Model = z.object({
10
+ id: z.string(),
11
+ name: z.string(),
12
+ family: z.string().optional(),
13
+ release_date: z.string(),
14
+ attachment: z.boolean(),
15
+ reasoning: z.boolean(),
16
+ temperature: z.boolean(),
17
+ tool_call: z.boolean(),
18
+ interleaved: z
19
+ .union([
20
+ z.literal(true),
21
+ z
22
+ .object({
23
+ field: z.enum(["reasoning_content", "reasoning_details"]),
24
+ })
25
+ .strict(),
26
+ ])
27
+ .optional(),
28
+ cost: z
29
+ .object({
30
+ input: z.number(),
31
+ output: z.number(),
32
+ cache_read: z.number().optional(),
33
+ cache_write: z.number().optional(),
34
+ context_over_200k: z
35
+ .object({
36
+ input: z.number(),
37
+ output: z.number(),
38
+ cache_read: z.number().optional(),
39
+ cache_write: z.number().optional(),
40
+ })
41
+ .optional(),
42
+ })
43
+ .optional(),
44
+ limit: z.object({
45
+ context: z.number(),
46
+ output: z.number(),
47
+ }),
48
+ modalities: z
49
+ .object({
50
+ input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
51
+ output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
52
+ })
53
+ .optional(),
54
+ experimental: z.boolean().optional(),
55
+ status: z.enum(["alpha", "beta", "deprecated"]).optional(),
56
+ options: z.record(z.string(), z.any()),
57
+ headers: z.record(z.string(), z.string()).optional(),
58
+ provider: z.object({ npm: z.string() }).optional(),
59
+ variants: z.record(z.string(), z.record(z.string(), z.any())).optional(),
60
+ })
61
+ export type Model = z.infer<typeof Model>
62
+
63
+ export const Provider = z.object({
64
+ api: z.string().optional(),
65
+ name: z.string(),
66
+ env: z.array(z.string()),
67
+ id: z.string(),
68
+ npm: z.string().optional(),
69
+ models: z.record(z.string(), Model),
70
+ })
71
+
72
+ export type Provider = z.infer<typeof Provider>
73
+
74
+ export async function get() {
75
+ refresh()
76
+ const file = Bun.file(filepath)
77
+ const result = await file.json().catch(() => {})
78
+ if (result) return result as Record<string, Provider>
79
+ const json = await data()
80
+ return JSON.parse(json) as Record<string, Provider>
81
+ }
82
+
83
+ export async function refresh() {
84
+ // Disabled for Tinfoil-only fork - models are fetched from Tinfoil API
85
+ }
86
+ }
@@ -0,0 +1,429 @@
1
+ import z from "zod"
2
+ import fuzzysort from "fuzzysort"
3
+ import { Config } from "../config/config"
4
+ import { sortBy } from "remeda"
5
+ import { NoSuchModelError, type Provider as SDK } from "ai"
6
+ import { Log } from "../util/log"
7
+ import { NamedError } from "@opencode-ai/util/error"
8
+ import { Auth } from "../auth"
9
+ import { Env } from "../env"
10
+ import { Instance } from "../project/instance"
11
+ import { SecureClient } from "tinfoil"
12
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
13
+ import type { LanguageModelV2 } from "@ai-sdk/provider"
14
+
15
+ export namespace Provider {
16
+ const log = Log.create({ service: "provider" })
17
+
18
+ const TINFOIL_API_URL = "https://inference.tinfoil.sh/v1"
19
+
20
+ interface TinfoilState {
21
+ secureClient: SecureClient
22
+ apiKey: string
23
+ baseURL: string
24
+ }
25
+
26
+ let tinfoilState: TinfoilState | null = null
27
+
28
+ async function initTinfoil(): Promise<TinfoilState | null> {
29
+ if (tinfoilState) return tinfoilState
30
+
31
+ const config = await Config.get()
32
+ const providerConfig = config.provider?.["tinfoil"]
33
+
34
+ const apiKey = await (async () => {
35
+ const env = Env.all()
36
+ const envKeys = providerConfig?.env ?? ["TINFOIL_API_KEY"]
37
+ const envKey = envKeys.map((item: string) => env[item]).find(Boolean)
38
+ if (envKey) return envKey
39
+ const auth = await Auth.get("tinfoil")
40
+ if (auth?.type === "api") return auth.key
41
+ if (providerConfig?.options?.apiKey) return providerConfig.options.apiKey
42
+ return undefined
43
+ })()
44
+
45
+ if (!apiKey) return null
46
+
47
+ const baseURL = providerConfig?.options?.baseURL
48
+ const enclaveURL = providerConfig?.options?.enclaveURL
49
+ const configRepo = providerConfig?.options?.configRepo
50
+ const transport = providerConfig?.options?.transport
51
+
52
+ const secureClient = new SecureClient({
53
+ baseURL,
54
+ enclaveURL,
55
+ configRepo,
56
+ transport: transport ?? "tls",
57
+ })
58
+
59
+ await secureClient.ready()
60
+
61
+ const finalBaseURL = baseURL || secureClient.getBaseURL() || TINFOIL_API_URL
62
+
63
+ tinfoilState = {
64
+ secureClient,
65
+ apiKey,
66
+ baseURL: finalBaseURL,
67
+ }
68
+
69
+ return tinfoilState
70
+ }
71
+
72
+ interface TinfoilModel {
73
+ id: string
74
+ object: string
75
+ created: number
76
+ owned_by: string
77
+ type: string
78
+ context_window?: number
79
+ multimodal?: boolean
80
+ }
81
+
82
+ interface TinfoilModelsResponse {
83
+ object: string
84
+ data: TinfoilModel[]
85
+ }
86
+
87
+ async function fetchTinfoilModels(state: TinfoilState): Promise<Record<string, Model>> {
88
+ try {
89
+ const response = await state.secureClient.fetch(`${state.baseURL}/models`, {
90
+ headers: {
91
+ Authorization: `Bearer ${state.apiKey}`,
92
+ },
93
+ })
94
+
95
+ if (!response.ok) {
96
+ log.error("Failed to fetch tinfoil models", { status: response.status })
97
+ return {}
98
+ }
99
+
100
+ const data = (await response.json()) as TinfoilModelsResponse
101
+ const models: Record<string, Model> = {}
102
+
103
+ // Only include chat and code models
104
+ const supportedTypes = ["chat", "code"]
105
+
106
+ for (const model of data.data) {
107
+ if (!supportedTypes.includes(model.type)) {
108
+ continue
109
+ }
110
+
111
+ const supportsImage = model.multimodal === true
112
+
113
+ models[model.id] = {
114
+ id: model.id,
115
+ providerID: "tinfoil",
116
+ name: model.id,
117
+ api: {
118
+ id: model.id,
119
+ url: state.baseURL,
120
+ npm: "tinfoil",
121
+ },
122
+ status: "active",
123
+ headers: {},
124
+ options: {},
125
+ cost: {
126
+ input: 0,
127
+ output: 0,
128
+ cache: { read: 0, write: 0 },
129
+ },
130
+ limit: {
131
+ context: model.context_window ?? 128000,
132
+ output: 4096,
133
+ },
134
+ capabilities: {
135
+ temperature: true,
136
+ reasoning: false,
137
+ attachment: supportsImage,
138
+ toolcall: true,
139
+ input: { text: true, audio: false, image: supportsImage, video: false, pdf: false },
140
+ output: { text: true, audio: false, image: false, video: false, pdf: false },
141
+ interleaved: false,
142
+ },
143
+ release_date: new Date().toISOString().split("T")[0],
144
+ }
145
+ }
146
+
147
+ return models
148
+ } catch (e) {
149
+ log.error("Error fetching tinfoil models", { error: e })
150
+ return {}
151
+ }
152
+ }
153
+
154
+ export const Model = z
155
+ .object({
156
+ id: z.string(),
157
+ providerID: z.string(),
158
+ api: z.object({
159
+ id: z.string(),
160
+ url: z.string(),
161
+ npm: z.string(),
162
+ }),
163
+ name: z.string(),
164
+ family: z.string().optional(),
165
+ capabilities: z.object({
166
+ temperature: z.boolean(),
167
+ reasoning: z.boolean(),
168
+ attachment: z.boolean(),
169
+ toolcall: z.boolean(),
170
+ input: z.object({
171
+ text: z.boolean(),
172
+ audio: z.boolean(),
173
+ image: z.boolean(),
174
+ video: z.boolean(),
175
+ pdf: z.boolean(),
176
+ }),
177
+ output: z.object({
178
+ text: z.boolean(),
179
+ audio: z.boolean(),
180
+ image: z.boolean(),
181
+ video: z.boolean(),
182
+ pdf: z.boolean(),
183
+ }),
184
+ interleaved: z.union([
185
+ z.boolean(),
186
+ z.object({
187
+ field: z.enum(["reasoning_content", "reasoning_details"]),
188
+ }),
189
+ ]),
190
+ }),
191
+ cost: z.object({
192
+ input: z.number(),
193
+ output: z.number(),
194
+ cache: z.object({
195
+ read: z.number(),
196
+ write: z.number(),
197
+ }),
198
+ experimentalOver200K: z
199
+ .object({
200
+ input: z.number(),
201
+ output: z.number(),
202
+ cache: z.object({
203
+ read: z.number(),
204
+ write: z.number(),
205
+ }),
206
+ })
207
+ .optional(),
208
+ }),
209
+ limit: z.object({
210
+ context: z.number(),
211
+ output: z.number(),
212
+ }),
213
+ status: z.enum(["alpha", "beta", "deprecated", "active"]),
214
+ options: z.record(z.string(), z.any()),
215
+ headers: z.record(z.string(), z.string()),
216
+ release_date: z.string(),
217
+ variants: z.record(z.string(), z.record(z.string(), z.any())).optional(),
218
+ })
219
+ .meta({
220
+ ref: "Model",
221
+ })
222
+ export type Model = z.infer<typeof Model>
223
+
224
+ export const Info = z
225
+ .object({
226
+ id: z.string(),
227
+ name: z.string(),
228
+ source: z.enum(["env", "config", "custom", "api"]),
229
+ env: z.string().array(),
230
+ key: z.string().optional(),
231
+ options: z.record(z.string(), z.any()),
232
+ models: z.record(z.string(), Model),
233
+ })
234
+ .meta({
235
+ ref: "Provider",
236
+ })
237
+ export type Info = z.infer<typeof Info>
238
+
239
+ // Simplified state for tinfoil-only provider
240
+ const state = Instance.state(async () => {
241
+ using _ = log.time("state")
242
+
243
+ const tinfoil = await initTinfoil()
244
+ if (!tinfoil) {
245
+ log.warn("Tinfoil not configured - no API key found")
246
+ return {
247
+ models: new Map<string, LanguageModelV2>(),
248
+ providers: {} as { [providerID: string]: Info },
249
+ sdk: new Map<number, SDK>(),
250
+ }
251
+ }
252
+
253
+ const models = await fetchTinfoilModels(tinfoil)
254
+
255
+ const provider: Info = {
256
+ id: "tinfoil",
257
+ name: "Tinfoil",
258
+ source: "env",
259
+ env: ["TINFOIL_API_KEY"],
260
+ key: tinfoil.apiKey,
261
+ options: {
262
+ baseURL: tinfoil.baseURL,
263
+ apiKey: tinfoil.apiKey,
264
+ fetch: tinfoil.secureClient.fetch,
265
+ },
266
+ models,
267
+ }
268
+
269
+ log.info("found", { providerID: "tinfoil", modelCount: Object.keys(models).length })
270
+
271
+ return {
272
+ models: new Map<string, LanguageModelV2>(),
273
+ providers: { tinfoil: provider },
274
+ sdk: new Map<number, SDK>(),
275
+ }
276
+ })
277
+
278
+ export async function list() {
279
+ return state().then((s) => s.providers)
280
+ }
281
+
282
+ async function getSDK(model: Model): Promise<SDK> {
283
+ const s = await state()
284
+ const provider = s.providers[model.providerID]
285
+ if (!provider) throw new InitError({ providerID: model.providerID })
286
+
287
+ const options = { ...provider.options }
288
+ options["includeUsage"] = true
289
+
290
+ const key = Bun.hash.xxHash32(JSON.stringify({ options }))
291
+ const existing = s.sdk.get(key)
292
+ if (existing) return existing
293
+
294
+ const customFetch = options["fetch"]
295
+
296
+ const loaded = createOpenAICompatible({
297
+ name: "tinfoil",
298
+ baseURL: options["baseURL"] as string,
299
+ apiKey: options["apiKey"] as string,
300
+ fetch: customFetch ?? fetch,
301
+ })
302
+ s.sdk.set(key, loaded)
303
+ return loaded as SDK
304
+ }
305
+
306
+ export async function getProvider(providerID: string) {
307
+ return state().then((s) => s.providers[providerID])
308
+ }
309
+
310
+ export async function getModel(providerID: string, modelID: string) {
311
+ const s = await state()
312
+ const provider = s.providers[providerID]
313
+ if (!provider) {
314
+ const availableProviders = Object.keys(s.providers)
315
+ const matches = fuzzysort.go(providerID, availableProviders, { limit: 3, threshold: -10000 })
316
+ const suggestions = matches.map((m) => m.target)
317
+ throw new ModelNotFoundError({ providerID, modelID, suggestions })
318
+ }
319
+
320
+ const info = provider.models[modelID]
321
+ if (!info) {
322
+ const availableModels = Object.keys(provider.models)
323
+ const matches = fuzzysort.go(modelID, availableModels, { limit: 3, threshold: -10000 })
324
+ const suggestions = matches.map((m) => m.target)
325
+ throw new ModelNotFoundError({ providerID, modelID, suggestions })
326
+ }
327
+ return info
328
+ }
329
+
330
+ export async function getLanguage(model: Model): Promise<LanguageModelV2> {
331
+ const s = await state()
332
+ const key = `${model.providerID}/${model.id}`
333
+ if (s.models.has(key)) return s.models.get(key)!
334
+
335
+ const sdk = await getSDK(model)
336
+
337
+ try {
338
+ const language = sdk.languageModel(model.api.id) as LanguageModelV2
339
+ s.models.set(key, language)
340
+ return language
341
+ } catch (e) {
342
+ if (e instanceof NoSuchModelError)
343
+ throw new ModelNotFoundError(
344
+ {
345
+ modelID: model.id,
346
+ providerID: model.providerID,
347
+ },
348
+ { cause: e },
349
+ )
350
+ throw e
351
+ }
352
+ }
353
+
354
+ export async function closest(providerID: string, query: string[]) {
355
+ const s = await state()
356
+ const provider = s.providers[providerID]
357
+ if (!provider) return undefined
358
+ for (const item of query) {
359
+ for (const modelID of Object.keys(provider.models)) {
360
+ if (modelID.includes(item))
361
+ return {
362
+ providerID,
363
+ modelID,
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ export async function getSmallModel(_providerID: string) {
370
+ const cfg = await Config.get()
371
+
372
+ if (cfg.small_model) {
373
+ const parsed = parseModel(cfg.small_model)
374
+ return getModel(parsed.providerID, parsed.modelID)
375
+ }
376
+
377
+ const provider = await state().then((s) => s.providers["tinfoil"])
378
+ if (provider) {
379
+ const models = Object.keys(provider.models)
380
+ if (models.length > 0) {
381
+ return getModel("tinfoil", models[0])
382
+ }
383
+ }
384
+
385
+ return undefined
386
+ }
387
+
388
+ export function sort(models: Model[]) {
389
+ return sortBy(models, [(model) => model.id, "asc"])
390
+ }
391
+
392
+ export async function defaultModel() {
393
+ const cfg = await Config.get()
394
+ if (cfg.model) return parseModel(cfg.model)
395
+
396
+ const provider = await list().then((val) => val["tinfoil"])
397
+ if (!provider) throw new Error("Tinfoil provider not configured. Set TINFOIL_API_KEY environment variable.")
398
+ const [model] = sort(Object.values(provider.models))
399
+ if (!model) throw new Error("No models available from Tinfoil")
400
+ return {
401
+ providerID: "tinfoil",
402
+ modelID: model.id,
403
+ }
404
+ }
405
+
406
+ export function parseModel(model: string) {
407
+ const [providerID, ...rest] = model.split("/")
408
+ return {
409
+ providerID: providerID,
410
+ modelID: rest.join("/"),
411
+ }
412
+ }
413
+
414
+ export const ModelNotFoundError = NamedError.create(
415
+ "ProviderModelNotFoundError",
416
+ z.object({
417
+ providerID: z.string(),
418
+ modelID: z.string(),
419
+ suggestions: z.array(z.string()).optional(),
420
+ }),
421
+ )
422
+
423
+ export const InitError = NamedError.create(
424
+ "ProviderInitError",
425
+ z.object({
426
+ providerID: z.string(),
427
+ }),
428
+ )
429
+ }
@@ -0,0 +1,5 @@
1
+ This is a temporary package used primarily for GitHub Copilot compatibility.
2
+
3
+ Avoid making changes to these files unless you only want to affect the Copilot provider.
4
+
5
+ Also, this should ONLY be used for the Copilot provider.
@@ -0,0 +1,2 @@
1
+ export { createOpenaiCompatible, openaiCompatible } from "./openai-compatible-provider"
2
+ export type { OpenaiCompatibleProvider, OpenaiCompatibleProviderSettings } from "./openai-compatible-provider"
@@ -0,0 +1,100 @@
1
+ import type { LanguageModelV2 } from "@ai-sdk/provider"
2
+ import { OpenAICompatibleChatLanguageModel } from "@ai-sdk/openai-compatible"
3
+ import { type FetchFunction, withoutTrailingSlash, withUserAgentSuffix } from "@ai-sdk/provider-utils"
4
+ import { OpenAIResponsesLanguageModel } from "./responses/openai-responses-language-model"
5
+
6
+ // Import the version or define it
7
+ const VERSION = "0.1.0"
8
+
9
+ export type OpenaiCompatibleModelId = string
10
+
11
+ export interface OpenaiCompatibleProviderSettings {
12
+ /**
13
+ * API key for authenticating requests.
14
+ */
15
+ apiKey?: string
16
+
17
+ /**
18
+ * Base URL for the OpenAI Compatible API calls.
19
+ */
20
+ baseURL?: string
21
+
22
+ /**
23
+ * Name of the provider.
24
+ */
25
+ name?: string
26
+
27
+ /**
28
+ * Custom headers to include in the requests.
29
+ */
30
+ headers?: Record<string, string>
31
+
32
+ /**
33
+ * Custom fetch implementation.
34
+ */
35
+ fetch?: FetchFunction
36
+ }
37
+
38
+ export interface OpenaiCompatibleProvider {
39
+ (modelId: OpenaiCompatibleModelId): LanguageModelV2
40
+ chat(modelId: OpenaiCompatibleModelId): LanguageModelV2
41
+ responses(modelId: OpenaiCompatibleModelId): LanguageModelV2
42
+ languageModel(modelId: OpenaiCompatibleModelId): LanguageModelV2
43
+
44
+ // embeddingModel(modelId: any): EmbeddingModelV2
45
+
46
+ // imageModel(modelId: any): ImageModelV2
47
+ }
48
+
49
+ /**
50
+ * Create an OpenAI Compatible provider instance.
51
+ */
52
+ export function createOpenaiCompatible(options: OpenaiCompatibleProviderSettings = {}): OpenaiCompatibleProvider {
53
+ const baseURL = withoutTrailingSlash(options.baseURL ?? "https://api.openai.com/v1")
54
+
55
+ if (!baseURL) {
56
+ throw new Error("baseURL is required")
57
+ }
58
+
59
+ // Merge headers: defaults first, then user overrides
60
+ const headers = {
61
+ // Default OpenAI Compatible headers (can be overridden by user)
62
+ ...(options.apiKey && { Authorization: `Bearer ${options.apiKey}` }),
63
+ ...options.headers,
64
+ }
65
+
66
+ const getHeaders = () => withUserAgentSuffix(headers, `ai-sdk/openai-compatible/${VERSION}`)
67
+
68
+ const createChatModel = (modelId: OpenaiCompatibleModelId) => {
69
+ return new OpenAICompatibleChatLanguageModel(modelId, {
70
+ provider: `${options.name ?? "openai-compatible"}.chat`,
71
+ headers: getHeaders,
72
+ url: ({ path }) => `${baseURL}${path}`,
73
+ fetch: options.fetch,
74
+ })
75
+ }
76
+
77
+ const createResponsesModel = (modelId: OpenaiCompatibleModelId) => {
78
+ return new OpenAIResponsesLanguageModel(modelId, {
79
+ provider: `${options.name ?? "openai-compatible"}.responses`,
80
+ headers: getHeaders,
81
+ url: ({ path }) => `${baseURL}${path}`,
82
+ fetch: options.fetch,
83
+ })
84
+ }
85
+
86
+ const createLanguageModel = (modelId: OpenaiCompatibleModelId) => createChatModel(modelId)
87
+
88
+ const provider = function (modelId: OpenaiCompatibleModelId) {
89
+ return createChatModel(modelId)
90
+ }
91
+
92
+ provider.languageModel = createLanguageModel
93
+ provider.chat = createChatModel
94
+ provider.responses = createResponsesModel
95
+
96
+ return provider as OpenaiCompatibleProvider
97
+ }
98
+
99
+ // Default OpenAI Compatible provider instance
100
+ export const openaiCompatible = createOpenaiCompatible()