@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.
- package/AGENTS.md +27 -0
- package/Dockerfile +18 -0
- package/README.md +15 -0
- package/bin/opencode +88 -0
- package/bunfig.toml +7 -0
- package/package.json +134 -0
- package/parsers-config.ts +253 -0
- package/script/build.ts +176 -0
- package/script/postinstall.mjs +122 -0
- package/script/publish-registries.ts +187 -0
- package/script/publish.ts +70 -0
- package/script/schema.ts +47 -0
- package/src/acp/README.md +164 -0
- package/src/acp/agent.ts +1124 -0
- package/src/acp/session.ts +101 -0
- package/src/acp/types.ts +22 -0
- package/src/agent/agent.ts +284 -0
- package/src/agent/generate.txt +75 -0
- package/src/agent/prompt/compaction.txt +12 -0
- package/src/agent/prompt/explore.txt +18 -0
- package/src/agent/prompt/summary.txt +11 -0
- package/src/agent/prompt/title.txt +43 -0
- package/src/auth/index.ts +73 -0
- package/src/bun/index.ts +130 -0
- package/src/bus/bus-event.ts +43 -0
- package/src/bus/global.ts +10 -0
- package/src/bus/index.ts +105 -0
- package/src/cli/bootstrap.ts +17 -0
- package/src/cli/cmd/acp.ts +69 -0
- package/src/cli/cmd/agent.ts +257 -0
- package/src/cli/cmd/auth.ts +400 -0
- package/src/cli/cmd/cmd.ts +7 -0
- package/src/cli/cmd/debug/agent.ts +29 -0
- package/src/cli/cmd/debug/config.ts +16 -0
- package/src/cli/cmd/debug/file.ts +97 -0
- package/src/cli/cmd/debug/index.ts +48 -0
- package/src/cli/cmd/debug/lsp.ts +52 -0
- package/src/cli/cmd/debug/ripgrep.ts +87 -0
- package/src/cli/cmd/debug/scrap.ts +16 -0
- package/src/cli/cmd/debug/skill.ts +16 -0
- package/src/cli/cmd/debug/snapshot.ts +52 -0
- package/src/cli/cmd/export.ts +88 -0
- package/src/cli/cmd/generate.ts +38 -0
- package/src/cli/cmd/github.ts +1546 -0
- package/src/cli/cmd/import.ts +98 -0
- package/src/cli/cmd/mcp.ts +671 -0
- package/src/cli/cmd/models.ts +77 -0
- package/src/cli/cmd/pr.ts +112 -0
- package/src/cli/cmd/run.ts +395 -0
- package/src/cli/cmd/serve.ts +16 -0
- package/src/cli/cmd/session.ts +135 -0
- package/src/cli/cmd/stats.ts +402 -0
- package/src/cli/cmd/tui/app.tsx +743 -0
- package/src/cli/cmd/tui/attach.ts +31 -0
- package/src/cli/cmd/tui/component/border.tsx +21 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-model.tsx +168 -0
- package/src/cli/cmd/tui/component/dialog-provider.tsx +47 -0
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +115 -0
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
- package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
- package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
- package/src/cli/cmd/tui/component/logo.tsx +33 -0
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +718 -0
- package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
- package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
- package/src/cli/cmd/tui/component/prompt/index.tsx +1083 -0
- package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
- package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
- package/src/cli/cmd/tui/component/tips.ts +103 -0
- package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
- package/src/cli/cmd/tui/context/args.tsx +14 -0
- package/src/cli/cmd/tui/context/directory.ts +13 -0
- package/src/cli/cmd/tui/context/exit.tsx +23 -0
- package/src/cli/cmd/tui/context/helper.tsx +25 -0
- package/src/cli/cmd/tui/context/keybind.tsx +101 -0
- package/src/cli/cmd/tui/context/kv.tsx +49 -0
- package/src/cli/cmd/tui/context/local.tsx +393 -0
- package/src/cli/cmd/tui/context/prompt.tsx +18 -0
- package/src/cli/cmd/tui/context/route.tsx +46 -0
- package/src/cli/cmd/tui/context/sdk.tsx +94 -0
- package/src/cli/cmd/tui/context/sync.tsx +427 -0
- package/src/cli/cmd/tui/context/theme/aura.json +69 -0
- package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
- package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
- package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
- package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
- package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
- package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
- package/src/cli/cmd/tui/context/theme/github.json +233 -0
- package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
- package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
- package/src/cli/cmd/tui/context/theme/material.json +235 -0
- package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
- package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
- package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
- package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
- package/src/cli/cmd/tui/context/theme/nord.json +223 -0
- package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
- package/src/cli/cmd/tui/context/theme/orng.json +249 -0
- package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
- package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
- package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
- package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
- package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
- package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
- package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
- package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
- package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
- package/src/cli/cmd/tui/context/theme.tsx +1150 -0
- package/src/cli/cmd/tui/event.ts +46 -0
- package/src/cli/cmd/tui/routes/home.tsx +138 -0
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
- package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
- package/src/cli/cmd/tui/routes/session/header.tsx +105 -0
- package/src/cli/cmd/tui/routes/session/index.tsx +1897 -0
- package/src/cli/cmd/tui/routes/session/permission.tsx +416 -0
- package/src/cli/cmd/tui/routes/session/question.tsx +368 -0
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +279 -0
- package/src/cli/cmd/tui/spawn.ts +46 -0
- package/src/cli/cmd/tui/thread.ts +174 -0
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
- package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
- package/src/cli/cmd/tui/ui/dialog-select.tsx +345 -0
- package/src/cli/cmd/tui/ui/dialog.tsx +172 -0
- package/src/cli/cmd/tui/ui/link.tsx +28 -0
- package/src/cli/cmd/tui/ui/spinner.ts +368 -0
- package/src/cli/cmd/tui/ui/toast.tsx +100 -0
- package/src/cli/cmd/tui/util/clipboard.ts +128 -0
- package/src/cli/cmd/tui/util/editor.ts +32 -0
- package/src/cli/cmd/tui/util/signal.ts +7 -0
- package/src/cli/cmd/tui/util/terminal.ts +114 -0
- package/src/cli/cmd/tui/util/transcript.ts +98 -0
- package/src/cli/cmd/tui/worker.ts +95 -0
- package/src/cli/cmd/uninstall.ts +344 -0
- package/src/cli/cmd/upgrade.ts +67 -0
- package/src/cli/cmd/web.ts +73 -0
- package/src/cli/error.ts +57 -0
- package/src/cli/network.ts +53 -0
- package/src/cli/ui.ts +87 -0
- package/src/cli/upgrade.ts +25 -0
- package/src/command/index.ts +131 -0
- package/src/command/template/initialize.txt +10 -0
- package/src/command/template/review.txt +97 -0
- package/src/config/config.ts +1226 -0
- package/src/config/markdown.ts +41 -0
- package/src/env/index.ts +26 -0
- package/src/file/ignore.ts +83 -0
- package/src/file/index.ts +411 -0
- package/src/file/ripgrep.ts +409 -0
- package/src/file/time.ts +64 -0
- package/src/file/watcher.ts +118 -0
- package/src/flag/flag.ts +51 -0
- package/src/format/formatter.ts +359 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +55 -0
- package/src/id/id.ts +83 -0
- package/src/ide/index.ts +76 -0
- package/src/index.ts +161 -0
- package/src/installation/index.ts +205 -0
- package/src/lsp/client.ts +252 -0
- package/src/lsp/index.ts +485 -0
- package/src/lsp/language.ts +119 -0
- package/src/lsp/server.ts +2032 -0
- package/src/mcp/auth.ts +135 -0
- package/src/mcp/index.ts +874 -0
- package/src/mcp/oauth-callback.ts +200 -0
- package/src/mcp/oauth-provider.ts +154 -0
- package/src/patch/index.ts +622 -0
- package/src/permission/arity.ts +163 -0
- package/src/permission/index.ts +210 -0
- package/src/permission/next.ts +269 -0
- package/src/plugin/codex.ts +524 -0
- package/src/plugin/index.ts +118 -0
- package/src/project/bootstrap.ts +31 -0
- package/src/project/instance.ts +78 -0
- package/src/project/project.ts +316 -0
- package/src/project/state.ts +65 -0
- package/src/project/vcs.ts +76 -0
- package/src/provider/auth.ts +147 -0
- package/src/provider/models-macro.ts +11 -0
- package/src/provider/models.ts +86 -0
- package/src/provider/provider.ts +429 -0
- package/src/provider/sdk/openai-compatible/src/README.md +5 -0
- package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
- package/src/provider/transform.ts +654 -0
- package/src/pty/index.ts +229 -0
- package/src/question/index.ts +170 -0
- package/src/server/error.ts +36 -0
- package/src/server/mdns.ts +57 -0
- package/src/server/project.ts +79 -0
- package/src/server/question.ts +95 -0
- package/src/server/server.ts +2878 -0
- package/src/server/tui.ts +71 -0
- package/src/session/compaction.ts +225 -0
- package/src/session/index.ts +476 -0
- package/src/session/llm.ts +235 -0
- package/src/session/message-v2.ts +683 -0
- package/src/session/message.ts +189 -0
- package/src/session/processor.ts +406 -0
- package/src/session/prompt/anthropic-20250930.txt +166 -0
- package/src/session/prompt/anthropic.txt +105 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +147 -0
- package/src/session/prompt/build-switch.txt +5 -0
- package/src/session/prompt/codex.txt +318 -0
- package/src/session/prompt/codex_header.txt +318 -0
- package/src/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/session/prompt/gemini.txt +155 -0
- package/src/session/prompt/max-steps.txt +16 -0
- package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/src/session/prompt/plan.txt +26 -0
- package/src/session/prompt/qwen.txt +109 -0
- package/src/session/prompt.ts +1652 -0
- package/src/session/retry.ts +90 -0
- package/src/session/revert.ts +108 -0
- package/src/session/status.ts +76 -0
- package/src/session/summary.ts +194 -0
- package/src/session/system.ts +138 -0
- package/src/session/todo.ts +37 -0
- package/src/share/share-next.ts +194 -0
- package/src/share/share.ts +87 -0
- package/src/shell/shell.ts +67 -0
- package/src/skill/index.ts +1 -0
- package/src/skill/skill.ts +127 -0
- package/src/snapshot/index.ts +199 -0
- package/src/storage/storage.ts +226 -0
- package/src/tool/bash.ts +258 -0
- package/src/tool/bash.txt +115 -0
- package/src/tool/batch.ts +175 -0
- package/src/tool/batch.txt +24 -0
- package/src/tool/codesearch.ts +132 -0
- package/src/tool/codesearch.txt +12 -0
- package/src/tool/edit.ts +645 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/external-directory.ts +33 -0
- package/src/tool/glob.ts +77 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +136 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +17 -0
- package/src/tool/ls.ts +121 -0
- package/src/tool/ls.txt +1 -0
- package/src/tool/lsp.ts +96 -0
- package/src/tool/lsp.txt +19 -0
- package/src/tool/multiedit.ts +46 -0
- package/src/tool/multiedit.txt +41 -0
- package/src/tool/patch.ts +201 -0
- package/src/tool/patch.txt +1 -0
- package/src/tool/question.ts +33 -0
- package/src/tool/question.txt +10 -0
- package/src/tool/read.ts +200 -0
- package/src/tool/read.txt +12 -0
- package/src/tool/registry.ts +141 -0
- package/src/tool/skill.ts +75 -0
- package/src/tool/task.ts +181 -0
- package/src/tool/task.txt +60 -0
- package/src/tool/todo.ts +53 -0
- package/src/tool/todoread.txt +14 -0
- package/src/tool/todowrite.txt +167 -0
- package/src/tool/tool.ts +88 -0
- package/src/tool/truncation.ts +98 -0
- package/src/tool/webfetch.ts +182 -0
- package/src/tool/webfetch.txt +13 -0
- package/src/tool/websearch.ts +144 -0
- package/src/tool/websearch.txt +11 -0
- package/src/tool/write.ts +80 -0
- package/src/tool/write.txt +8 -0
- package/src/util/archive.ts +16 -0
- package/src/util/color.ts +19 -0
- package/src/util/context.ts +25 -0
- package/src/util/defer.ts +12 -0
- package/src/util/eventloop.ts +20 -0
- package/src/util/filesystem.ts +83 -0
- package/src/util/fn.ts +11 -0
- package/src/util/iife.ts +3 -0
- package/src/util/keybind.ts +102 -0
- package/src/util/lazy.ts +18 -0
- package/src/util/locale.ts +81 -0
- package/src/util/lock.ts +98 -0
- package/src/util/log.ts +180 -0
- package/src/util/queue.ts +32 -0
- package/src/util/rpc.ts +66 -0
- package/src/util/scrap.ts +10 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +14 -0
- package/src/util/token.ts +7 -0
- package/src/util/wildcard.ts +54 -0
- package/src/worktree/index.ts +217 -0
- package/sst-env.d.ts +9 -0
- package/test/agent/agent.test.ts +511 -0
- package/test/bun.test.ts +53 -0
- package/test/cli/github-action.test.ts +129 -0
- package/test/cli/github-remote.test.ts +80 -0
- package/test/cli/tui/transcript.test.ts +297 -0
- package/test/config/agent-color.test.ts +66 -0
- package/test/config/config.test.ts +1235 -0
- package/test/config/markdown.test.ts +89 -0
- package/test/file/ignore.test.ts +10 -0
- package/test/file/path-traversal.test.ts +115 -0
- package/test/fixture/fixture.ts +45 -0
- package/test/fixture/lsp/fake-lsp-server.js +77 -0
- package/test/ide/ide.test.ts +82 -0
- package/test/keybind.test.ts +421 -0
- package/test/lsp/client.test.ts +95 -0
- package/test/mcp/headers.test.ts +153 -0
- package/test/patch/patch.test.ts +348 -0
- package/test/permission/arity.test.ts +33 -0
- package/test/permission/next.test.ts +652 -0
- package/test/permission-task.test.ts +319 -0
- package/test/plugin/codex.test.ts +123 -0
- package/test/preload.ts +65 -0
- package/test/project/project.test.ts +120 -0
- package/test/provider/amazon-bedrock.test.ts +205 -0
- package/test/provider/provider.test.ts +2127 -0
- package/test/provider/transform.test.ts +1155 -0
- package/test/question/question.test.ts +300 -0
- package/test/server/session-select.test.ts +78 -0
- package/test/session/compaction.test.ts +251 -0
- package/test/session/message-v2.test.ts +570 -0
- package/test/session/retry.test.ts +131 -0
- package/test/session/revert-compact.test.ts +285 -0
- package/test/session/session.test.ts +71 -0
- package/test/skill/skill.test.ts +185 -0
- package/test/snapshot/snapshot.test.ts +939 -0
- package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
- package/test/tool/bash.test.ts +320 -0
- package/test/tool/external-directory.test.ts +126 -0
- package/test/tool/fixtures/large-image.png +0 -0
- package/test/tool/fixtures/models-api.json +33453 -0
- package/test/tool/grep.test.ts +109 -0
- package/test/tool/patch.test.ts +261 -0
- package/test/tool/read.test.ts +303 -0
- package/test/tool/truncation.test.ts +159 -0
- package/test/util/iife.test.ts +36 -0
- package/test/util/lazy.test.ts +50 -0
- package/test/util/timeout.test.ts +21 -0
- package/test/util/wildcard.test.ts +55 -0
- 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,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()
|