@miaws/miaw 1.18.5 → 1.18.6
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/package.json +1 -154
- package/AGENTS.md +0 -131
- package/Dockerfile +0 -18
- package/README.md +0 -15
- package/bunfig.toml +0 -7
- package/git +0 -0
- package/migration/20260511173437_session-metadata/migration.sql +0 -1
- package/migration/20260511173437_session-metadata/snapshot.json +0 -1500
- package/parsers-config.ts +0 -1
- package/script/bench-search.ts +0 -94
- package/script/bench-test-suite.ts +0 -52
- package/script/build.ts +0 -243
- package/script/generate.ts +0 -14
- package/script/httpapi-exercise.ts +0 -1
- package/script/postinstall.mjs +0 -189
- package/script/profile-test-files.ts +0 -42
- package/script/publish.ts +0 -213
- package/script/run-workspace-server +0 -106
- package/script/schema.ts +0 -77
- package/script/time.ts +0 -6
- package/script/trace-imports.ts +0 -153
- package/specs/effect/error-boundaries-plan.md +0 -235
- package/specs/effect/errors.md +0 -207
- package/specs/effect/facades.md +0 -218
- package/specs/effect/guide.md +0 -247
- package/specs/effect/instance-context.md +0 -13
- package/specs/effect/loose-ends.md +0 -30
- package/specs/effect/migration.md +0 -62
- package/specs/effect/routes.md +0 -61
- package/specs/effect/schema.md +0 -88
- package/specs/effect/server-package.md +0 -58
- package/specs/effect/todo.md +0 -241
- package/specs/effect/tools.md +0 -88
- package/specs/openapi-translation-cleanup.md +0 -204
- package/specs/tui-plugins.md +0 -544
- package/specs/v2/api.ts +0 -67
- package/specs/v2/message-shape.md +0 -136
- package/specs/v2/notifications.md +0 -13
- package/specs/v2/tui-command-shim.md +0 -67
- package/src/account/account.ts +0 -463
- package/src/account/repo.ts +0 -173
- package/src/account/schema.ts +0 -99
- package/src/account/url.ts +0 -8
- package/src/acp/agent.ts +0 -95
- package/src/acp/config-option.ts +0 -203
- package/src/acp/content.ts +0 -250
- package/src/acp/directory.ts +0 -210
- package/src/acp/error.ts +0 -90
- package/src/acp/event.ts +0 -336
- package/src/acp/permission.ts +0 -124
- package/src/acp/profile.ts +0 -42
- package/src/acp/service.ts +0 -1048
- package/src/acp/session.ts +0 -231
- package/src/acp/tool.ts +0 -321
- package/src/acp/usage.ts +0 -232
- package/src/agent/agent.ts +0 -467
- package/src/agent/generate.txt +0 -75
- package/src/agent/prompt/compaction.txt +0 -9
- package/src/agent/prompt/explore.txt +0 -18
- package/src/agent/prompt/summary.txt +0 -11
- package/src/agent/prompt/title.txt +0 -44
- package/src/agent/subagent-permissions.ts +0 -27
- package/src/audio.d.ts +0 -14
- package/src/auth/index.ts +0 -99
- package/src/background/job.ts +0 -39
- package/src/bus/global.ts +0 -22
- package/src/cli/bootstrap.ts +0 -11
- package/src/cli/cmd/account.ts +0 -264
- package/src/cli/cmd/acp.ts +0 -73
- package/src/cli/cmd/agent.ts +0 -253
- package/src/cli/cmd/attach.ts +0 -97
- package/src/cli/cmd/cmd.ts +0 -7
- package/src/cli/cmd/db.ts +0 -62
- package/src/cli/cmd/debug/agent.handler.ts +0 -193
- package/src/cli/cmd/debug/agent.ts +0 -27
- package/src/cli/cmd/debug/config.ts +0 -14
- package/src/cli/cmd/debug/file.ts +0 -73
- package/src/cli/cmd/debug/index.ts +0 -87
- package/src/cli/cmd/debug/lsp.ts +0 -50
- package/src/cli/cmd/debug/ripgrep.ts +0 -79
- package/src/cli/cmd/debug/scrap.ts +0 -15
- package/src/cli/cmd/debug/skill.ts +0 -15
- package/src/cli/cmd/debug/snapshot.ts +0 -50
- package/src/cli/cmd/debug/startup.ts +0 -11
- package/src/cli/cmd/debug/v2.ts +0 -49
- package/src/cli/cmd/export.ts +0 -292
- package/src/cli/cmd/generate.ts +0 -54
- package/src/cli/cmd/github.handler.ts +0 -1593
- package/src/cli/cmd/github.shared.ts +0 -30
- package/src/cli/cmd/github.ts +0 -42
- package/src/cli/cmd/import.ts +0 -224
- package/src/cli/cmd/mcp.ts +0 -849
- package/src/cli/cmd/models.ts +0 -66
- package/src/cli/cmd/plug.ts +0 -230
- package/src/cli/cmd/pr.ts +0 -115
- package/src/cli/cmd/prompt-display.ts +0 -1
- package/src/cli/cmd/providers.ts +0 -534
- package/src/cli/cmd/run/demo.ts +0 -1274
- package/src/cli/cmd/run/entry.body.ts +0 -205
- package/src/cli/cmd/run/footer.command.tsx +0 -1064
- package/src/cli/cmd/run/footer.menu.tsx +0 -351
- package/src/cli/cmd/run/footer.permission.tsx +0 -472
- package/src/cli/cmd/run/footer.prompt.tsx +0 -1306
- package/src/cli/cmd/run/footer.question.tsx +0 -573
- package/src/cli/cmd/run/footer.subagent.tsx +0 -173
- package/src/cli/cmd/run/footer.ts +0 -1129
- package/src/cli/cmd/run/footer.view.tsx +0 -943
- package/src/cli/cmd/run/footer.width.ts +0 -27
- package/src/cli/cmd/run/permission.shared.ts +0 -256
- package/src/cli/cmd/run/prompt.editor.ts +0 -157
- package/src/cli/cmd/run/prompt.shared.ts +0 -153
- package/src/cli/cmd/run/question.shared.ts +0 -340
- package/src/cli/cmd/run/runtime.boot.ts +0 -202
- package/src/cli/cmd/run/runtime.lifecycle.ts +0 -406
- package/src/cli/cmd/run/runtime.queue.ts +0 -349
- package/src/cli/cmd/run/runtime.shared.ts +0 -17
- package/src/cli/cmd/run/runtime.stdin.ts +0 -37
- package/src/cli/cmd/run/runtime.ts +0 -814
- package/src/cli/cmd/run/scrollback.shared.ts +0 -92
- package/src/cli/cmd/run/scrollback.surface.ts +0 -431
- package/src/cli/cmd/run/scrollback.writer.tsx +0 -352
- package/src/cli/cmd/run/session-data.ts +0 -1113
- package/src/cli/cmd/run/session-replay.ts +0 -374
- package/src/cli/cmd/run/session.shared.ts +0 -196
- package/src/cli/cmd/run/splash.ts +0 -280
- package/src/cli/cmd/run/stream.transport.ts +0 -1462
- package/src/cli/cmd/run/stream.ts +0 -175
- package/src/cli/cmd/run/subagent-data.ts +0 -876
- package/src/cli/cmd/run/theme.ts +0 -690
- package/src/cli/cmd/run/tool.ts +0 -1489
- package/src/cli/cmd/run/trace.ts +0 -94
- package/src/cli/cmd/run/turn-summary.ts +0 -47
- package/src/cli/cmd/run/types.ts +0 -350
- package/src/cli/cmd/run/variant.shared.ts +0 -215
- package/src/cli/cmd/run.ts +0 -894
- package/src/cli/cmd/serve.ts +0 -24
- package/src/cli/cmd/session.ts +0 -147
- package/src/cli/cmd/stats.ts +0 -393
- package/src/cli/cmd/tui.ts +0 -224
- package/src/cli/cmd/uninstall.ts +0 -353
- package/src/cli/cmd/upgrade.ts +0 -74
- package/src/cli/cmd/web.ts +0 -84
- package/src/cli/effect/prompt.ts +0 -37
- package/src/cli/effect-cmd.ts +0 -96
- package/src/cli/error.ts +0 -130
- package/src/cli/heap.ts +0 -45
- package/src/cli/logo.ts +0 -1
- package/src/cli/network.ts +0 -64
- package/src/cli/tui/layer.ts +0 -7
- package/src/cli/tui/validate-session.ts +0 -29
- package/src/cli/tui/worker.ts +0 -71
- package/src/cli/ui.ts +0 -132
- package/src/cli/upgrade.ts +0 -53
- package/src/command/index.ts +0 -184
- package/src/command/template/initialize.txt +0 -66
- package/src/command/template/review.txt +0 -101
- package/src/config/agent-preset.ts +0 -175
- package/src/config/agent.ts +0 -59
- package/src/config/command.ts +0 -39
- package/src/config/config.ts +0 -703
- package/src/config/entry-name.ts +0 -19
- package/src/config/managed.ts +0 -69
- package/src/config/markdown.ts +0 -36
- package/src/config/parse.ts +0 -79
- package/src/config/paths.ts +0 -45
- package/src/config/plugin.ts +0 -79
- package/src/config/tui-cwd.ts +0 -5
- package/src/config/tui-host-attention.ts +0 -21
- package/src/config/tui-migrate.ts +0 -132
- package/src/config/tui.ts +0 -274
- package/src/config/variable.ts +0 -91
- package/src/control-plane/adapters/index.ts +0 -41
- package/src/control-plane/adapters/worktree.ts +0 -96
- package/src/control-plane/dev/README.md +0 -19
- package/src/control-plane/dev/debug-workspace-plugin.ts +0 -73
- package/src/control-plane/types.ts +0 -59
- package/src/control-plane/util.ts +0 -39
- package/src/control-plane/workspace-adapter-runtime.ts +0 -51
- package/src/control-plane/workspace-context.ts +0 -26
- package/src/control-plane/workspace.ts +0 -989
- package/src/effect/app-runtime.ts +0 -132
- package/src/effect/bootstrap-runtime.ts +0 -23
- package/src/effect/bridge.ts +0 -84
- package/src/effect/config-service.ts +0 -67
- package/src/effect/instance-ref.ts +0 -11
- package/src/effect/instance-registry.ts +0 -12
- package/src/effect/instance-state.ts +0 -69
- package/src/effect/promise.ts +0 -17
- package/src/effect/run-service.ts +0 -47
- package/src/effect/runner.ts +0 -217
- package/src/effect/runtime-flags.ts +0 -79
- package/src/env/index.ts +0 -43
- package/src/event-v2-bridge.ts +0 -79
- package/src/format/formatter.ts +0 -404
- package/src/format/index.ts +0 -205
- package/src/git/index.ts +0 -350
- package/src/id/id.ts +0 -80
- package/src/ide/index.ts +0 -61
- package/src/image/image.ts +0 -174
- package/src/index.ts +0 -142
- package/src/installation/index.ts +0 -350
- package/src/lsp/client.ts +0 -650
- package/src/lsp/diagnostic.ts +0 -29
- package/src/lsp/language.ts +0 -121
- package/src/lsp/launch.ts +0 -21
- package/src/lsp/lsp.ts +0 -511
- package/src/lsp/server.ts +0 -1983
- package/src/markdown.d.ts +0 -4
- package/src/mcp/auth.ts +0 -174
- package/src/mcp/catalog.ts +0 -144
- package/src/mcp/index.ts +0 -953
- package/src/mcp/oauth-callback.ts +0 -221
- package/src/mcp/oauth-provider.ts +0 -206
- package/src/node.ts +0 -4
- package/src/patch/index.ts +0 -686
- package/src/permission/arity.ts +0 -163
- package/src/permission/evaluate.ts +0 -1
- package/src/permission/index.ts +0 -230
- package/src/plugin/azure.ts +0 -26
- package/src/plugin/cloudflare.ts +0 -76
- package/src/plugin/digitalocean.ts +0 -383
- package/src/plugin/github-copilot/copilot.ts +0 -413
- package/src/plugin/github-copilot/models.ts +0 -246
- package/src/plugin/index.ts +0 -315
- package/src/plugin/install.ts +0 -439
- package/src/plugin/loader.ts +0 -237
- package/src/plugin/meta.ts +0 -188
- package/src/plugin/openai/README.md +0 -31
- package/src/plugin/openai/codex.ts +0 -640
- package/src/plugin/openai/ws-pool.ts +0 -270
- package/src/plugin/openai/ws.ts +0 -381
- package/src/plugin/pty-environment.ts +0 -24
- package/src/plugin/shared.ts +0 -323
- package/src/plugin/snowflake-cortex.ts +0 -529
- package/src/plugin/tui/internal.ts +0 -10
- package/src/plugin/tui/runtime.ts +0 -1130
- package/src/plugin/xai.ts +0 -734
- package/src/project/bootstrap-service.ts +0 -9
- package/src/project/bootstrap.ts +0 -76
- package/src/project/instance-context.ts +0 -24
- package/src/project/instance-layer.ts +0 -11
- package/src/project/instance-runtime.ts +0 -16
- package/src/project/instance-store.ts +0 -209
- package/src/project/project.ts +0 -519
- package/src/project/vcs.ts +0 -431
- package/src/provider/auth.ts +0 -233
- package/src/provider/error.ts +0 -188
- package/src/provider/model-status.ts +0 -8
- package/src/provider/provider.ts +0 -1975
- package/src/provider/transform.ts +0 -1426
- package/src/question/index.ts +0 -229
- package/src/question/schema.ts +0 -10
- package/src/server/auth.ts +0 -48
- package/src/server/event.ts +0 -13
- package/src/server/global-lifecycle.ts +0 -28
- package/src/server/init-projectors.ts +0 -3
- package/src/server/mdns.ts +0 -47
- package/src/server/projectors.ts +0 -1
- package/src/server/proxy-util.ts +0 -48
- package/src/server/routes/instance/httpapi/AGENTS.md +0 -39
- package/src/server/routes/instance/httpapi/api.ts +0 -78
- package/src/server/routes/instance/httpapi/errors.ts +0 -193
- package/src/server/routes/instance/httpapi/groups/config.ts +0 -65
- package/src/server/routes/instance/httpapi/groups/control-plane.ts +0 -35
- package/src/server/routes/instance/httpapi/groups/control.ts +0 -76
- package/src/server/routes/instance/httpapi/groups/event.ts +0 -29
- package/src/server/routes/instance/httpapi/groups/experimental.ts +0 -260
- package/src/server/routes/instance/httpapi/groups/file.ts +0 -185
- package/src/server/routes/instance/httpapi/groups/global.ts +0 -138
- package/src/server/routes/instance/httpapi/groups/instance.ts +0 -206
- package/src/server/routes/instance/httpapi/groups/mcp.ts +0 -156
- package/src/server/routes/instance/httpapi/groups/metadata.ts +0 -18
- package/src/server/routes/instance/httpapi/groups/permission.ts +0 -61
- package/src/server/routes/instance/httpapi/groups/project-copy.ts +0 -32
- package/src/server/routes/instance/httpapi/groups/project.ts +0 -93
- package/src/server/routes/instance/httpapi/groups/provider.ts +0 -101
- package/src/server/routes/instance/httpapi/groups/pty.ts +0 -172
- package/src/server/routes/instance/httpapi/groups/query.ts +0 -12
- package/src/server/routes/instance/httpapi/groups/question.ts +0 -74
- package/src/server/routes/instance/httpapi/groups/session.ts +0 -462
- package/src/server/routes/instance/httpapi/groups/sync.ts +0 -113
- package/src/server/routes/instance/httpapi/groups/tui.ts +0 -208
- package/src/server/routes/instance/httpapi/groups/workspace.ts +0 -141
- package/src/server/routes/instance/httpapi/handlers/config.ts +0 -34
- package/src/server/routes/instance/httpapi/handlers/control-plane.ts +0 -37
- package/src/server/routes/instance/httpapi/handlers/control.ts +0 -43
- package/src/server/routes/instance/httpapi/handlers/event.ts +0 -99
- package/src/server/routes/instance/httpapi/handlers/experimental.ts +0 -187
- package/src/server/routes/instance/httpapi/handlers/file.ts +0 -139
- package/src/server/routes/instance/httpapi/handlers/global.ts +0 -156
- package/src/server/routes/instance/httpapi/handlers/instance.ts +0 -110
- package/src/server/routes/instance/httpapi/handlers/mcp.ts +0 -111
- package/src/server/routes/instance/httpapi/handlers/permission.ts +0 -41
- package/src/server/routes/instance/httpapi/handlers/project-copy.ts +0 -83
- package/src/server/routes/instance/httpapi/handlers/project.ts +0 -63
- package/src/server/routes/instance/httpapi/handlers/provider.ts +0 -113
- package/src/server/routes/instance/httpapi/handlers/pty.ts +0 -273
- package/src/server/routes/instance/httpapi/handlers/question.ts +0 -54
- package/src/server/routes/instance/httpapi/handlers/session-errors.ts +0 -21
- package/src/server/routes/instance/httpapi/handlers/session.ts +0 -440
- package/src/server/routes/instance/httpapi/handlers/sync.ts +0 -89
- package/src/server/routes/instance/httpapi/handlers/tui.ts +0 -131
- package/src/server/routes/instance/httpapi/handlers/workspace.ts +0 -102
- package/src/server/routes/instance/httpapi/lifecycle.ts +0 -54
- package/src/server/routes/instance/httpapi/middleware/authorization.ts +0 -150
- package/src/server/routes/instance/httpapi/middleware/compression.ts +0 -64
- package/src/server/routes/instance/httpapi/middleware/cors-vary.ts +0 -29
- package/src/server/routes/instance/httpapi/middleware/error.ts +0 -43
- package/src/server/routes/instance/httpapi/middleware/fence.ts +0 -25
- package/src/server/routes/instance/httpapi/middleware/instance-context.ts +0 -43
- package/src/server/routes/instance/httpapi/middleware/proxy.ts +0 -108
- package/src/server/routes/instance/httpapi/middleware/schema-error.ts +0 -41
- package/src/server/routes/instance/httpapi/middleware/workspace-routing.ts +0 -250
- package/src/server/routes/instance/httpapi/public.ts +0 -535
- package/src/server/routes/instance/httpapi/server.ts +0 -298
- package/src/server/routes/instance/httpapi/websocket-tracker.ts +0 -57
- package/src/server/server.ts +0 -217
- package/src/server/shared/fence.ts +0 -60
- package/src/server/shared/pty-ticket.ts +0 -15
- package/src/server/shared/public-ui.ts +0 -12
- package/src/server/shared/tui-control.ts +0 -28
- package/src/server/shared/ui.ts +0 -108
- package/src/server/shared/workspace-routing.ts +0 -38
- package/src/server/tui-event.ts +0 -53
- package/src/session/compaction.ts +0 -620
- package/src/session/instruction.ts +0 -250
- package/src/session/llm/AGENTS.md +0 -90
- package/src/session/llm/ai-sdk.ts +0 -288
- package/src/session/llm/native-request.ts +0 -196
- package/src/session/llm/native-runtime.ts +0 -195
- package/src/session/llm/request.ts +0 -216
- package/src/session/llm.ts +0 -415
- package/src/session/message-error.ts +0 -14
- package/src/session/message-v2.ts +0 -744
- package/src/session/message.ts +0 -148
- package/src/session/overflow.ts +0 -34
- package/src/session/processor.ts +0 -1084
- package/src/session/prompt/anthropic.txt +0 -105
- package/src/session/prompt/beast.txt +0 -147
- package/src/session/prompt/build-switch.txt +0 -5
- package/src/session/prompt/codex.txt +0 -79
- package/src/session/prompt/copilot-gpt-5.txt +0 -143
- package/src/session/prompt/default.txt +0 -95
- package/src/session/prompt/gemini.txt +0 -155
- package/src/session/prompt/gpt.txt +0 -107
- package/src/session/prompt/kimi.txt +0 -95
- package/src/session/prompt/max-steps.txt +0 -16
- package/src/session/prompt/plan-mode.txt +0 -70
- package/src/session/prompt/plan-reminder-anthropic.txt +0 -67
- package/src/session/prompt/plan.txt +0 -26
- package/src/session/prompt/trinity.txt +0 -97
- package/src/session/prompt/ultrawork.txt +0 -289
- package/src/session/prompt.ts +0 -1725
- package/src/session/reminders.ts +0 -92
- package/src/session/retry.ts +0 -201
- package/src/session/revert.ts +0 -160
- package/src/session/run-state.ts +0 -156
- package/src/session/schema.ts +0 -26
- package/src/session/session.ts +0 -1119
- package/src/session/status.ts +0 -97
- package/src/session/summary.ts +0 -165
- package/src/session/system.ts +0 -117
- package/src/session/todo.ts +0 -90
- package/src/session/tools.ts +0 -207
- package/src/session/ultrawork.ts +0 -26
- package/src/share/session.ts +0 -61
- package/src/share/share-next.ts +0 -385
- package/src/skill/discovery.ts +0 -109
- package/src/skill/index.ts +0 -366
- package/src/snapshot/index.ts +0 -808
- package/src/sql.d.ts +0 -4
- package/src/storage/schema.ts +0 -5
- package/src/storage/storage.ts +0 -329
- package/src/sync/README.md +0 -179
- package/src/sync/schema.ts +0 -11
- package/src/temporary.ts +0 -31
- package/src/tool/apply_patch.ts +0 -313
- package/src/tool/apply_patch.txt +0 -33
- package/src/tool/edit.ts +0 -737
- package/src/tool/edit.txt +0 -10
- package/src/tool/external-directory.ts +0 -49
- package/src/tool/glob.ts +0 -76
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.ts +0 -112
- package/src/tool/grep.txt +0 -8
- package/src/tool/invalid.ts +0 -21
- package/src/tool/json-schema.ts +0 -164
- package/src/tool/lsp.ts +0 -113
- package/src/tool/lsp.txt +0 -24
- package/src/tool/mcp-websearch.ts +0 -96
- package/src/tool/plan-enter.txt +0 -14
- package/src/tool/plan-exit.txt +0 -13
- package/src/tool/plan.ts +0 -79
- package/src/tool/question.ts +0 -44
- package/src/tool/question.txt +0 -10
- package/src/tool/read.ts +0 -386
- package/src/tool/read.txt +0 -14
- package/src/tool/registry.ts +0 -440
- package/src/tool/schema.ts +0 -14
- package/src/tool/shell/id.ts +0 -19
- package/src/tool/shell/prompt.ts +0 -307
- package/src/tool/shell/shell.txt +0 -21
- package/src/tool/shell.ts +0 -657
- package/src/tool/skill.ts +0 -71
- package/src/tool/skill.txt +0 -5
- package/src/tool/task.ts +0 -346
- package/src/tool/task.txt +0 -19
- package/src/tool/todo.ts +0 -57
- package/src/tool/todowrite.txt +0 -44
- package/src/tool/tool.ts +0 -183
- package/src/tool/truncate.ts +0 -158
- package/src/tool/truncation-dir.ts +0 -4
- package/src/tool/webfetch.ts +0 -192
- package/src/tool/webfetch.txt +0 -13
- package/src/tool/websearch.ts +0 -143
- package/src/tool/websearch.txt +0 -14
- package/src/tool/write.ts +0 -104
- package/src/tool/write.txt +0 -8
- package/src/util/archive.ts +0 -17
- package/src/util/bom.ts +0 -27
- package/src/util/data-url.ts +0 -9
- package/src/util/defer.ts +0 -10
- package/src/util/effect-http-client.ts +0 -11
- package/src/util/error.ts +0 -1
- package/src/util/filesystem.ts +0 -251
- package/src/util/iife.ts +0 -3
- package/src/util/lazy.ts +0 -20
- package/src/util/local-context.ts +0 -25
- package/src/util/locale.ts +0 -2
- package/src/util/media.ts +0 -26
- package/src/util/process.ts +0 -177
- package/src/util/proxy-env.ts +0 -72
- package/src/util/queue.ts +0 -32
- package/src/util/record.ts +0 -1
- package/src/util/repository.ts +0 -232
- package/src/util/rpc.ts +0 -66
- package/src/util/signal.ts +0 -12
- package/src/util/timeout.ts +0 -13
- package/src/util/token.ts +0 -1
- package/src/util/wildcard.ts +0 -59
- package/src/worktree/index.ts +0 -654
- package/sst-env.d.ts +0 -10
- package/test/AGENTS.md +0 -204
- package/test/EFFECT_TEST_MIGRATION.md +0 -169
- package/test/account/repo.test.ts +0 -353
- package/test/account/service.test.ts +0 -453
- package/test/acp/config-option.test.ts +0 -229
- package/test/acp/content.test.ts +0 -201
- package/test/acp/directory.test.ts +0 -186
- package/test/acp/error.test.ts +0 -67
- package/test/acp/event.test.ts +0 -743
- package/test/acp/permission.test.ts +0 -273
- package/test/acp/service-session.test.ts +0 -1174
- package/test/acp/session.test.ts +0 -200
- package/test/acp/tool.test.ts +0 -210
- package/test/acp/usage.test.ts +0 -315
- package/test/agent/agent.test.ts +0 -760
- package/test/agent/plan-mode-subagent-bypass.test.ts +0 -159
- package/test/agent/plugin-agent-regression.test.ts +0 -64
- package/test/auth/auth.test.ts +0 -77
- package/test/background/job.test.ts +0 -243
- package/test/cli/account.test.ts +0 -30
- package/test/cli/acp/acp-test-client.ts +0 -97
- package/test/cli/acp/config-options.test.ts +0 -103
- package/test/cli/acp/helpers.ts +0 -96
- package/test/cli/acp/initialize-auth.test.ts +0 -61
- package/test/cli/acp/lifecycle.test.ts +0 -118
- package/test/cli/acp/prompt-content.test.ts +0 -97
- package/test/cli/acp/skills.test.ts +0 -38
- package/test/cli/cmd/tui/attention.test.ts +0 -484
- package/test/cli/effect-cmd-instance-als.test.ts +0 -39
- package/test/cli/error.test.ts +0 -95
- package/test/cli/github-action.test.ts +0 -199
- package/test/cli/github-remote.test.ts +0 -90
- package/test/cli/help/__snapshots__/help-snapshots.test.ts.snap +0 -631
- package/test/cli/help/help-snapshots.test.ts +0 -137
- package/test/cli/import.test.ts +0 -54
- package/test/cli/mcp-add.test.ts +0 -74
- package/test/cli/plugin-auth-picker.test.ts +0 -120
- package/test/cli/run/entry.body.test.ts +0 -536
- package/test/cli/run/footer.menu.test.ts +0 -43
- package/test/cli/run/footer.view.test.tsx +0 -1375
- package/test/cli/run/footer.width.test.ts +0 -35
- package/test/cli/run/permission.shared.test.ts +0 -144
- package/test/cli/run/prompt.editor.test.ts +0 -101
- package/test/cli/run/prompt.shared.test.ts +0 -101
- package/test/cli/run/question.shared.test.ts +0 -115
- package/test/cli/run/run-process.test.ts +0 -84
- package/test/cli/run/runtime.boot.test.ts +0 -283
- package/test/cli/run/runtime.queue.test.ts +0 -481
- package/test/cli/run/runtime.stdin.test.ts +0 -71
- package/test/cli/run/runtime.test.ts +0 -238
- package/test/cli/run/scrollback.surface.test.ts +0 -1065
- package/test/cli/run/session-data.test.ts +0 -595
- package/test/cli/run/session-replay.test.ts +0 -692
- package/test/cli/run/session.shared.test.ts +0 -247
- package/test/cli/run/stream.test.ts +0 -56
- package/test/cli/run/stream.transport.test.ts +0 -2363
- package/test/cli/run/subagent-data.test.ts +0 -547
- package/test/cli/run/theme.test.ts +0 -177
- package/test/cli/run/variant.shared.test.ts +0 -217
- package/test/cli/serve/serve-process.test.ts +0 -61
- package/test/cli/smokes/read-only.test.ts +0 -115
- package/test/cli/tui/attach.test.ts +0 -11
- package/test/cli/tui/editor-context-zed.test.ts +0 -379
- package/test/cli/tui/editor-context.test.tsx +0 -297
- package/test/cli/tui/plugin-add.test.ts +0 -110
- package/test/cli/tui/plugin-install.test.ts +0 -87
- package/test/cli/tui/plugin-lifecycle.test.ts +0 -224
- package/test/cli/tui/plugin-loader-entrypoint.test.ts +0 -485
- package/test/cli/tui/plugin-loader-pure.test.ts +0 -72
- package/test/cli/tui/plugin-loader.test.ts +0 -1332
- package/test/cli/tui/plugin-toggle.test.ts +0 -264
- package/test/cli/tui/thread.test.ts +0 -36
- package/test/config/agent-color.test.ts +0 -47
- package/test/config/config.test.ts +0 -2041
- package/test/config/entry-name.test.ts +0 -57
- package/test/config/fixtures/empty-frontmatter.md +0 -4
- package/test/config/fixtures/frontmatter.md +0 -28
- package/test/config/fixtures/markdown-header.md +0 -11
- package/test/config/fixtures/no-frontmatter.md +0 -1
- package/test/config/fixtures/weird-model-id.md +0 -13
- package/test/config/lsp.test.ts +0 -69
- package/test/config/markdown.test.ts +0 -228
- package/test/config/plugin.test.ts +0 -0
- package/test/config/tui.test.ts +0 -886
- package/test/control-plane/adapters.test.ts +0 -71
- package/test/control-plane/workspace.test.ts +0 -1703
- package/test/effect/app-graph-types.test.ts +0 -108
- package/test/effect/app-graph.test.ts +0 -204
- package/test/effect/app-runtime-logger.test.ts +0 -99
- package/test/effect/config-service.test.ts +0 -65
- package/test/effect/instance-state.test.ts +0 -391
- package/test/effect/run-service.test.ts +0 -89
- package/test/effect/runner.test.ts +0 -514
- package/test/effect/runtime-flags.test.ts +0 -373
- package/test/fake/account.ts +0 -9
- package/test/fake/auth.ts +0 -8
- package/test/fake/npm.ts +0 -8
- package/test/fake/provider.ts +0 -82
- package/test/fake/skill.ts +0 -8
- package/test/filesystem/filesystem.test.ts +0 -319
- package/test/fixture/agent-plugin.constants.ts +0 -6
- package/test/fixture/agent-plugin.ts +0 -12
- package/test/fixture/config.ts +0 -23
- package/test/fixture/db.ts +0 -11
- package/test/fixture/fixture.test.ts +0 -26
- package/test/fixture/fixture.ts +0 -224
- package/test/fixture/flag.ts +0 -20
- package/test/fixture/flock-worker.ts +0 -72
- package/test/fixture/lsp/fake-lsp-server.js +0 -249
- package/test/fixture/mcp-session-recovery.ts +0 -50
- package/test/fixture/plug-worker.ts +0 -93
- package/test/fixture/plugin-meta-worker.ts +0 -19
- package/test/fixture/plugin.ts +0 -10
- package/test/fixture/skills/agents-sdk/SKILL.md +0 -152
- package/test/fixture/skills/agents-sdk/references/callable.md +0 -92
- package/test/fixture/skills/cloudflare/SKILL.md +0 -211
- package/test/fixture/skills/index.json +0 -6
- package/test/fixture/tui-environment.tsx +0 -32
- package/test/fixture/tui-plugin.ts +0 -355
- package/test/fixture/tui-runtime.ts +0 -56
- package/test/fixture/tui-sdk.ts +0 -82
- package/test/fixture/workspace.ts +0 -30
- package/test/fixtures/recordings/session/native-anthropic-tool-loop.json +0 -49
- package/test/fixtures/recordings/session/native-openai-oauth-tool-loop.json +0 -45
- package/test/fixtures/recordings/session/native-zen-tool-loop.json +0 -49
- package/test/format/format.test.ts +0 -228
- package/test/git/git.test.ts +0 -178
- package/test/ide/ide.test.ts +0 -82
- package/test/image/fixtures/picture-5mb-base64.png +0 -0
- package/test/image/image.test.ts +0 -123
- package/test/installation/installation.test.ts +0 -230
- package/test/lib/cli-process.ts +0 -459
- package/test/lib/effect.ts +0 -177
- package/test/lib/filesystem.ts +0 -10
- package/test/lib/llm-server.ts +0 -779
- package/test/lib/snapshot.ts +0 -73
- package/test/lib/test-provider.ts +0 -37
- package/test/lib/websocket.ts +0 -46
- package/test/lsp/client.test.ts +0 -488
- package/test/lsp/index.test.ts +0 -232
- package/test/lsp/jdtls-root.test.ts +0 -459
- package/test/lsp/launch.test.ts +0 -22
- package/test/lsp/lifecycle.test.ts +0 -160
- package/test/mcp/auth.test.ts +0 -78
- package/test/mcp/headers.test.ts +0 -126
- package/test/mcp/lifecycle.test.ts +0 -1213
- package/test/mcp/oauth-auto-connect.test.ts +0 -276
- package/test/mcp/oauth-browser.test.ts +0 -239
- package/test/mcp/oauth-callback.test.ts +0 -34
- package/test/mcp/oauth-provider.test.ts +0 -61
- package/test/mcp/session-recovery.test.ts +0 -27
- package/test/patch/patch.test.ts +0 -383
- package/test/permission/arity.test.ts +0 -33
- package/test/permission/next.test.ts +0 -1176
- package/test/permission-task.test.ts +0 -318
- package/test/plugin/auth-override.test.ts +0 -105
- package/test/plugin/cloudflare.test.ts +0 -68
- package/test/plugin/codex.test.ts +0 -247
- package/test/plugin/github-copilot-models.test.ts +0 -332
- package/test/plugin/install-concurrency.test.ts +0 -140
- package/test/plugin/install.test.ts +0 -570
- package/test/plugin/loader-shared.test.ts +0 -1303
- package/test/plugin/meta.test.ts +0 -137
- package/test/plugin/openai-rollout.test.ts +0 -17
- package/test/plugin/openai-ws.test.ts +0 -877
- package/test/plugin/shared.test.ts +0 -88
- package/test/plugin/snowflake-cortex.test.ts +0 -278
- package/test/plugin/trigger.test.ts +0 -120
- package/test/plugin/workspace-adapter.test.ts +0 -140
- package/test/plugin/xai.test.ts +0 -634
- package/test/preload.ts +0 -92
- package/test/project/instance-bootstrap.test.ts +0 -110
- package/test/project/instance.test.ts +0 -245
- package/test/project/migrate-global.test.ts +0 -167
- package/test/project/project-directory.test.ts +0 -201
- package/test/project/project.test.ts +0 -815
- package/test/project/vcs.test.ts +0 -336
- package/test/project/worktree-remove.test.ts +0 -126
- package/test/project/worktree.test.ts +0 -320
- package/test/provider/amazon-bedrock.test.ts +0 -360
- package/test/provider/cf-ai-gateway-e2e.test.ts +0 -132
- package/test/provider/digitalocean.test.ts +0 -123
- package/test/provider/gitlab-duo.test.ts +0 -412
- package/test/provider/header-timeout.test.ts +0 -233
- package/test/provider/model-status.test.ts +0 -61
- package/test/provider/provider.test.ts +0 -1793
- package/test/provider/transform.test.ts +0 -4207
- package/test/question/question.test.ts +0 -465
- package/test/server/AGENTS.md +0 -15
- package/test/server/auth.test.ts +0 -59
- package/test/server/global-bus.ts +0 -31
- package/test/server/global-session-list.test.ts +0 -104
- package/test/server/httpapi-authorization.test.ts +0 -174
- package/test/server/httpapi-compression.test.ts +0 -151
- package/test/server/httpapi-config.test.ts +0 -110
- package/test/server/httpapi-control-plane.test.ts +0 -63
- package/test/server/httpapi-cors-vary.test.ts +0 -63
- package/test/server/httpapi-cors.test.ts +0 -122
- package/test/server/httpapi-error-middleware.test.ts +0 -101
- package/test/server/httpapi-event.test.ts +0 -94
- package/test/server/httpapi-exercise/assertions.ts +0 -64
- package/test/server/httpapi-exercise/backend.ts +0 -144
- package/test/server/httpapi-exercise/dsl.ts +0 -210
- package/test/server/httpapi-exercise/environment.ts +0 -40
- package/test/server/httpapi-exercise/index.ts +0 -1685
- package/test/server/httpapi-exercise/report.ts +0 -66
- package/test/server/httpapi-exercise/routing.ts +0 -96
- package/test/server/httpapi-exercise/runner.ts +0 -267
- package/test/server/httpapi-exercise/runtime.ts +0 -52
- package/test/server/httpapi-exercise/types.ts +0 -123
- package/test/server/httpapi-experimental.test.ts +0 -297
- package/test/server/httpapi-file.test.ts +0 -73
- package/test/server/httpapi-global.test.ts +0 -66
- package/test/server/httpapi-instance-context.test.ts +0 -348
- package/test/server/httpapi-instance-route-auth.test.ts +0 -81
- package/test/server/httpapi-instance.test.ts +0 -265
- package/test/server/httpapi-layer.ts +0 -33
- package/test/server/httpapi-listen.test.ts +0 -412
- package/test/server/httpapi-mcp-oauth.test.ts +0 -73
- package/test/server/httpapi-mcp.test.ts +0 -223
- package/test/server/httpapi-mdns.test.ts +0 -79
- package/test/server/httpapi-promptasync-context.test.ts +0 -223
- package/test/server/httpapi-provider.test.ts +0 -400
- package/test/server/httpapi-pty.test.ts +0 -299
- package/test/server/httpapi-public-openapi.test.ts +0 -319
- package/test/server/httpapi-query-schema-drift.test.ts +0 -330
- package/test/server/httpapi-reference.test.ts +0 -62
- package/test/server/httpapi-schema-error-body.test.ts +0 -165
- package/test/server/httpapi-sdk.test.ts +0 -909
- package/test/server/httpapi-session.test.ts +0 -1011
- package/test/server/httpapi-sync.test.ts +0 -148
- package/test/server/httpapi-ui.test.ts +0 -453
- package/test/server/httpapi-v2-location.test.ts +0 -82
- package/test/server/httpapi-v2-pty.test.ts +0 -250
- package/test/server/httpapi-workspace-routing.test.ts +0 -555
- package/test/server/httpapi-workspace.test.ts +0 -513
- package/test/server/negative-tokens-regression.test.ts +0 -83
- package/test/server/project-copy.test.ts +0 -121
- package/test/server/project-init-git.test.ts +0 -114
- package/test/server/proxy-util.test.ts +0 -113
- package/test/server/sdk-error-shape.test.ts +0 -81
- package/test/server/sdk-v1-smoke.test.ts +0 -57
- package/test/server/session-actions.test.ts +0 -109
- package/test/server/session-diff-missing-patch.test.ts +0 -96
- package/test/server/session-list.test.ts +0 -312
- package/test/server/session-messages.test.ts +0 -179
- package/test/server/session-select.test.ts +0 -66
- package/test/server/workspace-proxy.test.ts +0 -181
- package/test/server/workspace-routing.test.ts +0 -94
- package/test/server/worktree-endpoint-repro.test.ts +0 -307
- package/test/session/compaction.test.ts +0 -1834
- package/test/session/instruction.test.ts +0 -256
- package/test/session/llm-native-recorded.test.ts +0 -433
- package/test/session/llm-native.test.ts +0 -760
- package/test/session/llm.test.ts +0 -1932
- package/test/session/message-v2.test.ts +0 -1661
- package/test/session/messages-pagination.test.ts +0 -1056
- package/test/session/processor-effect.test.ts +0 -1076
- package/test/session/prompt.test.ts +0 -2326
- package/test/session/retry.test.ts +0 -439
- package/test/session/revert-compact.test.ts +0 -639
- package/test/session/schema-decoding.test.ts +0 -313
- package/test/session/session-schema.test.ts +0 -78
- package/test/session/session.test.ts +0 -248
- package/test/session/snapshot-tool-race.test.ts +0 -190
- package/test/session/structured-output-integration.test.ts +0 -235
- package/test/session/structured-output.test.ts +0 -387
- package/test/session/system.test.ts +0 -86
- package/test/session/ultrawork.test.ts +0 -25
- package/test/share/share-next.test.ts +0 -326
- package/test/skill/discovery.test.ts +0 -139
- package/test/skill/skill.test.ts +0 -571
- package/test/snapshot/snapshot.test.ts +0 -1121
- package/test/storage/storage.test.ts +0 -296
- package/test/tool/__snapshots__/parameters.test.ts.snap +0 -484
- package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
- package/test/tool/apply_patch.test.ts +0 -533
- package/test/tool/edit.test.ts +0 -578
- package/test/tool/external-directory.test.ts +0 -155
- package/test/tool/fixtures/large-image.png +0 -0
- package/test/tool/fixtures/models-api.json +0 -117299
- package/test/tool/glob.test.ts +0 -136
- package/test/tool/grep.test.ts +0 -225
- package/test/tool/lsp.test.ts +0 -181
- package/test/tool/parameters.test.ts +0 -293
- package/test/tool/question.test.ts +0 -138
- package/test/tool/read.test.ts +0 -605
- package/test/tool/registry.test.ts +0 -497
- package/test/tool/shell.test.ts +0 -1238
- package/test/tool/skill.test.ts +0 -136
- package/test/tool/task.test.ts +0 -898
- package/test/tool/tool-define.test.ts +0 -153
- package/test/tool/truncation.test.ts +0 -266
- package/test/tool/webfetch.test.ts +0 -113
- package/test/tool/websearch.test.ts +0 -99
- package/test/tool/write.test.ts +0 -276
- package/test/util/data-url.test.ts +0 -14
- package/test/util/error.test.ts +0 -16
- package/test/util/filesystem.test.ts +0 -656
- package/test/util/glob.test.ts +0 -164
- package/test/util/iife.test.ts +0 -36
- package/test/util/lazy.test.ts +0 -50
- package/test/util/module.test.ts +0 -59
- package/test/util/process.test.ts +0 -128
- package/test/util/repository.test.ts +0 -93
- package/test/util/timeout.test.ts +0 -21
- package/test/util/wildcard.test.ts +0 -90
- package/test/v2/session-message-updater.test.ts +0 -269
- package/tsconfig.json +0 -16
|
@@ -1,1426 +0,0 @@
|
|
|
1
|
-
import type { ModelMessage, ToolResultPart } from "ai"
|
|
2
|
-
import { mergeDeep, unique } from "remeda"
|
|
3
|
-
import type { JSONSchema7 } from "@ai-sdk/provider"
|
|
4
|
-
import type * as Provider from "./provider"
|
|
5
|
-
import type * as ModelsDev from "@miaw/core/models-dev"
|
|
6
|
-
import { iife } from "@/util/iife"
|
|
7
|
-
|
|
8
|
-
type Modality = NonNullable<ModelsDev.Model["modalities"]>["input"][number]
|
|
9
|
-
|
|
10
|
-
function mimeToModality(mime: string): Modality | undefined {
|
|
11
|
-
if (mime.startsWith("image/")) return "image"
|
|
12
|
-
if (mime.startsWith("audio/")) return "audio"
|
|
13
|
-
if (mime.startsWith("video/")) return "video"
|
|
14
|
-
if (mime === "application/pdf") return "pdf"
|
|
15
|
-
return undefined
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const OUTPUT_TOKEN_MAX = 32_000
|
|
19
|
-
|
|
20
|
-
// OpenAI Responses `include` value that returns the encrypted reasoning state
|
|
21
|
-
// needed for stateless multi-turn reasoning (store: false). Hoisted so every
|
|
22
|
-
// branch that requests it stays in lockstep.
|
|
23
|
-
const INCLUDE_ENCRYPTED_REASONING = ["reasoning.encrypted_content"] as const
|
|
24
|
-
|
|
25
|
-
export function sanitizeSurrogates(content: string) {
|
|
26
|
-
return content.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD")
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Maps npm package to the key the AI SDK expects for providerOptions
|
|
30
|
-
function sdkKey(npm: string): string | undefined {
|
|
31
|
-
switch (npm) {
|
|
32
|
-
case "@ai-sdk/github-copilot":
|
|
33
|
-
return "copilot"
|
|
34
|
-
case "@ai-sdk/azure":
|
|
35
|
-
return "azure"
|
|
36
|
-
case "@ai-sdk/openai":
|
|
37
|
-
return "openai"
|
|
38
|
-
case "@ai-sdk/amazon-bedrock/mantle":
|
|
39
|
-
return "openai"
|
|
40
|
-
case "@ai-sdk/amazon-bedrock":
|
|
41
|
-
return "bedrock"
|
|
42
|
-
case "@ai-sdk/anthropic":
|
|
43
|
-
case "@ai-sdk/google-vertex/anthropic":
|
|
44
|
-
return "anthropic"
|
|
45
|
-
case "@ai-sdk/google-vertex":
|
|
46
|
-
return "vertex"
|
|
47
|
-
case "@ai-sdk/google":
|
|
48
|
-
return "google"
|
|
49
|
-
case "@ai-sdk/gateway":
|
|
50
|
-
return "gateway"
|
|
51
|
-
case "@openrouter/ai-sdk-provider":
|
|
52
|
-
return "openrouter"
|
|
53
|
-
case "ai-gateway-provider":
|
|
54
|
-
// ai-gateway-provider/unified wraps createOpenAICompatible({ name: "Unified" }),
|
|
55
|
-
// and @ai-sdk/openai-compatible parses compatibleOptions from one of
|
|
56
|
-
// "openai-compatible" / "openaiCompatible" / "Unified" / "unified". The
|
|
57
|
-
// "openai-compatible" key emits a deprecation warning at runtime, so we
|
|
58
|
-
// pick the camelCase form the SDK now treats as canonical.
|
|
59
|
-
return "openaiCompatible"
|
|
60
|
-
}
|
|
61
|
-
return undefined
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// TODO: fix this stupid inefficient dogshit function
|
|
65
|
-
function normalizeMessages(
|
|
66
|
-
msgs: ModelMessage[],
|
|
67
|
-
model: Provider.Model,
|
|
68
|
-
_options: Record<string, unknown>,
|
|
69
|
-
): ModelMessage[] {
|
|
70
|
-
const sanitizeToolResultOutput = (content: ToolResultPart) => {
|
|
71
|
-
if (content.output.type === "text" || content.output.type === "error-text") {
|
|
72
|
-
content.output.value = sanitizeSurrogates(content.output.value)
|
|
73
|
-
}
|
|
74
|
-
if (content.output.type === "content") {
|
|
75
|
-
content.output.value = content.output.value.map((item) => {
|
|
76
|
-
if (item.type === "text") {
|
|
77
|
-
item.text = sanitizeSurrogates(item.text)
|
|
78
|
-
}
|
|
79
|
-
return item
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
return content
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
msgs = msgs.map((msg) => {
|
|
86
|
-
switch (msg.role) {
|
|
87
|
-
case "tool":
|
|
88
|
-
if (!Array.isArray(msg.content)) return msg
|
|
89
|
-
msg.content = msg.content.map((content) => {
|
|
90
|
-
if (content.type === "tool-result") {
|
|
91
|
-
return sanitizeToolResultOutput(content)
|
|
92
|
-
}
|
|
93
|
-
return content
|
|
94
|
-
})
|
|
95
|
-
return msg
|
|
96
|
-
|
|
97
|
-
case "system":
|
|
98
|
-
msg.content = sanitizeSurrogates(msg.content)
|
|
99
|
-
return msg
|
|
100
|
-
|
|
101
|
-
case "user":
|
|
102
|
-
if (typeof msg.content === "string") {
|
|
103
|
-
msg.content = sanitizeSurrogates(msg.content)
|
|
104
|
-
} else {
|
|
105
|
-
msg.content = msg.content.map((content) => {
|
|
106
|
-
if (content.type === "text") {
|
|
107
|
-
content.text = sanitizeSurrogates(content.text)
|
|
108
|
-
}
|
|
109
|
-
return content
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
return msg
|
|
113
|
-
|
|
114
|
-
case "assistant":
|
|
115
|
-
if (typeof msg.content === "string") {
|
|
116
|
-
msg.content = sanitizeSurrogates(msg.content)
|
|
117
|
-
} else {
|
|
118
|
-
msg.content = msg.content.map((content) => {
|
|
119
|
-
if (content.type === "text" || content.type === "reasoning") {
|
|
120
|
-
content.text = sanitizeSurrogates(content.text)
|
|
121
|
-
}
|
|
122
|
-
if (content.type === "tool-result") {
|
|
123
|
-
return sanitizeToolResultOutput(content)
|
|
124
|
-
}
|
|
125
|
-
return content
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
return msg
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
// Anthropic rejects messages with empty content - filter out empty string messages
|
|
133
|
-
// and remove empty text/reasoning parts from array content
|
|
134
|
-
if (model.api.npm === "@ai-sdk/anthropic") {
|
|
135
|
-
msgs = msgs
|
|
136
|
-
.map((msg) => {
|
|
137
|
-
if (typeof msg.content === "string") {
|
|
138
|
-
if (msg.content === "") return undefined
|
|
139
|
-
return msg
|
|
140
|
-
}
|
|
141
|
-
if (!Array.isArray(msg.content)) return msg
|
|
142
|
-
const filtered = msg.content.filter((part) => {
|
|
143
|
-
if (part.type === "text") {
|
|
144
|
-
return part.text !== ""
|
|
145
|
-
}
|
|
146
|
-
if (part.type === "reasoning") {
|
|
147
|
-
return (
|
|
148
|
-
part.text.trim().length > 0 ||
|
|
149
|
-
part.providerOptions?.anthropic?.signature != null ||
|
|
150
|
-
part.providerOptions?.anthropic?.redactedData != null
|
|
151
|
-
)
|
|
152
|
-
}
|
|
153
|
-
return true
|
|
154
|
-
})
|
|
155
|
-
if (filtered.length === 0) return undefined
|
|
156
|
-
return { ...msg, content: filtered }
|
|
157
|
-
})
|
|
158
|
-
.filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "")
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Bedrock specific transforms
|
|
162
|
-
if (model.api.npm === "@ai-sdk/amazon-bedrock") {
|
|
163
|
-
msgs = msgs
|
|
164
|
-
.map((msg) => {
|
|
165
|
-
if (typeof msg.content === "string") {
|
|
166
|
-
if (msg.content === "") return undefined
|
|
167
|
-
return msg
|
|
168
|
-
}
|
|
169
|
-
if (!Array.isArray(msg.content)) return msg
|
|
170
|
-
const filtered = msg.content.filter((part) => {
|
|
171
|
-
if (part.type === "text") {
|
|
172
|
-
return part.text !== ""
|
|
173
|
-
}
|
|
174
|
-
if (part.type === "reasoning") {
|
|
175
|
-
return (
|
|
176
|
-
part.text.trim().length > 0 ||
|
|
177
|
-
part.providerOptions?.bedrock?.signature != null ||
|
|
178
|
-
part.providerOptions?.bedrock?.redactedData != null
|
|
179
|
-
)
|
|
180
|
-
}
|
|
181
|
-
return true
|
|
182
|
-
})
|
|
183
|
-
if (filtered.length === 0) return undefined
|
|
184
|
-
return { ...msg, content: filtered }
|
|
185
|
-
})
|
|
186
|
-
.filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "")
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (model.api.id.includes("claude")) {
|
|
190
|
-
const scrub = (id: string) => id.replace(/[^a-zA-Z0-9_-]/g, "_")
|
|
191
|
-
msgs = msgs.map((msg) => {
|
|
192
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
193
|
-
return {
|
|
194
|
-
...msg,
|
|
195
|
-
content: msg.content.map((part) => {
|
|
196
|
-
if (part.type === "tool-call" || part.type === "tool-result") {
|
|
197
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
198
|
-
}
|
|
199
|
-
return part
|
|
200
|
-
}),
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (msg.role === "tool" && Array.isArray(msg.content)) {
|
|
204
|
-
return {
|
|
205
|
-
...msg,
|
|
206
|
-
content: msg.content.map((part) => {
|
|
207
|
-
if (part.type === "tool-result") {
|
|
208
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
209
|
-
}
|
|
210
|
-
return part
|
|
211
|
-
}),
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return msg
|
|
215
|
-
})
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
model.providerID === "mistral" ||
|
|
220
|
-
model.api.id.toLowerCase().includes("mistral") ||
|
|
221
|
-
model.api.id.toLocaleLowerCase().includes("devstral")
|
|
222
|
-
) {
|
|
223
|
-
const scrub = (id: string) => {
|
|
224
|
-
return id
|
|
225
|
-
.replace(/[^a-zA-Z0-9]/g, "") // Remove non-alphanumeric characters
|
|
226
|
-
.substring(0, 9) // Take first 9 characters
|
|
227
|
-
.padEnd(9, "0") // Pad with zeros if less than 9 characters
|
|
228
|
-
}
|
|
229
|
-
const result: ModelMessage[] = []
|
|
230
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
231
|
-
const msg = msgs[i]
|
|
232
|
-
const nextMsg = msgs[i + 1]
|
|
233
|
-
|
|
234
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
235
|
-
msg.content = msg.content.map((part) => {
|
|
236
|
-
if (part.type === "tool-call" || part.type === "tool-result") {
|
|
237
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
238
|
-
}
|
|
239
|
-
return part
|
|
240
|
-
})
|
|
241
|
-
}
|
|
242
|
-
if (msg.role === "tool" && Array.isArray(msg.content)) {
|
|
243
|
-
msg.content = msg.content.map((part) => {
|
|
244
|
-
if (part.type === "tool-result") {
|
|
245
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
246
|
-
}
|
|
247
|
-
return part
|
|
248
|
-
})
|
|
249
|
-
}
|
|
250
|
-
result.push(msg)
|
|
251
|
-
|
|
252
|
-
// Fix message sequence: tool messages cannot be followed by user messages
|
|
253
|
-
if (msg.role === "tool" && nextMsg?.role === "user") {
|
|
254
|
-
result.push({
|
|
255
|
-
role: "assistant",
|
|
256
|
-
content: [
|
|
257
|
-
{
|
|
258
|
-
type: "text",
|
|
259
|
-
text: "Done.",
|
|
260
|
-
},
|
|
261
|
-
],
|
|
262
|
-
})
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return result
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Deepseek requires all assistant messages to have reasoning on them
|
|
269
|
-
if (model.api.id.toLowerCase().includes("deepseek")) {
|
|
270
|
-
msgs = msgs.map((msg) => {
|
|
271
|
-
if (msg.role !== "assistant") return msg
|
|
272
|
-
if (Array.isArray(msg.content)) {
|
|
273
|
-
if (msg.content.some((part) => part.type === "reasoning")) return msg
|
|
274
|
-
return { ...msg, content: [...msg.content, { type: "reasoning", text: "" }] }
|
|
275
|
-
}
|
|
276
|
-
return {
|
|
277
|
-
...msg,
|
|
278
|
-
content: [
|
|
279
|
-
...(msg.content ? [{ type: "text" as const, text: msg.content }] : []),
|
|
280
|
-
{ type: "reasoning" as const, text: "" },
|
|
281
|
-
],
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (
|
|
287
|
-
typeof model.capabilities.interleaved === "object" &&
|
|
288
|
-
model.capabilities.interleaved.field &&
|
|
289
|
-
model.api.npm !== "@openrouter/ai-sdk-provider"
|
|
290
|
-
) {
|
|
291
|
-
const field = model.capabilities.interleaved.field
|
|
292
|
-
return msgs.map((msg) => {
|
|
293
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
294
|
-
const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
|
|
295
|
-
const reasoningText = reasoningParts.map((part: any) => part.text).join("")
|
|
296
|
-
|
|
297
|
-
// Filter out reasoning parts from content
|
|
298
|
-
const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
|
|
299
|
-
|
|
300
|
-
// Include reasoning_content | reasoning_details directly on the message for all assistant messages.
|
|
301
|
-
// Always set the field even when empty — some providers (e.g. DeepSeek) may return empty
|
|
302
|
-
// reasoning_content which still needs to be sent back in subsequent requests.
|
|
303
|
-
return {
|
|
304
|
-
...msg,
|
|
305
|
-
content: filteredContent,
|
|
306
|
-
providerOptions: {
|
|
307
|
-
...msg.providerOptions,
|
|
308
|
-
openaiCompatible: {
|
|
309
|
-
...msg.providerOptions?.openaiCompatible,
|
|
310
|
-
[field]: reasoningText,
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return msg
|
|
317
|
-
})
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
return msgs
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function applyCaching(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
|
|
324
|
-
const system = msgs.filter((msg) => msg.role === "system").slice(0, 2)
|
|
325
|
-
const final = msgs.filter((msg) => msg.role !== "system").slice(-2)
|
|
326
|
-
|
|
327
|
-
const providerOptions = {
|
|
328
|
-
anthropic: {
|
|
329
|
-
cacheControl: { type: "ephemeral" },
|
|
330
|
-
},
|
|
331
|
-
openrouter: {
|
|
332
|
-
cacheControl: { type: "ephemeral" },
|
|
333
|
-
},
|
|
334
|
-
bedrock: {
|
|
335
|
-
cachePoint: { type: "default" },
|
|
336
|
-
},
|
|
337
|
-
openaiCompatible: {
|
|
338
|
-
cache_control: { type: "ephemeral" },
|
|
339
|
-
},
|
|
340
|
-
copilot: {
|
|
341
|
-
copilot_cache_control: { type: "ephemeral" },
|
|
342
|
-
},
|
|
343
|
-
alibaba: {
|
|
344
|
-
cacheControl: { type: "ephemeral" },
|
|
345
|
-
},
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
for (const msg of unique([...system, ...final])) {
|
|
349
|
-
const useMessageLevelOptions =
|
|
350
|
-
model.providerID === "anthropic" ||
|
|
351
|
-
model.providerID.includes("bedrock") ||
|
|
352
|
-
model.api.npm === "@ai-sdk/amazon-bedrock"
|
|
353
|
-
const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(msg.content) && msg.content.length > 0
|
|
354
|
-
|
|
355
|
-
if (shouldUseContentOptions) {
|
|
356
|
-
const lastContent = msg.content[msg.content.length - 1]
|
|
357
|
-
if (
|
|
358
|
-
lastContent &&
|
|
359
|
-
typeof lastContent === "object" &&
|
|
360
|
-
lastContent.type !== "tool-approval-request" &&
|
|
361
|
-
lastContent.type !== "tool-approval-response"
|
|
362
|
-
) {
|
|
363
|
-
lastContent.providerOptions = mergeDeep(lastContent.providerOptions ?? {}, providerOptions)
|
|
364
|
-
continue
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
msg.providerOptions = mergeDeep(msg.providerOptions ?? {}, providerOptions)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return msgs
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function unsupportedParts(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
|
|
375
|
-
return msgs.map((msg) => {
|
|
376
|
-
if (msg.role !== "user" || !Array.isArray(msg.content)) return msg
|
|
377
|
-
|
|
378
|
-
const filtered = msg.content.map((part) => {
|
|
379
|
-
if (part.type !== "file" && part.type !== "image") return part
|
|
380
|
-
|
|
381
|
-
// Check for empty base64 image data
|
|
382
|
-
if (part.type === "image") {
|
|
383
|
-
const imageStr = String(part.image)
|
|
384
|
-
if (imageStr.startsWith("data:")) {
|
|
385
|
-
const match = imageStr.match(/^data:([^;]+);base64,(.*)$/)
|
|
386
|
-
if (match && (!match[2] || match[2].length === 0)) {
|
|
387
|
-
return {
|
|
388
|
-
type: "text" as const,
|
|
389
|
-
text: "ERROR: Image file is empty or corrupted. Please provide a valid image.",
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const mime = part.type === "image" ? String(part.image).split(";")[0].replace("data:", "") : part.mediaType
|
|
396
|
-
const filename = part.type === "file" ? part.filename : undefined
|
|
397
|
-
const modality = mimeToModality(mime)
|
|
398
|
-
if (!modality) return part
|
|
399
|
-
if (model.capabilities.input[modality]) return part
|
|
400
|
-
|
|
401
|
-
const name = filename ? `"${filename}"` : modality
|
|
402
|
-
return {
|
|
403
|
-
type: "text" as const,
|
|
404
|
-
text: `ERROR: Cannot read ${name} (this model does not support ${modality} input). Inform the user.`,
|
|
405
|
-
}
|
|
406
|
-
})
|
|
407
|
-
|
|
408
|
-
return { ...msg, content: filtered }
|
|
409
|
-
})
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function mapProviderOptions(
|
|
413
|
-
msgs: ModelMessage[],
|
|
414
|
-
transform: (options: Record<string, any> | undefined) => Record<string, any> | undefined,
|
|
415
|
-
) {
|
|
416
|
-
return msgs.map((msg) => {
|
|
417
|
-
if (!Array.isArray(msg.content)) return { ...msg, providerOptions: transform(msg.providerOptions) }
|
|
418
|
-
return {
|
|
419
|
-
...msg,
|
|
420
|
-
providerOptions: transform(msg.providerOptions),
|
|
421
|
-
content: msg.content.map((part) =>
|
|
422
|
-
part.type === "tool-approval-request" || part.type === "tool-approval-response"
|
|
423
|
-
? part
|
|
424
|
-
: { ...part, providerOptions: transform(part.providerOptions) },
|
|
425
|
-
),
|
|
426
|
-
} as typeof msg
|
|
427
|
-
})
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
export function message(msgs: ModelMessage[], model: Provider.Model, options: Record<string, unknown>) {
|
|
431
|
-
msgs = unsupportedParts(msgs, model)
|
|
432
|
-
msgs = normalizeMessages(msgs, model, options)
|
|
433
|
-
if (
|
|
434
|
-
(model.providerID === "anthropic" ||
|
|
435
|
-
model.providerID === "google-vertex-anthropic" ||
|
|
436
|
-
model.api.id.includes("anthropic") ||
|
|
437
|
-
model.api.id.includes("claude") ||
|
|
438
|
-
model.id.includes("anthropic") ||
|
|
439
|
-
model.id.includes("claude") ||
|
|
440
|
-
model.api.npm === "@ai-sdk/anthropic" ||
|
|
441
|
-
model.api.npm === "@ai-sdk/alibaba") &&
|
|
442
|
-
model.api.npm !== "@ai-sdk/gateway"
|
|
443
|
-
) {
|
|
444
|
-
msgs = applyCaching(msgs, model)
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Remap providerOptions keys from stored providerID to expected SDK key
|
|
448
|
-
const key = sdkKey(model.api.npm)
|
|
449
|
-
if (key && key !== model.providerID) {
|
|
450
|
-
const remap = (opts: Record<string, any> | undefined) => {
|
|
451
|
-
if (!opts) return opts
|
|
452
|
-
if (!(model.providerID in opts)) return opts
|
|
453
|
-
const result = { ...opts }
|
|
454
|
-
result[key] = result[model.providerID]
|
|
455
|
-
delete result[model.providerID]
|
|
456
|
-
return result
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
msgs = mapProviderOptions(msgs, remap)
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Strip Responses item IDs before serialization, following Codex and keeping signed request bodies immutable.
|
|
463
|
-
if (
|
|
464
|
-
options.store !== true &&
|
|
465
|
-
key &&
|
|
466
|
-
["@ai-sdk/openai", "@ai-sdk/azure", "@ai-sdk/amazon-bedrock/mantle"].includes(model.api.npm)
|
|
467
|
-
) {
|
|
468
|
-
msgs = mapProviderOptions(msgs, (options) => {
|
|
469
|
-
if (!options?.[key] || !("itemId" in options[key])) return options
|
|
470
|
-
const metadata = { ...options[key] }
|
|
471
|
-
delete metadata.itemId
|
|
472
|
-
return { ...options, [key]: metadata }
|
|
473
|
-
})
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return msgs
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
export function temperature(model: Provider.Model) {
|
|
480
|
-
const id = model.id.toLowerCase()
|
|
481
|
-
if (id.includes("north-mini-code")) return 1.0
|
|
482
|
-
if (id.includes("qwen")) return 0.55
|
|
483
|
-
if (id.includes("claude")) return undefined
|
|
484
|
-
if (id.includes("gemini")) return 1.0
|
|
485
|
-
if (id.includes("glm-4.6")) return 1.0
|
|
486
|
-
if (id.includes("glm-4.7")) return 1.0
|
|
487
|
-
if (id.includes("minimax-m2")) return 1.0
|
|
488
|
-
if (id.includes("kimi-k2")) {
|
|
489
|
-
// kimi-k2-thinking & kimi-k2.5 && kimi-k2p5 && kimi-k2-5
|
|
490
|
-
if (["thinking", "k2.", "k2p", "k2-5"].some((s) => id.includes(s))) {
|
|
491
|
-
return 1.0
|
|
492
|
-
}
|
|
493
|
-
return 0.6
|
|
494
|
-
}
|
|
495
|
-
return undefined
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
export function topP(model: Provider.Model) {
|
|
499
|
-
const id = model.id.toLowerCase()
|
|
500
|
-
if (id.includes("qwen")) return 1
|
|
501
|
-
if (["minimax-m2", "gemini", "kimi-k2.5", "kimi-k2p5", "kimi-k2-5"].some((s) => id.includes(s))) {
|
|
502
|
-
return 0.95
|
|
503
|
-
}
|
|
504
|
-
return undefined
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export function topK(model: Provider.Model) {
|
|
508
|
-
const id = model.id.toLowerCase()
|
|
509
|
-
if (id.includes("minimax-m2")) {
|
|
510
|
-
if (["m2.", "m25", "m21"].some((s) => id.includes(s))) return 40
|
|
511
|
-
return 20
|
|
512
|
-
}
|
|
513
|
-
if (id.includes("gemini")) return 64
|
|
514
|
-
return undefined
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const WIDELY_SUPPORTED_EFFORTS = ["low", "medium", "high"]
|
|
518
|
-
const OPENAI_EFFORTS = ["none", "minimal", ...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
519
|
-
const OPENAI_GPT5_1_EFFORTS = ["none", ...WIDELY_SUPPORTED_EFFORTS]
|
|
520
|
-
const OPENAI_GPT5_2_PLUS_EFFORTS = [...OPENAI_GPT5_1_EFFORTS, "xhigh"]
|
|
521
|
-
const OPENAI_GPT5_PRO_EFFORTS = ["high"]
|
|
522
|
-
const OPENAI_GPT5_PRO_2_PLUS_EFFORTS = ["medium", "high", "xhigh"]
|
|
523
|
-
const OPENAI_GPT5_CHAT_EFFORTS = ["medium"]
|
|
524
|
-
const OPENAI_GPT5_CODEX_XHIGH_EFFORTS = [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
525
|
-
const OPENAI_GPT5_CODEX_3_PLUS_EFFORTS = ["none", ...OPENAI_GPT5_CODEX_XHIGH_EFFORTS]
|
|
526
|
-
|
|
527
|
-
// OpenAI rolled out the `none` reasoning_effort tier on this date (Responses API).
|
|
528
|
-
// Models released before it 400 on `reasoning_effort: "none"`, so we only expose
|
|
529
|
-
// it as a variant for models new enough to accept it.
|
|
530
|
-
const OPENAI_NONE_EFFORT_RELEASE_DATE = "2025-11-13"
|
|
531
|
-
|
|
532
|
-
// OpenAI rolled out the `xhigh` reasoning_effort tier on this date. Same reasoning.
|
|
533
|
-
const OPENAI_XHIGH_EFFORT_RELEASE_DATE = "2025-12-04"
|
|
534
|
-
|
|
535
|
-
// Matches members of the gpt-5 family across the id formats we encounter:
|
|
536
|
-
// "gpt-5", "gpt-5-nano", "gpt-5.4", "openai/gpt-5.4-codex".
|
|
537
|
-
// Anchored to start-of-string or "/" so it doesn't false-match "gpt-50" or "gpt-5o".
|
|
538
|
-
const GPT5_FAMILY_RE = /(?:^|\/)gpt-5(?:[.-]|$)/
|
|
539
|
-
const GPT5_VERSION_RE = /(?:^|\/)gpt-5[.-](\d+)(?:[.-]|$)/
|
|
540
|
-
const GPT5_PRO_RE = /(?:^|\/)gpt-5[.-]?pro(?:[.-]|$)/
|
|
541
|
-
const GPT5_VERSIONED_PRO_RE = /(?:^|\/)gpt-5[.-]\d+[.-]pro(?:[.-]|$)/
|
|
542
|
-
|
|
543
|
-
function gpt5Version(apiId: string) {
|
|
544
|
-
return Number(GPT5_VERSION_RE.exec(apiId)?.[1]) || undefined
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function versionedGpt5ReasoningEfforts(apiId: string) {
|
|
548
|
-
if (GPT5_VERSIONED_PRO_RE.test(apiId)) return OPENAI_GPT5_PRO_2_PLUS_EFFORTS
|
|
549
|
-
const version = gpt5Version(apiId)
|
|
550
|
-
if (version === undefined) return undefined
|
|
551
|
-
if (version === 1) return OPENAI_GPT5_1_EFFORTS
|
|
552
|
-
return OPENAI_GPT5_2_PLUS_EFFORTS
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function gpt5CodexReasoningEfforts(apiId: string) {
|
|
556
|
-
if (!GPT5_FAMILY_RE.test(apiId) || !apiId.includes("codex")) return undefined
|
|
557
|
-
const version = gpt5Version(apiId)
|
|
558
|
-
if (version !== undefined && version >= 3) return OPENAI_GPT5_CODEX_3_PLUS_EFFORTS
|
|
559
|
-
if (apiId.includes("codex-max") || (version !== undefined && version >= 2)) return OPENAI_GPT5_CODEX_XHIGH_EFFORTS
|
|
560
|
-
return WIDELY_SUPPORTED_EFFORTS
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
function gpt5ChatReasoningEfforts(apiId: string) {
|
|
564
|
-
if (!GPT5_FAMILY_RE.test(apiId) || !apiId.includes("-chat")) return undefined
|
|
565
|
-
return gpt5Version(apiId) === undefined ? [] : OPENAI_GPT5_CHAT_EFFORTS
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Computes the reasoning_effort tiers an OpenAI (or OpenAI-compatible upstream
|
|
569
|
-
// routed through it, e.g. cf-ai-gateway) model exposes. Effort order: weakest
|
|
570
|
-
// to strongest.
|
|
571
|
-
function openaiReasoningEfforts(apiId: string, releaseDate: string) {
|
|
572
|
-
const id = apiId.toLowerCase()
|
|
573
|
-
if (id.includes("deep-research")) return ["medium"]
|
|
574
|
-
const chatEfforts = gpt5ChatReasoningEfforts(id)
|
|
575
|
-
if (chatEfforts) return chatEfforts
|
|
576
|
-
if (GPT5_PRO_RE.test(id)) return OPENAI_GPT5_PRO_EFFORTS
|
|
577
|
-
const codexEfforts = gpt5CodexReasoningEfforts(id)
|
|
578
|
-
if (codexEfforts) return codexEfforts
|
|
579
|
-
const versionedEfforts = versionedGpt5ReasoningEfforts(id)
|
|
580
|
-
// GPT-5.1 replaced GPT-5's `minimal` effort with `none`; GPT-5.2+
|
|
581
|
-
// additionally accepts `xhigh`. Model pages list the supported subset.
|
|
582
|
-
if (versionedEfforts) return versionedEfforts
|
|
583
|
-
const efforts = [...WIDELY_SUPPORTED_EFFORTS]
|
|
584
|
-
if (GPT5_FAMILY_RE.test(id)) efforts.unshift("minimal")
|
|
585
|
-
if (releaseDate >= OPENAI_NONE_EFFORT_RELEASE_DATE) efforts.unshift("none")
|
|
586
|
-
if (releaseDate >= OPENAI_XHIGH_EFFORT_RELEASE_DATE) efforts.push("xhigh")
|
|
587
|
-
return efforts
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function openaiCompatibleReasoningEfforts(id: string) {
|
|
591
|
-
const apiId = id.toLowerCase()
|
|
592
|
-
const chatEfforts = gpt5ChatReasoningEfforts(apiId)
|
|
593
|
-
if (chatEfforts) return chatEfforts
|
|
594
|
-
if (GPT5_PRO_RE.test(apiId)) return OPENAI_GPT5_PRO_EFFORTS
|
|
595
|
-
return gpt5CodexReasoningEfforts(apiId) ?? versionedGpt5ReasoningEfforts(apiId) ?? OPENAI_EFFORTS
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
function anthropicOpus47OrLater(apiId: string) {
|
|
599
|
-
// Matches "opus-4.7" (Anthropic/Bedrock/Vertex) and "claude-4.7-opus" (SAP AI Core inverted).
|
|
600
|
-
// Greedy \d+ correctly extends to multi-digit majors (e.g. "claude-10.0-opus") for forward compatibility.
|
|
601
|
-
const version = /opus-(\d+)[.-](\d+)(?:[.@-]|$)|claude-(\d+)[.-](\d+)-opus(?:[.@-]|$)/i.exec(apiId)
|
|
602
|
-
if (!version) return false
|
|
603
|
-
const major = Number(version[1] ?? version[3])
|
|
604
|
-
const minor = Number(version[2] ?? version[4])
|
|
605
|
-
return major > 4 || (major === 4 && minor >= 7)
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
function anthropicAdaptiveEfforts(apiId: string): string[] | null {
|
|
609
|
-
if (anthropicOpus47OrLater(apiId) || apiId.includes("fable-5")) {
|
|
610
|
-
return ["low", "medium", "high", "xhigh", "max"]
|
|
611
|
-
}
|
|
612
|
-
if (
|
|
613
|
-
["opus-4-6", "opus-4.6", "4-6-opus", "4.6-opus", "sonnet-4-6", "sonnet-4.6", "4-6-sonnet", "4.6-sonnet"].some((v) =>
|
|
614
|
-
apiId.includes(v),
|
|
615
|
-
)
|
|
616
|
-
) {
|
|
617
|
-
return ["low", "medium", "high", "max"]
|
|
618
|
-
}
|
|
619
|
-
return null
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
function anthropicOmitsThinking(apiId: string) {
|
|
623
|
-
return anthropicOpus47OrLater(apiId) || apiId.includes("fable-5")
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
function googleThinkingLevelEfforts(apiId: string) {
|
|
627
|
-
const id = apiId.toLowerCase()
|
|
628
|
-
if (!id.includes("gemini-3")) return ["low", "high"]
|
|
629
|
-
if (id.includes("flash-image")) return ["minimal", "high"]
|
|
630
|
-
if (id.includes("pro-image")) return ["high"]
|
|
631
|
-
if (id.includes("flash")) return ["minimal", "low", "medium", "high"]
|
|
632
|
-
return ["low", "medium", "high"]
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
function googleThinkingBudgetMax(apiId: string) {
|
|
636
|
-
const id = apiId.toLowerCase()
|
|
637
|
-
if (id.includes("2.5") && id.includes("pro") && !id.includes("flash")) return 32_768
|
|
638
|
-
return 24_576
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// SAP's Zod schema drops unknown top-level keys; reasoning controls survive
|
|
642
|
-
// only via `modelParams` (catchall), forwarded verbatim by the SAP SDKs.
|
|
643
|
-
function wrapInSapModelParams(variants: Record<string, Record<string, any>>): Record<string, Record<string, any>> {
|
|
644
|
-
return Object.fromEntries(Object.entries(variants).map(([k, v]) => [k, { modelParams: v }]))
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
function googleThinkingVariants(model: Provider.Model): Record<string, Record<string, any>> {
|
|
648
|
-
const id = model.api.id.toLowerCase()
|
|
649
|
-
if (id.includes("2.5")) {
|
|
650
|
-
return {
|
|
651
|
-
high: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } },
|
|
652
|
-
max: {
|
|
653
|
-
thinkingConfig: { includeThoughts: true, thinkingBudget: googleThinkingBudgetMax(id) },
|
|
654
|
-
},
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
return Object.fromEntries(
|
|
658
|
-
googleThinkingLevelEfforts(id).map((effort) => [
|
|
659
|
-
effort,
|
|
660
|
-
{ thinkingConfig: { includeThoughts: true, thinkingLevel: effort } },
|
|
661
|
-
]),
|
|
662
|
-
)
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
export function variants(model: Provider.Model): Record<string, Record<string, any>> {
|
|
666
|
-
if (!model.capabilities.reasoning) return {}
|
|
667
|
-
|
|
668
|
-
const id = model.id.toLowerCase()
|
|
669
|
-
if (
|
|
670
|
-
model.api.id.toLowerCase().includes("minimax-m3") &&
|
|
671
|
-
["@ai-sdk/anthropic", "@ai-sdk/openai-compatible"].includes(model.api.npm)
|
|
672
|
-
) {
|
|
673
|
-
return {
|
|
674
|
-
none: { thinking: { type: "disabled" } },
|
|
675
|
-
thinking: { thinking: { type: "adaptive" } },
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
const adaptiveThinkingOmitted = anthropicOmitsThinking(model.api.id)
|
|
679
|
-
const adaptiveEfforts = anthropicAdaptiveEfforts(model.api.id)
|
|
680
|
-
if (
|
|
681
|
-
id.includes("deepseek-chat") ||
|
|
682
|
-
id.includes("deepseek-reasoner") ||
|
|
683
|
-
id.includes("deepseek-r1") ||
|
|
684
|
-
id.includes("deepseek-v3") ||
|
|
685
|
-
id.includes("minimax") ||
|
|
686
|
-
id.includes("glm") ||
|
|
687
|
-
id.includes("kimi") ||
|
|
688
|
-
id.includes("k2p") ||
|
|
689
|
-
id.includes("qwen") ||
|
|
690
|
-
id.includes("big-pickle")
|
|
691
|
-
)
|
|
692
|
-
return {}
|
|
693
|
-
|
|
694
|
-
// see: https://docs.x.ai/docs/guides/reasoning#control-how-hard-the-model-thinks
|
|
695
|
-
if (id.includes("grok") && id.includes("grok-3-mini")) {
|
|
696
|
-
if (model.api.npm === "@openrouter/ai-sdk-provider") {
|
|
697
|
-
return {
|
|
698
|
-
low: { reasoning: { effort: "low" } },
|
|
699
|
-
high: { reasoning: { effort: "high" } },
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
return {
|
|
703
|
-
low: { reasoningEffort: "low" },
|
|
704
|
-
high: { reasoningEffort: "high" },
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
if (id.includes("grok")) return {}
|
|
708
|
-
|
|
709
|
-
switch (model.api.npm) {
|
|
710
|
-
case "@openrouter/ai-sdk-provider":
|
|
711
|
-
return Object.fromEntries(
|
|
712
|
-
(model.api.id.startsWith("openai/") || id.includes("gpt")
|
|
713
|
-
? openaiCompatibleReasoningEfforts(model.api.id)
|
|
714
|
-
: WIDELY_SUPPORTED_EFFORTS
|
|
715
|
-
).map((effort) => [effort, { reasoning: { effort } }]),
|
|
716
|
-
)
|
|
717
|
-
|
|
718
|
-
case "ai-gateway-provider": {
|
|
719
|
-
// Cloudflare AI Gateway routes every upstream through its OpenAI-compatible
|
|
720
|
-
// /v1/compat endpoint, so the body is always OAI-shaped. The gateway
|
|
721
|
-
// translates `reasoning_effort` to the upstream provider's native control
|
|
722
|
-
// (e.g. Anthropic thinking budgets) when needed. Variants therefore stay
|
|
723
|
-
// OAI-style for all upstreams, with an extended effort set for OpenAI
|
|
724
|
-
// models that support it.
|
|
725
|
-
if (model.api.id.startsWith("openai/")) {
|
|
726
|
-
const efforts = openaiReasoningEfforts(model.api.id, model.release_date)
|
|
727
|
-
return Object.fromEntries(efforts.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
728
|
-
}
|
|
729
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
case "@ai-sdk/gateway":
|
|
733
|
-
if (model.id.includes("anthropic")) {
|
|
734
|
-
if (adaptiveEfforts) {
|
|
735
|
-
return Object.fromEntries(
|
|
736
|
-
adaptiveEfforts.map((effort) => [
|
|
737
|
-
effort,
|
|
738
|
-
{
|
|
739
|
-
thinking: {
|
|
740
|
-
type: "adaptive",
|
|
741
|
-
// Newer adaptive-only models default `display` to "omitted", which
|
|
742
|
-
// returns empty thinking blocks. Force "summarized" so summaries
|
|
743
|
-
// survive (4.6/Sonnet 4.6 already default to "summarized").
|
|
744
|
-
...(adaptiveThinkingOmitted ? { display: "summarized" } : {}),
|
|
745
|
-
},
|
|
746
|
-
effort,
|
|
747
|
-
},
|
|
748
|
-
]),
|
|
749
|
-
)
|
|
750
|
-
}
|
|
751
|
-
return {
|
|
752
|
-
high: {
|
|
753
|
-
thinking: {
|
|
754
|
-
type: "enabled",
|
|
755
|
-
budgetTokens: 16000,
|
|
756
|
-
},
|
|
757
|
-
},
|
|
758
|
-
max: {
|
|
759
|
-
thinking: {
|
|
760
|
-
type: "enabled",
|
|
761
|
-
budgetTokens: 31999,
|
|
762
|
-
},
|
|
763
|
-
},
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
if (model.id.includes("google")) {
|
|
767
|
-
if (id.includes("2.5")) {
|
|
768
|
-
return {
|
|
769
|
-
high: {
|
|
770
|
-
thinkingConfig: {
|
|
771
|
-
includeThoughts: true,
|
|
772
|
-
thinkingBudget: 16000,
|
|
773
|
-
},
|
|
774
|
-
},
|
|
775
|
-
max: {
|
|
776
|
-
thinkingConfig: {
|
|
777
|
-
includeThoughts: true,
|
|
778
|
-
thinkingBudget: googleThinkingBudgetMax(id),
|
|
779
|
-
},
|
|
780
|
-
},
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
return Object.fromEntries(
|
|
784
|
-
["low", "high"].map((effort) => [
|
|
785
|
-
effort,
|
|
786
|
-
{
|
|
787
|
-
includeThoughts: true,
|
|
788
|
-
thinkingLevel: effort,
|
|
789
|
-
},
|
|
790
|
-
]),
|
|
791
|
-
)
|
|
792
|
-
}
|
|
793
|
-
return Object.fromEntries(
|
|
794
|
-
openaiCompatibleReasoningEfforts(model.api.id).map((effort) => [effort, { reasoningEffort: effort }]),
|
|
795
|
-
)
|
|
796
|
-
|
|
797
|
-
case "@ai-sdk/github-copilot":
|
|
798
|
-
if (model.id.includes("gemini")) {
|
|
799
|
-
// currently github copilot only returns thinking
|
|
800
|
-
return {}
|
|
801
|
-
}
|
|
802
|
-
if (model.id.includes("claude")) {
|
|
803
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
804
|
-
}
|
|
805
|
-
const copilotEfforts = iife(() => {
|
|
806
|
-
if (id.includes("5.1-codex-max") || id.includes("5.2") || id.includes("5.3"))
|
|
807
|
-
return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
808
|
-
const arr = [...WIDELY_SUPPORTED_EFFORTS]
|
|
809
|
-
if (id.includes("gpt-5") && model.release_date >= "2025-12-04") arr.push("xhigh")
|
|
810
|
-
return arr
|
|
811
|
-
})
|
|
812
|
-
return Object.fromEntries(
|
|
813
|
-
copilotEfforts.map((effort) => [
|
|
814
|
-
effort,
|
|
815
|
-
{
|
|
816
|
-
reasoningEffort: effort,
|
|
817
|
-
reasoningSummary: "auto",
|
|
818
|
-
include: INCLUDE_ENCRYPTED_REASONING,
|
|
819
|
-
},
|
|
820
|
-
]),
|
|
821
|
-
)
|
|
822
|
-
|
|
823
|
-
case "@ai-sdk/cerebras":
|
|
824
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/cerebras
|
|
825
|
-
case "@ai-sdk/togetherai":
|
|
826
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/togetherai
|
|
827
|
-
case "@ai-sdk/xai":
|
|
828
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/xai
|
|
829
|
-
case "@ai-sdk/deepinfra":
|
|
830
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/deepinfra
|
|
831
|
-
case "venice-ai-sdk-provider":
|
|
832
|
-
// https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort
|
|
833
|
-
case "@ai-sdk/openai-compatible":
|
|
834
|
-
if (model.api.id.toLowerCase().includes("north-mini-code")) {
|
|
835
|
-
return Object.fromEntries(["none", "high"].map((effort) => [effort, { reasoningEffort: effort }]))
|
|
836
|
-
}
|
|
837
|
-
const efforts = [...WIDELY_SUPPORTED_EFFORTS]
|
|
838
|
-
if (model.api.id.toLowerCase().includes("deepseek-v4")) {
|
|
839
|
-
efforts.push("max")
|
|
840
|
-
}
|
|
841
|
-
return Object.fromEntries(efforts.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
842
|
-
|
|
843
|
-
case "@ai-sdk/azure":
|
|
844
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/azure
|
|
845
|
-
if (id === "o1-mini") return {}
|
|
846
|
-
return Object.fromEntries(
|
|
847
|
-
openaiReasoningEfforts(id, model.release_date).map((effort) => [
|
|
848
|
-
effort,
|
|
849
|
-
{
|
|
850
|
-
reasoningEffort: effort,
|
|
851
|
-
reasoningSummary: "auto",
|
|
852
|
-
include: INCLUDE_ENCRYPTED_REASONING,
|
|
853
|
-
},
|
|
854
|
-
]),
|
|
855
|
-
)
|
|
856
|
-
case "@ai-sdk/amazon-bedrock/mantle":
|
|
857
|
-
case "@ai-sdk/openai": {
|
|
858
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/openai
|
|
859
|
-
const efforts = openaiReasoningEfforts(model.api.id, model.release_date)
|
|
860
|
-
return Object.fromEntries(
|
|
861
|
-
efforts.map((effort) => [
|
|
862
|
-
effort,
|
|
863
|
-
{
|
|
864
|
-
reasoningEffort: effort,
|
|
865
|
-
reasoningSummary: "auto",
|
|
866
|
-
include: INCLUDE_ENCRYPTED_REASONING,
|
|
867
|
-
},
|
|
868
|
-
]),
|
|
869
|
-
)
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
case "@ai-sdk/anthropic":
|
|
873
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/anthropic
|
|
874
|
-
case "@ai-sdk/google-vertex/anthropic":
|
|
875
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex#anthropic-provider
|
|
876
|
-
if (adaptiveEfforts) {
|
|
877
|
-
let efforts = [...adaptiveEfforts]
|
|
878
|
-
if (model.providerID === "github-copilot") {
|
|
879
|
-
if (model.api.id.includes("opus-4.7")) {
|
|
880
|
-
efforts = ["medium"]
|
|
881
|
-
}
|
|
882
|
-
// Efforts currently supported are: low, medium, high
|
|
883
|
-
efforts = efforts.filter((v) => v !== "max" && v !== "xhigh")
|
|
884
|
-
}
|
|
885
|
-
return Object.fromEntries(
|
|
886
|
-
efforts.map((effort) => [
|
|
887
|
-
effort,
|
|
888
|
-
{
|
|
889
|
-
thinking: {
|
|
890
|
-
type: "adaptive",
|
|
891
|
-
...(adaptiveThinkingOmitted ? { display: "summarized" } : {}),
|
|
892
|
-
},
|
|
893
|
-
effort,
|
|
894
|
-
},
|
|
895
|
-
]),
|
|
896
|
-
)
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
if (["opus-4-5", "opus-4.5"].some((v) => model.api.id.includes(v))) {
|
|
900
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { effort }]))
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
return {
|
|
904
|
-
high: {
|
|
905
|
-
thinking: {
|
|
906
|
-
type: "enabled",
|
|
907
|
-
budgetTokens: Math.min(16_000, Math.floor(model.limit.output / 2 - 1)),
|
|
908
|
-
},
|
|
909
|
-
},
|
|
910
|
-
max: {
|
|
911
|
-
thinking: {
|
|
912
|
-
type: "enabled",
|
|
913
|
-
budgetTokens: Math.min(31_999, model.limit.output - 1),
|
|
914
|
-
},
|
|
915
|
-
},
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
case "@ai-sdk/amazon-bedrock":
|
|
919
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock
|
|
920
|
-
if (adaptiveEfforts) {
|
|
921
|
-
return Object.fromEntries(
|
|
922
|
-
adaptiveEfforts.map((effort) => [
|
|
923
|
-
effort,
|
|
924
|
-
{
|
|
925
|
-
reasoningConfig: {
|
|
926
|
-
type: "adaptive",
|
|
927
|
-
maxReasoningEffort: effort,
|
|
928
|
-
...(adaptiveThinkingOmitted ? { display: "summarized" } : {}),
|
|
929
|
-
},
|
|
930
|
-
},
|
|
931
|
-
]),
|
|
932
|
-
)
|
|
933
|
-
}
|
|
934
|
-
// For Anthropic models on Bedrock, use reasoningConfig with budgetTokens
|
|
935
|
-
if (model.api.id.includes("anthropic")) {
|
|
936
|
-
return {
|
|
937
|
-
high: {
|
|
938
|
-
reasoningConfig: {
|
|
939
|
-
type: "enabled",
|
|
940
|
-
budgetTokens: 16000,
|
|
941
|
-
},
|
|
942
|
-
},
|
|
943
|
-
max: {
|
|
944
|
-
reasoningConfig: {
|
|
945
|
-
type: "enabled",
|
|
946
|
-
budgetTokens: 31999,
|
|
947
|
-
},
|
|
948
|
-
},
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
// For Amazon Nova models, use reasoningConfig with maxReasoningEffort
|
|
953
|
-
return Object.fromEntries(
|
|
954
|
-
WIDELY_SUPPORTED_EFFORTS.map((effort) => [
|
|
955
|
-
effort,
|
|
956
|
-
{
|
|
957
|
-
reasoningConfig: {
|
|
958
|
-
type: "enabled",
|
|
959
|
-
maxReasoningEffort: effort,
|
|
960
|
-
},
|
|
961
|
-
},
|
|
962
|
-
]),
|
|
963
|
-
)
|
|
964
|
-
|
|
965
|
-
case "@ai-sdk/google-vertex":
|
|
966
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex
|
|
967
|
-
case "@ai-sdk/google":
|
|
968
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai
|
|
969
|
-
return googleThinkingVariants(model)
|
|
970
|
-
|
|
971
|
-
case "@ai-sdk/mistral":
|
|
972
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/mistral
|
|
973
|
-
// https://docs.mistral.ai/capabilities/reasoning/adjustable
|
|
974
|
-
if (!model.capabilities.reasoning) return {}
|
|
975
|
-
// Only Mistral Small 4 and Medium 3.5 support reasoning
|
|
976
|
-
const MISTRAL_REASONING_IDS = [
|
|
977
|
-
"mistral-small-2603",
|
|
978
|
-
"mistral-small-latest",
|
|
979
|
-
"mistral-medium-3.5",
|
|
980
|
-
"mistral-medium-2604",
|
|
981
|
-
]
|
|
982
|
-
const mistralId = model.api.id.toLowerCase()
|
|
983
|
-
if (!MISTRAL_REASONING_IDS.some((id) => mistralId.includes(id))) return {}
|
|
984
|
-
return {
|
|
985
|
-
high: { reasoningEffort: "high" },
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
case "@ai-sdk/cohere":
|
|
989
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/cohere
|
|
990
|
-
return {}
|
|
991
|
-
|
|
992
|
-
case "@ai-sdk/groq":
|
|
993
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/groq
|
|
994
|
-
const groqEffort = ["none", ...WIDELY_SUPPORTED_EFFORTS]
|
|
995
|
-
return Object.fromEntries(
|
|
996
|
-
groqEffort.map((effort) => [
|
|
997
|
-
effort,
|
|
998
|
-
{
|
|
999
|
-
reasoningEffort: effort,
|
|
1000
|
-
},
|
|
1001
|
-
]),
|
|
1002
|
-
)
|
|
1003
|
-
|
|
1004
|
-
case "@ai-sdk/perplexity":
|
|
1005
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/perplexity
|
|
1006
|
-
return {}
|
|
1007
|
-
|
|
1008
|
-
case "@jerome-benoit/sap-ai-provider-v2": {
|
|
1009
|
-
if (id.includes("anthropic")) {
|
|
1010
|
-
if (adaptiveEfforts) {
|
|
1011
|
-
// Bedrock adaptive splits `effort` out into `output_config` (vs Anthropic
|
|
1012
|
-
// native which inlines it). Opus 4.7+ flipped `display` default to "omitted".
|
|
1013
|
-
return wrapInSapModelParams(
|
|
1014
|
-
Object.fromEntries(
|
|
1015
|
-
adaptiveEfforts.map((effort) => [
|
|
1016
|
-
effort,
|
|
1017
|
-
{
|
|
1018
|
-
thinking: { type: "adaptive", ...(adaptiveThinkingOmitted ? { display: "summarized" } : {}) },
|
|
1019
|
-
output_config: { effort },
|
|
1020
|
-
},
|
|
1021
|
-
]),
|
|
1022
|
-
),
|
|
1023
|
-
)
|
|
1024
|
-
}
|
|
1025
|
-
return wrapInSapModelParams({
|
|
1026
|
-
high: { thinking: { type: "enabled", budget_tokens: 16000 } },
|
|
1027
|
-
max: { thinking: { type: "enabled", budget_tokens: 31999 } },
|
|
1028
|
-
})
|
|
1029
|
-
}
|
|
1030
|
-
if (id.includes("gemini") && id.includes("2.5")) {
|
|
1031
|
-
return wrapInSapModelParams(googleThinkingVariants(model))
|
|
1032
|
-
}
|
|
1033
|
-
if (id.includes("gpt") || /\bo[1-9]/.test(id)) {
|
|
1034
|
-
const efforts = openaiReasoningEfforts(id, model.release_date)
|
|
1035
|
-
return wrapInSapModelParams(Object.fromEntries(efforts.map((effort) => [effort, { reasoning_effort: effort }])))
|
|
1036
|
-
}
|
|
1037
|
-
return wrapInSapModelParams(
|
|
1038
|
-
Object.fromEntries(["low", "medium", "high"].map((effort) => [effort, { reasoning_effort: effort }])),
|
|
1039
|
-
)
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
return {}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
export function options(input: {
|
|
1046
|
-
model: Provider.Model
|
|
1047
|
-
sessionID: string
|
|
1048
|
-
providerOptions?: Record<string, any>
|
|
1049
|
-
}): Record<string, any> {
|
|
1050
|
-
const result: Record<string, any> = {}
|
|
1051
|
-
|
|
1052
|
-
if (
|
|
1053
|
-
input.model.api.npm === "@ai-sdk/google-vertex/anthropic" ||
|
|
1054
|
-
(!input.model.api.id.includes("claude") && input.model.api.npm === "@ai-sdk/anthropic")
|
|
1055
|
-
) {
|
|
1056
|
-
result["toolStreaming"] = false
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
// openai and providers using openai package should set store to false by default.
|
|
1060
|
-
if (
|
|
1061
|
-
input.model.providerID === "openai" ||
|
|
1062
|
-
input.model.api.npm === "@ai-sdk/openai" ||
|
|
1063
|
-
input.model.api.npm === "@ai-sdk/github-copilot" ||
|
|
1064
|
-
input.model.api.npm === "@ai-sdk/amazon-bedrock/mantle"
|
|
1065
|
-
) {
|
|
1066
|
-
result["store"] = false
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
if (input.model.api.npm === "@ai-sdk/azure") {
|
|
1070
|
-
result["store"] = false
|
|
1071
|
-
result["promptCacheKey"] = input.sessionID
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
if (input.model.api.npm === "@openrouter/ai-sdk-provider" || input.model.api.npm === "@llmgateway/ai-sdk-provider") {
|
|
1075
|
-
result["usage"] = {
|
|
1076
|
-
include: true,
|
|
1077
|
-
}
|
|
1078
|
-
if (input.model.api.id.includes("gemini-3")) {
|
|
1079
|
-
result["reasoning"] = { effort: "high" }
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
if (
|
|
1084
|
-
input.model.providerID === "baseten" ||
|
|
1085
|
-
(input.model.providerID === "miaw" && ["kimi-k2-thinking", "glm-4.6"].includes(input.model.api.id))
|
|
1086
|
-
) {
|
|
1087
|
-
result["chat_template_args"] = { enable_thinking: true }
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
if (
|
|
1091
|
-
["zai", "zhipuai"].some((id) => input.model.providerID.includes(id)) &&
|
|
1092
|
-
input.model.api.npm === "@ai-sdk/openai-compatible"
|
|
1093
|
-
) {
|
|
1094
|
-
result["thinking"] = {
|
|
1095
|
-
type: "enabled",
|
|
1096
|
-
clear_thinking: false,
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
if (input.model.providerID === "openai" || input.providerOptions?.setCacheKey) {
|
|
1101
|
-
result["promptCacheKey"] = input.sessionID
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
if (input.model.api.npm === "@ai-sdk/google" || input.model.api.npm === "@ai-sdk/google-vertex") {
|
|
1105
|
-
if (input.model.capabilities.reasoning) {
|
|
1106
|
-
result["thinkingConfig"] = {
|
|
1107
|
-
includeThoughts: true,
|
|
1108
|
-
}
|
|
1109
|
-
if (input.model.api.id.includes("gemini-3")) {
|
|
1110
|
-
result["thinkingConfig"]["thinkingLevel"] = "high"
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
const modelId = input.model.api.id.toLowerCase()
|
|
1116
|
-
|
|
1117
|
-
// MiniMax's Anthropic interface defaults thinking off, unlike Chat Completions.
|
|
1118
|
-
if (modelId.includes("minimax-m3") && input.model.api.npm === "@ai-sdk/anthropic") {
|
|
1119
|
-
result["thinking"] = { type: "adaptive" }
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
// Enable thinking by default for kimi models using anthropic SDK
|
|
1123
|
-
if (
|
|
1124
|
-
(input.model.api.npm === "@ai-sdk/anthropic" || input.model.api.npm === "@ai-sdk/google-vertex/anthropic") &&
|
|
1125
|
-
(modelId.includes("k2p") || modelId.includes("kimi-k2.") || modelId.includes("kimi-k2p"))
|
|
1126
|
-
) {
|
|
1127
|
-
result["thinking"] = {
|
|
1128
|
-
type: "enabled",
|
|
1129
|
-
budgetTokens: Math.min(16_000, Math.floor(input.model.limit.output / 2 - 1)),
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
// Enable thinking for reasoning models on alibaba-cn (DashScope).
|
|
1134
|
-
// DashScope's OpenAI-compatible API requires `enable_thinking: true` in the request body
|
|
1135
|
-
// to return reasoning_content. Without it, models like kimi-k2.5, qwen-plus, qwen3, qwq,
|
|
1136
|
-
// deepseek-r1, etc. never output thinking/reasoning tokens.
|
|
1137
|
-
// Note: kimi-k2-thinking is excluded as it returns reasoning_content by default.
|
|
1138
|
-
if (
|
|
1139
|
-
input.model.providerID === "alibaba-cn" &&
|
|
1140
|
-
input.model.capabilities.reasoning &&
|
|
1141
|
-
input.model.api.npm === "@ai-sdk/openai-compatible" &&
|
|
1142
|
-
!modelId.includes("kimi-k2-thinking")
|
|
1143
|
-
) {
|
|
1144
|
-
result["enable_thinking"] = true
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
if (input.model.api.npm === "@ai-sdk/azure" && input.model.api.id.includes("gpt-5.5")) {
|
|
1148
|
-
result["reasoningSummary"] = "auto"
|
|
1149
|
-
return result
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
if (input.model.api.id.includes("gpt-5") && !input.model.api.id.includes("gpt-5-chat")) {
|
|
1153
|
-
if (!input.model.api.id.includes("gpt-5-pro")) {
|
|
1154
|
-
result["reasoningEffort"] = "medium"
|
|
1155
|
-
if (
|
|
1156
|
-
input.model.api.npm === "@ai-sdk/openai" ||
|
|
1157
|
-
input.model.api.npm === "@ai-sdk/azure" ||
|
|
1158
|
-
input.model.api.npm === "@ai-sdk/github-copilot" ||
|
|
1159
|
-
input.model.api.npm === "@ai-sdk/amazon-bedrock/mantle"
|
|
1160
|
-
) {
|
|
1161
|
-
result["reasoningSummary"] = "auto"
|
|
1162
|
-
}
|
|
1163
|
-
if (input.model.api.npm === "@ai-sdk/openai" || input.model.api.npm === "@ai-sdk/amazon-bedrock/mantle") {
|
|
1164
|
-
result["include"] = INCLUDE_ENCRYPTED_REASONING
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Only set textVerbosity for non-chat gpt-5.x models
|
|
1169
|
-
// Chat models (e.g. gpt-5.2-chat-latest) only support "medium" verbosity
|
|
1170
|
-
if (
|
|
1171
|
-
input.model.api.id.includes("gpt-5.") &&
|
|
1172
|
-
!input.model.api.id.includes("codex") &&
|
|
1173
|
-
!input.model.api.id.includes("-chat") &&
|
|
1174
|
-
input.model.providerID !== "azure"
|
|
1175
|
-
) {
|
|
1176
|
-
result["textVerbosity"] = "low"
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
if (input.model.providerID.startsWith("miaw")) {
|
|
1180
|
-
result["promptCacheKey"] = input.sessionID
|
|
1181
|
-
result["include"] = INCLUDE_ENCRYPTED_REASONING
|
|
1182
|
-
result["reasoningSummary"] = "auto"
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
if (input.model.providerID === "venice") {
|
|
1187
|
-
result["promptCacheKey"] = input.sessionID
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
if (input.model.providerID === "openrouter") {
|
|
1191
|
-
result["prompt_cache_key"] = input.sessionID
|
|
1192
|
-
}
|
|
1193
|
-
if (input.model.api.npm === "@ai-sdk/gateway") {
|
|
1194
|
-
result["gateway"] = {
|
|
1195
|
-
caching: "auto",
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
return result
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
export function smallOptions(model: Provider.Model) {
|
|
1203
|
-
const small = Object.values(model.variants ?? {})[0] ?? {}
|
|
1204
|
-
if (
|
|
1205
|
-
model.providerID === "openai" ||
|
|
1206
|
-
model.api.npm === "@ai-sdk/openai" ||
|
|
1207
|
-
model.api.npm === "@ai-sdk/github-copilot"
|
|
1208
|
-
) {
|
|
1209
|
-
const base = { store: false }
|
|
1210
|
-
return mergeDeep(base, small)
|
|
1211
|
-
}
|
|
1212
|
-
if (model.providerID === "openrouter" || model.providerID === "llmgateway") {
|
|
1213
|
-
if (model.providerID === "openrouter" && small.reasoning?.effort === "low") {
|
|
1214
|
-
return { reasoning: { effort: "none" } }
|
|
1215
|
-
}
|
|
1216
|
-
if (Object.keys(small).length === 0 && model.api.id.includes("google")) {
|
|
1217
|
-
return { reasoning: { enabled: false } }
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
if (model.providerID === "venice") {
|
|
1222
|
-
if (Object.keys(small).length > 0) return small
|
|
1223
|
-
return { veniceParameters: { disableThinking: true } }
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
return small
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
// Maps model ID prefix to provider slug used in providerOptions.
|
|
1230
|
-
// Example: "amazon/nova-2-lite" → "bedrock"
|
|
1231
|
-
const SLUG_OVERRIDES: Record<string, string> = {
|
|
1232
|
-
amazon: "bedrock",
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
export function providerOptions(model: Provider.Model, options: { [x: string]: any }) {
|
|
1236
|
-
if (model.api.npm === "@ai-sdk/gateway") {
|
|
1237
|
-
// Gateway providerOptions are split across two namespaces:
|
|
1238
|
-
// - `gateway`: gateway-native routing/caching controls (order, only, byok, etc.)
|
|
1239
|
-
// - `<upstream slug>`: provider-specific model options (anthropic/openai/...)
|
|
1240
|
-
// We keep `gateway` as-is and route every other top-level option under the
|
|
1241
|
-
// model-derived upstream slug.
|
|
1242
|
-
const i = model.api.id.indexOf("/")
|
|
1243
|
-
const rawSlug = i > 0 ? model.api.id.slice(0, i) : undefined
|
|
1244
|
-
const slug = rawSlug ? (SLUG_OVERRIDES[rawSlug] ?? rawSlug) : undefined
|
|
1245
|
-
const gateway = options.gateway
|
|
1246
|
-
const rest = Object.fromEntries(Object.entries(options).filter(([k]) => k !== "gateway"))
|
|
1247
|
-
const has = Object.keys(rest).length > 0
|
|
1248
|
-
|
|
1249
|
-
const result: Record<string, any> = {}
|
|
1250
|
-
if (gateway !== undefined) result.gateway = gateway
|
|
1251
|
-
|
|
1252
|
-
if (has) {
|
|
1253
|
-
if (slug) {
|
|
1254
|
-
// Route model-specific options under the provider slug
|
|
1255
|
-
result[slug] = rest
|
|
1256
|
-
} else if (gateway && typeof gateway === "object" && !Array.isArray(gateway)) {
|
|
1257
|
-
result.gateway = { ...gateway, ...rest }
|
|
1258
|
-
} else {
|
|
1259
|
-
result.gateway = rest
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
return result
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
// AI SDK packages that resolve providerOptionsName by splitting the
|
|
1267
|
-
// provider name on "." (e.g. "wafer.ai" -> "wafer") need the same
|
|
1268
|
-
// logic here so the key we write matches the key they read.
|
|
1269
|
-
// Other SDKs (xai, mistral, groq, cohere, etc.) use hardcoded keys
|
|
1270
|
-
// like "xai" or "cohere" - applying .split(".")[0] would break those.
|
|
1271
|
-
const usesDotSplitOptions =
|
|
1272
|
-
model.api.npm === "@ai-sdk/openai-compatible" ||
|
|
1273
|
-
model.api.npm === "@ai-sdk/openai" ||
|
|
1274
|
-
model.api.npm === "@ai-sdk/anthropic"
|
|
1275
|
-
const key = sdkKey(model.api.npm) ?? (usesDotSplitOptions ? model.providerID.split(".")[0] : model.providerID)
|
|
1276
|
-
// @ai-sdk/azure delegates to OpenAIChatLanguageModel which reads from
|
|
1277
|
-
// providerOptions["openai"], but OpenAIResponsesLanguageModel checks
|
|
1278
|
-
// "azure" first. Pass both so model options work on either code path.
|
|
1279
|
-
if (model.api.npm === "@ai-sdk/azure") {
|
|
1280
|
-
return { openai: options, azure: options }
|
|
1281
|
-
}
|
|
1282
|
-
return { [key]: options }
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
export function maxOutputTokens(model: Provider.Model, outputTokenMax = OUTPUT_TOKEN_MAX): number {
|
|
1286
|
-
return Math.min(model.limit.output, outputTokenMax) || outputTokenMax
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
export function schema(model: Provider.Model, schema: JSONSchema7): JSONSchema7 {
|
|
1290
|
-
/*
|
|
1291
|
-
if (["openai", "azure"].includes(providerID)) {
|
|
1292
|
-
if (schema.type === "object" && schema.properties) {
|
|
1293
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
1294
|
-
if (schema.required?.includes(key)) continue
|
|
1295
|
-
schema.properties[key] = {
|
|
1296
|
-
anyOf: [
|
|
1297
|
-
value as JSONSchema.JSONSchema,
|
|
1298
|
-
{
|
|
1299
|
-
type: "null",
|
|
1300
|
-
},
|
|
1301
|
-
],
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
*/
|
|
1307
|
-
|
|
1308
|
-
if (model.providerID === "moonshotai" || model.api.id.toLowerCase().includes("kimi")) {
|
|
1309
|
-
const sanitizeMoonshot = (obj: unknown): unknown => {
|
|
1310
|
-
if (obj === null || typeof obj !== "object") return obj
|
|
1311
|
-
if (Array.isArray(obj)) return obj.map(sanitizeMoonshot)
|
|
1312
|
-
// Moonshot expands $ref before validation and rejects sibling keywords like description on the same node.
|
|
1313
|
-
if ("$ref" in obj && typeof obj.$ref === "string") return { $ref: obj.$ref }
|
|
1314
|
-
const result = Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, sanitizeMoonshot(value)]))
|
|
1315
|
-
// MFJS does not support tuple-style `items` arrays; it requires one schema object for all array items.
|
|
1316
|
-
if (Array.isArray(result.items)) result.items = result.items[0] ?? {}
|
|
1317
|
-
return result
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
const sanitized = sanitizeMoonshot(schema)
|
|
1321
|
-
if (typeof sanitized === "object" && sanitized !== null && !Array.isArray(sanitized)) {
|
|
1322
|
-
schema = sanitized
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
// Convert integer enums to string enums for Google/Gemini
|
|
1327
|
-
if (model.providerID === "google" || model.api.id.includes("gemini")) {
|
|
1328
|
-
const isPlainObject = (node: unknown): node is Record<string, any> =>
|
|
1329
|
-
typeof node === "object" && node !== null && !Array.isArray(node)
|
|
1330
|
-
const hasCombiner = (node: unknown) =>
|
|
1331
|
-
isPlainObject(node) && (Array.isArray(node.anyOf) || Array.isArray(node.oneOf) || Array.isArray(node.allOf))
|
|
1332
|
-
const hasSchemaIntent = (node: unknown) => {
|
|
1333
|
-
if (!isPlainObject(node)) return false
|
|
1334
|
-
if (hasCombiner(node)) return true
|
|
1335
|
-
return [
|
|
1336
|
-
"type",
|
|
1337
|
-
"properties",
|
|
1338
|
-
"items",
|
|
1339
|
-
"prefixItems",
|
|
1340
|
-
"enum",
|
|
1341
|
-
"const",
|
|
1342
|
-
"$ref",
|
|
1343
|
-
"additionalProperties",
|
|
1344
|
-
"patternProperties",
|
|
1345
|
-
"required",
|
|
1346
|
-
"not",
|
|
1347
|
-
"if",
|
|
1348
|
-
"then",
|
|
1349
|
-
"else",
|
|
1350
|
-
].some((key) => key in node)
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
const sanitizeGemini = (obj: any): any => {
|
|
1354
|
-
if (obj === null || typeof obj !== "object") {
|
|
1355
|
-
return obj
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
if (Array.isArray(obj)) {
|
|
1359
|
-
return obj.map(sanitizeGemini)
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
const result: any = {}
|
|
1363
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1364
|
-
if (key === "enum" && Array.isArray(value)) {
|
|
1365
|
-
// Convert all enum values to strings
|
|
1366
|
-
result[key] = value.map((v) => String(v))
|
|
1367
|
-
// If we have integer type with enum, change type to string
|
|
1368
|
-
if (result.type === "integer" || result.type === "number") {
|
|
1369
|
-
result.type = "string"
|
|
1370
|
-
}
|
|
1371
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1372
|
-
result[key] = sanitizeGemini(value)
|
|
1373
|
-
} else {
|
|
1374
|
-
result[key] = value
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
// Gemini requires a single `type`, not a JSON Schema type array such as
|
|
1379
|
-
// `["number","string"]` (emitted by some MCP servers). Plain `@ai-sdk/google`
|
|
1380
|
-
// rewrites these into an `anyOf` of single-type schemas, but OpenAI-compatible
|
|
1381
|
-
// transports (e.g. GitHub Copilot proxying to Gemini) forward them verbatim
|
|
1382
|
-
// and the backend rejects the array form. Mirror the SDK: split non-null
|
|
1383
|
-
// types into `anyOf`, and lift `null` into `nullable`.
|
|
1384
|
-
if (Array.isArray(result.type)) {
|
|
1385
|
-
const hasNull = result.type.includes("null")
|
|
1386
|
-
const nonNull = result.type.filter((entry: unknown) => entry !== "null")
|
|
1387
|
-
if (nonNull.length === 0) {
|
|
1388
|
-
result.type = "null"
|
|
1389
|
-
} else {
|
|
1390
|
-
delete result.type
|
|
1391
|
-
result.anyOf = nonNull.map((entry: unknown) => ({ type: entry }))
|
|
1392
|
-
if (hasNull) result.nullable = true
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
// Filter required array to only include fields that exist in properties
|
|
1397
|
-
if (result.type === "object" && result.properties && Array.isArray(result.required)) {
|
|
1398
|
-
result.required = result.required.filter((field: any) => field in result.properties)
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
if (result.type === "array" && !hasCombiner(result)) {
|
|
1402
|
-
if (result.items == null) {
|
|
1403
|
-
result.items = {}
|
|
1404
|
-
}
|
|
1405
|
-
// Ensure items has a type only when it's still schema-empty.
|
|
1406
|
-
if (isPlainObject(result.items) && !hasSchemaIntent(result.items)) {
|
|
1407
|
-
result.items.type = "string"
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
// Remove properties/required from non-object types (Gemini rejects these)
|
|
1412
|
-
if (result.type && result.type !== "object" && !hasCombiner(result)) {
|
|
1413
|
-
delete result.properties
|
|
1414
|
-
delete result.required
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
return result
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
schema = sanitizeGemini(schema)
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
return schema
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
export * as ProviderTransform from "./transform"
|