@sleepy-ai/cli 0.1.6 → 0.1.7
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/{src/skill/compose/LICENSE-superpowers → LICENSE} +3 -6
- package/README.md +139 -6
- package/package.json +35 -199
- package/postinstall.mjs +102 -0
- package/.sleepycode-test-fixtures-50158/sleepycode-test-eqsxv84ythu/.watcher-b67v64k2mnv +0 -1
- package/Dockerfile +0 -18
- package/drizzle.config.ts +0 -10
- package/git +0 -0
- package/migration/20260127222353_familiar_lady_ursula/migration.sql +0 -90
- package/migration/20260127222353_familiar_lady_ursula/snapshot.json +0 -796
- package/migration/20260211171708_add_project_commands/migration.sql +0 -1
- package/migration/20260211171708_add_project_commands/snapshot.json +0 -806
- package/migration/20260213144116_wakeful_the_professor/migration.sql +0 -11
- package/migration/20260213144116_wakeful_the_professor/snapshot.json +0 -897
- package/migration/20260225215848_workspace/migration.sql +0 -7
- package/migration/20260225215848_workspace/snapshot.json +0 -959
- package/migration/20260227213759_add_session_workspace_id/migration.sql +0 -2
- package/migration/20260227213759_add_session_workspace_id/snapshot.json +0 -983
- package/migration/20260228203230_blue_harpoon/migration.sql +0 -17
- package/migration/20260228203230_blue_harpoon/snapshot.json +0 -1102
- package/migration/20260303231226_add_workspace_fields/migration.sql +0 -5
- package/migration/20260303231226_add_workspace_fields/snapshot.json +0 -1013
- package/migration/20260309230000_move_org_to_state/migration.sql +0 -3
- package/migration/20260309230000_move_org_to_state/snapshot.json +0 -1156
- package/migration/20260312043431_session_message_cursor/migration.sql +0 -4
- package/migration/20260312043431_session_message_cursor/snapshot.json +0 -1168
- package/migration/20260323234822_events/migration.sql +0 -13
- package/migration/20260323234822_events/snapshot.json +0 -1271
- package/migration/20260410174513_workspace-name/migration.sql +0 -16
- package/migration/20260410174513_workspace-name/snapshot.json +0 -1271
- package/migration/20260413175956_chief_energizer/migration.sql +0 -13
- package/migration/20260413175956_chief_energizer/snapshot.json +0 -1399
- package/migration/20260422160000_context_inheritance/migration.sql +0 -3
- package/migration/20260422170000_task_registry/migration.sql +0 -18
- package/migration/20260423145421_remove_session_entry/migration.sql +0 -4
- package/migration/20260515000000_actor_rename/migration.sql +0 -7
- package/migration/20260515010000_memory_fts/migration.sql +0 -33
- package/migration/20260515020000_user_task/migration.sql +0 -29
- package/migration/20260519000000_last_checkpoint_message_id/migration.sql +0 -1
- package/migration/20260521000000_message_agent_id/migration.sql +0 -2
- package/migration/20260521000100_actor_registry_v6/migration.sql +0 -25
- package/migration/20260521010000_memory_fts_v6/migration.sql +0 -33
- package/migration/20260521020000_memory_fts_triggers/migration.sql +0 -17
- package/migration/20260526000000_agent_id_main/migration.sql +0 -14
- package/migration/20260527000000_actor_lifecycle/migration.sql +0 -8
- package/migration/20260527000100_inbox/migration.sql +0 -12
- package/migration/20260529000000_task_todo_redesign/migration.sql +0 -16
- package/migration/20260603000000_task_in_progress_owner/migration.sql +0 -1
- package/migration/20260603000000_workflow_run/migration.sql +0 -17
- package/migration/20260604000000_workflow_script_sha/migration.sql +0 -1
- package/migration/20260608000000_claude_import/migration.sql +0 -7
- package/migration/20260608010000_claude_import_message_ids/migration.sql +0 -1
- package/migration/20260609000000_history_fts/migration.sql +0 -29
- package/migration/20260609230000_workflow_agent_timeout/migration.sql +0 -1
- package/migration/20260612000000_external_import/migration.sql +0 -16
- package/parsers-config.ts +0 -290
- package/src/account/account.sql.ts +0 -39
- package/src/account/account.ts +0 -456
- package/src/account/repo.ts +0 -166
- package/src/account/schema.ts +0 -99
- package/src/account/url.ts +0 -8
- package/src/acp/README.md +0 -174
- package/src/acp/agent.ts +0 -1787
- package/src/acp/session.ts +0 -116
- package/src/acp/types.ts +0 -24
- package/src/actor/actor.sql.ts +0 -38
- package/src/actor/events.ts +0 -67
- package/src/actor/index.ts +0 -2
- package/src/actor/registry.ts +0 -412
- package/src/actor/return-header.ts +0 -24
- package/src/actor/schema.ts +0 -47
- package/src/actor/spawn-ref.ts +0 -16
- package/src/actor/spawn.ts +0 -756
- package/src/actor/turn.ts +0 -49
- package/src/actor/waiter.ts +0 -166
- package/src/agent/agent.ts +0 -574
- package/src/agent/config.ts +0 -5
- package/src/agent/generate.txt +0 -75
- package/src/agent/prompt/checkpoint-writer.txt +0 -167
- package/src/agent/prompt/compaction.txt +0 -9
- package/src/agent/prompt/distill.txt +0 -199
- package/src/agent/prompt/dream.txt +0 -155
- 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/audio.d.ts +0 -9
- package/src/auth/index.ts +0 -97
- package/src/bus/bus-event.ts +0 -33
- package/src/bus/global.ts +0 -12
- package/src/bus/index.ts +0 -193
- package/src/cli/bootstrap.ts +0 -33
- package/src/cli/cmd/account.ts +0 -258
- package/src/cli/cmd/acp.ts +0 -70
- package/src/cli/cmd/agent.ts +0 -248
- package/src/cli/cmd/cmd.ts +0 -7
- package/src/cli/cmd/db.ts +0 -120
- package/src/cli/cmd/debug/agent.ts +0 -192
- package/src/cli/cmd/debug/config.ts +0 -17
- package/src/cli/cmd/debug/file.ts +0 -100
- package/src/cli/cmd/debug/index.ts +0 -48
- package/src/cli/cmd/debug/lsp.ts +0 -61
- package/src/cli/cmd/debug/ripgrep.ts +0 -105
- package/src/cli/cmd/debug/scrap.ts +0 -16
- package/src/cli/cmd/debug/skill.ts +0 -23
- package/src/cli/cmd/debug/snapshot.ts +0 -53
- package/src/cli/cmd/doctor.ts +0 -116
- package/src/cli/cmd/export.ts +0 -306
- package/src/cli/cmd/generate.ts +0 -50
- package/src/cli/cmd/github.ts +0 -1647
- package/src/cli/cmd/import.ts +0 -208
- package/src/cli/cmd/init.ts +0 -97
- package/src/cli/cmd/login.ts +0 -402
- package/src/cli/cmd/mcp.ts +0 -812
- package/src/cli/cmd/models.ts +0 -88
- package/src/cli/cmd/plug.ts +0 -233
- package/src/cli/cmd/pr.ts +0 -138
- package/src/cli/cmd/providers.ts +0 -713
- package/src/cli/cmd/run-completion.ts +0 -77
- package/src/cli/cmd/run.ts +0 -694
- package/src/cli/cmd/serve.ts +0 -30
- package/src/cli/cmd/session.ts +0 -181
- package/src/cli/cmd/stats.ts +0 -413
- package/src/cli/cmd/tui/app.tsx +0 -1181
- package/src/cli/cmd/tui/asset/TEN_VAD_LICENSE +0 -12
- package/src/cli/cmd/tui/asset/charge.wav +0 -0
- package/src/cli/cmd/tui/asset/pulse-a.wav +0 -0
- package/src/cli/cmd/tui/asset/pulse-b.wav +0 -0
- package/src/cli/cmd/tui/asset/pulse-c.wav +0 -0
- package/src/cli/cmd/tui/asset/ten_vad.wasm +0 -0
- package/src/cli/cmd/tui/asset/ten_vad_loader.js +0 -30
- package/src/cli/cmd/tui/attach.ts +0 -84
- package/src/cli/cmd/tui/component/background-image.tsx +0 -150
- package/src/cli/cmd/tui/component/banner-session-expired.tsx +0 -48
- package/src/cli/cmd/tui/component/bg-pulse.tsx +0 -130
- package/src/cli/cmd/tui/component/border.tsx +0 -21
- package/src/cli/cmd/tui/component/dialog-agent.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-agreement.tsx +0 -111
- package/src/cli/cmd/tui/component/dialog-command.tsx +0 -219
- package/src/cli/cmd/tui/component/dialog-console-org.tsx +0 -103
- package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +0 -157
- package/src/cli/cmd/tui/component/dialog-image-list.tsx +0 -111
- package/src/cli/cmd/tui/component/dialog-logo-design.tsx +0 -37
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +0 -86
- package/src/cli/cmd/tui/component/dialog-model.tsx +0 -299
- package/src/cli/cmd/tui/component/dialog-provider.tsx +0 -449
- package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +0 -101
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -269
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-skill.tsx +0 -42
- package/src/cli/cmd/tui/component/dialog-sleepy-login.tsx +0 -288
- package/src/cli/cmd/tui/component/dialog-stash.tsx +0 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +0 -170
- package/src/cli/cmd/tui/component/dialog-tag.tsx +0 -44
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +0 -50
- package/src/cli/cmd/tui/component/dialog-token-plan.tsx +0 -77
- package/src/cli/cmd/tui/component/dialog-variant.tsx +0 -39
- package/src/cli/cmd/tui/component/dialog-workflows.tsx +0 -51
- package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +0 -289
- package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +0 -81
- package/src/cli/cmd/tui/component/dialog-worktree.tsx +0 -90
- package/src/cli/cmd/tui/component/error-component.tsx +0 -92
- package/src/cli/cmd/tui/component/logo.tsx +0 -961
- package/src/cli/cmd/tui/component/plugin-route-missing.tsx +0 -14
- package/src/cli/cmd/tui/component/prompt/autocomplete-detect.ts +0 -34
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -668
- package/src/cli/cmd/tui/component/prompt/cwd.ts +0 -0
- package/src/cli/cmd/tui/component/prompt/frecency.tsx +0 -90
- package/src/cli/cmd/tui/component/prompt/history.tsx +0 -108
- package/src/cli/cmd/tui/component/prompt/index.tsx +0 -1869
- package/src/cli/cmd/tui/component/prompt/offset.ts +0 -45
- package/src/cli/cmd/tui/component/prompt/part.ts +0 -36
- package/src/cli/cmd/tui/component/prompt/stash.tsx +0 -101
- package/src/cli/cmd/tui/component/spinner.tsx +0 -24
- package/src/cli/cmd/tui/component/starry-background.tsx +0 -305
- package/src/cli/cmd/tui/component/startup-loading.tsx +0 -67
- package/src/cli/cmd/tui/component/task-item.tsx +0 -63
- package/src/cli/cmd/tui/component/textarea-keybindings.ts +0 -73
- package/src/cli/cmd/tui/component/todo-item.tsx +0 -32
- package/src/cli/cmd/tui/component/workflow-tree.tsx +0 -177
- package/src/cli/cmd/tui/config/cwd.ts +0 -5
- package/src/cli/cmd/tui/config/tui-migrate.ts +0 -151
- package/src/cli/cmd/tui/config/tui-schema.ts +0 -38
- package/src/cli/cmd/tui/config/tui.ts +0 -219
- package/src/cli/cmd/tui/context/args.tsx +0 -16
- package/src/cli/cmd/tui/context/directory.ts +0 -15
- package/src/cli/cmd/tui/context/event.ts +0 -45
- package/src/cli/cmd/tui/context/exit.tsx +0 -65
- package/src/cli/cmd/tui/context/helper.tsx +0 -25
- package/src/cli/cmd/tui/context/keybind.tsx +0 -105
- package/src/cli/cmd/tui/context/kv.tsx +0 -86
- package/src/cli/cmd/tui/context/language.tsx +0 -91
- package/src/cli/cmd/tui/context/local.tsx +0 -469
- package/src/cli/cmd/tui/context/plugin-keybinds.ts +0 -41
- package/src/cli/cmd/tui/context/project.tsx +0 -109
- package/src/cli/cmd/tui/context/prompt.tsx +0 -18
- package/src/cli/cmd/tui/context/route.tsx +0 -68
- package/src/cli/cmd/tui/context/sdk.tsx +0 -150
- package/src/cli/cmd/tui/context/sync.tsx +0 -884
- package/src/cli/cmd/tui/context/theme/aura.json +0 -69
- package/src/cli/cmd/tui/context/theme/ayu.json +0 -80
- package/src/cli/cmd/tui/context/theme/carbonfox.json +0 -248
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +0 -230
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +0 -230
- package/src/cli/cmd/tui/context/theme/catppuccin.json +0 -112
- package/src/cli/cmd/tui/context/theme/cobalt2.json +0 -225
- package/src/cli/cmd/tui/context/theme/cursor.json +0 -249
- package/src/cli/cmd/tui/context/theme/dracula.json +0 -219
- package/src/cli/cmd/tui/context/theme/everforest.json +0 -241
- package/src/cli/cmd/tui/context/theme/flexoki.json +0 -237
- package/src/cli/cmd/tui/context/theme/github.json +0 -233
- package/src/cli/cmd/tui/context/theme/gruvbox.json +0 -242
- package/src/cli/cmd/tui/context/theme/kanagawa.json +0 -77
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +0 -234
- package/src/cli/cmd/tui/context/theme/material.json +0 -235
- package/src/cli/cmd/tui/context/theme/matrix.json +0 -77
- package/src/cli/cmd/tui/context/theme/mercury.json +0 -252
- package/src/cli/cmd/tui/context/theme/monokai.json +0 -221
- package/src/cli/cmd/tui/context/theme/nightowl.json +0 -221
- package/src/cli/cmd/tui/context/theme/nord.json +0 -223
- package/src/cli/cmd/tui/context/theme/one-dark.json +0 -84
- package/src/cli/cmd/tui/context/theme/orng.json +0 -249
- package/src/cli/cmd/tui/context/theme/osaka-jade.json +0 -93
- package/src/cli/cmd/tui/context/theme/palenight.json +0 -222
- package/src/cli/cmd/tui/context/theme/rosepine.json +0 -234
- package/src/cli/cmd/tui/context/theme/sleepycode.json +0 -245
- package/src/cli/cmd/tui/context/theme/solarized.json +0 -223
- package/src/cli/cmd/tui/context/theme/synthwave84.json +0 -226
- package/src/cli/cmd/tui/context/theme/tokyonight.json +0 -243
- package/src/cli/cmd/tui/context/theme/vercel.json +0 -245
- package/src/cli/cmd/tui/context/theme/vesper.json +0 -218
- package/src/cli/cmd/tui/context/theme/zenburn.json +0 -223
- package/src/cli/cmd/tui/context/theme.tsx +0 -1298
- package/src/cli/cmd/tui/context/thinking.ts +0 -48
- package/src/cli/cmd/tui/context/tui-config.tsx +0 -9
- package/src/cli/cmd/tui/event.ts +0 -62
- package/src/cli/cmd/tui/feature-plugins/home/footer.tsx +0 -93
- package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +0 -193
- package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +0 -54
- package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +0 -267
- package/src/cli/cmd/tui/feature-plugins/sidebar/cwd.tsx +0 -45
- package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +0 -62
- package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +0 -93
- package/src/cli/cmd/tui/feature-plugins/sidebar/goal.tsx +0 -84
- package/src/cli/cmd/tui/feature-plugins/sidebar/instructions.tsx +0 -54
- package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +0 -66
- package/src/cli/cmd/tui/feature-plugins/sidebar/mascot.tsx +0 -69
- package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +0 -98
- package/src/cli/cmd/tui/feature-plugins/sidebar/task.tsx +0 -95
- package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +0 -51
- package/src/cli/cmd/tui/feature-plugins/sidebar/tps.ts +0 -31
- package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +0 -274
- package/src/cli/cmd/tui/i18n/en.ts +0 -465
- package/src/cli/cmd/tui/i18n/es.ts +0 -508
- package/src/cli/cmd/tui/i18n/fr.ts +0 -515
- package/src/cli/cmd/tui/i18n/ja.ts +0 -463
- package/src/cli/cmd/tui/i18n/locales.ts +0 -82
- package/src/cli/cmd/tui/i18n/ru.ts +0 -527
- package/src/cli/cmd/tui/i18n/slash-command.ts +0 -11
- package/src/cli/cmd/tui/i18n/zh.ts +0 -454
- package/src/cli/cmd/tui/i18n/zht.ts +0 -430
- package/src/cli/cmd/tui/layer.ts +0 -6
- package/src/cli/cmd/tui/plugin/api.tsx +0 -402
- package/src/cli/cmd/tui/plugin/index.ts +0 -3
- package/src/cli/cmd/tui/plugin/internal.ts +0 -37
- package/src/cli/cmd/tui/plugin/runtime.ts +0 -1057
- package/src/cli/cmd/tui/plugin/slots.tsx +0 -60
- package/src/cli/cmd/tui/routes/home.tsx +0 -165
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +0 -76
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +0 -116
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +0 -47
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +0 -47
- package/src/cli/cmd/tui/routes/session/footer.tsx +0 -91
- package/src/cli/cmd/tui/routes/session/index.tsx +0 -3073
- package/src/cli/cmd/tui/routes/session/permission.tsx +0 -697
- package/src/cli/cmd/tui/routes/session/question.tsx +0 -488
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -97
- package/src/cli/cmd/tui/routes/session/subagent-footer.tsx +0 -143
- package/src/cli/cmd/tui/thread.ts +0 -324
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -61
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -95
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +0 -223
- package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -42
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -123
- package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -467
- package/src/cli/cmd/tui/ui/dialog.tsx +0 -207
- package/src/cli/cmd/tui/ui/link.tsx +0 -28
- package/src/cli/cmd/tui/ui/spinner.ts +0 -378
- package/src/cli/cmd/tui/ui/toast.tsx +0 -102
- package/src/cli/cmd/tui/util/clipboard.ts +0 -203
- package/src/cli/cmd/tui/util/editor.ts +0 -36
- package/src/cli/cmd/tui/util/image-protocol.ts +0 -35
- package/src/cli/cmd/tui/util/index.ts +0 -6
- package/src/cli/cmd/tui/util/model.ts +0 -23
- package/src/cli/cmd/tui/util/pinyin.ts +0 -20
- package/src/cli/cmd/tui/util/provider-origin.ts +0 -7
- package/src/cli/cmd/tui/util/revert-diff.ts +0 -18
- package/src/cli/cmd/tui/util/scroll.ts +0 -23
- package/src/cli/cmd/tui/util/selection.ts +0 -23
- package/src/cli/cmd/tui/util/signal.ts +0 -41
- package/src/cli/cmd/tui/util/sound.ts +0 -154
- package/src/cli/cmd/tui/util/system-locale.ts +0 -209
- package/src/cli/cmd/tui/util/terminal.ts +0 -110
- package/src/cli/cmd/tui/util/transcript.ts +0 -112
- package/src/cli/cmd/tui/util/vad.ts +0 -229
- package/src/cli/cmd/tui/util/voice.ts +0 -450
- package/src/cli/cmd/tui/win32.ts +0 -130
- package/src/cli/cmd/tui/worker.ts +0 -104
- package/src/cli/cmd/uninstall.ts +0 -351
- package/src/cli/cmd/upgrade.ts +0 -79
- package/src/cli/cmd/web.ts +0 -96
- package/src/cli/effect/prompt.ts +0 -25
- package/src/cli/error.ts +0 -82
- package/src/cli/heap.ts +0 -59
- package/src/cli/i18n.ts +0 -15
- package/src/cli/logo.ts +0 -53
- package/src/cli/network.ts +0 -68
- package/src/cli/ui.ts +0 -133
- package/src/cli/upgrade.ts +0 -41
- package/src/command/index.ts +0 -276
- package/src/command/template/initialize.txt +0 -66
- package/src/command/template/review.txt +0 -101
- package/src/config/agent.ts +0 -197
- package/src/config/command.ts +0 -69
- package/src/config/compose.ts +0 -26
- package/src/config/config.ts +0 -1047
- package/src/config/console-state.ts +0 -16
- package/src/config/entry-name.ts +0 -16
- package/src/config/error.ts +0 -21
- package/src/config/formatter.ts +0 -17
- package/src/config/history.ts +0 -21
- package/src/config/index.ts +0 -17
- package/src/config/keybinds.ts +0 -127
- package/src/config/layout.ts +0 -10
- package/src/config/lsp.ts +0 -45
- package/src/config/managed.ts +0 -70
- package/src/config/markdown.ts +0 -97
- package/src/config/mcp.ts +0 -172
- package/src/config/model-id.ts +0 -14
- package/src/config/parse.ts +0 -44
- package/src/config/paths.ts +0 -85
- package/src/config/permission.ts +0 -76
- package/src/config/plugin.ts +0 -88
- package/src/config/provider.ts +0 -118
- package/src/config/server.ts +0 -20
- package/src/config/skills.ts +0 -16
- package/src/config/variable.ts +0 -90
- package/src/control-plane/adaptors/index.ts +0 -52
- package/src/control-plane/adaptors/worktree.ts +0 -47
- package/src/control-plane/dev/debug-workspace-plugin.ts +0 -73
- package/src/control-plane/schema.ts +0 -19
- package/src/control-plane/sse.ts +0 -66
- package/src/control-plane/types.ts +0 -34
- package/src/control-plane/util.ts +0 -37
- package/src/control-plane/workspace-context.ts +0 -26
- package/src/control-plane/workspace.sql.ts +0 -17
- package/src/control-plane/workspace.ts +0 -615
- package/src/effect/app-runtime.ts +0 -146
- package/src/effect/bootstrap-runtime.ts +0 -33
- package/src/effect/bridge.ts +0 -48
- package/src/effect/cross-spawn-spawner.ts +0 -514
- package/src/effect/index.ts +0 -5
- package/src/effect/instance-ref.ts +0 -11
- package/src/effect/instance-registry.ts +0 -12
- package/src/effect/instance-state.ts +0 -81
- package/src/effect/logger.ts +0 -73
- package/src/effect/memo-map.ts +0 -3
- package/src/effect/observability.ts +0 -107
- package/src/effect/run-service.ts +0 -52
- package/src/effect/runner.ts +0 -210
- package/src/effect/runtime.ts +0 -19
- package/src/env/index.ts +0 -37
- package/src/file/ignore.ts +0 -81
- package/src/file/index.ts +0 -664
- package/src/file/protected.ts +0 -59
- package/src/file/ripgrep.ts +0 -485
- package/src/file/watcher.ts +0 -163
- package/src/flag/flag.ts +0 -185
- package/src/format/formatter.ts +0 -403
- package/src/format/index.ts +0 -203
- package/src/git/index.ts +0 -260
- package/src/global/index.ts +0 -54
- package/src/history/backfill.ts +0 -162
- package/src/history/extract.ts +0 -67
- package/src/history/fts-query.ts +0 -15
- package/src/history/fts.sql.ts +0 -20
- package/src/history/index.ts +0 -10
- package/src/history/resolve.ts +0 -65
- package/src/history/service.ts +0 -258
- package/src/history/writer.ts +0 -112
- package/src/id/id.ts +0 -87
- package/src/ide/index.ts +0 -73
- package/src/inbox/inbox-ref.ts +0 -38
- package/src/inbox/inbox.sql.ts +0 -26
- package/src/inbox/inbox.ts +0 -223
- package/src/inbox/index.ts +0 -3
- package/src/inbox/render.ts +0 -40
- package/src/index.ts +0 -268
- package/src/installation/index.ts +0 -362
- package/src/installation/version.ts +0 -8
- package/src/lsp/client.ts +0 -249
- package/src/lsp/diagnostic.ts +0 -29
- package/src/lsp/index.ts +0 -3
- package/src/lsp/language.ts +0 -120
- package/src/lsp/launch.ts +0 -21
- package/src/lsp/lsp.ts +0 -519
- package/src/lsp/server.ts +0 -1956
- package/src/mcp/auth.ts +0 -144
- package/src/mcp/index.ts +0 -939
- package/src/mcp/oauth-callback.ts +0 -236
- package/src/mcp/oauth-provider.ts +0 -214
- package/src/memory/fts-query.ts +0 -37
- package/src/memory/fts.sql.ts +0 -19
- package/src/memory/index.ts +0 -1
- package/src/memory/paths.ts +0 -116
- package/src/memory/reconcile.ts +0 -144
- package/src/memory/service.ts +0 -144
- package/src/metrics/client.ts +0 -40
- package/src/metrics/event.ts +0 -43
- package/src/metrics/index.ts +0 -5
- package/src/metrics/installation.ts +0 -18
- package/src/metrics/subscriber.ts +0 -58
- package/src/metrics/util.ts +0 -9
- package/src/node.ts +0 -6
- package/src/npm/config.ts +0 -0
- package/src/npm/index.ts +0 -293
- package/src/npmcli-config.d.ts +0 -43
- package/src/patch/index.ts +0 -680
- package/src/permission/arity.ts +0 -163
- package/src/permission/evaluate.ts +0 -15
- package/src/permission/index.ts +0 -382
- package/src/permission/schema.ts +0 -17
- package/src/plugin/checkpoint-splitover.ts +0 -60
- package/src/plugin/cloudflare.ts +0 -76
- package/src/plugin/codex.ts +0 -611
- package/src/plugin/github-copilot/copilot.ts +0 -368
- package/src/plugin/github-copilot/models.ts +0 -153
- package/src/plugin/index.ts +0 -637
- package/src/plugin/install.ts +0 -439
- package/src/plugin/loader.ts +0 -216
- package/src/plugin/matcher.ts +0 -33
- package/src/plugin/meta.ts +0 -188
- package/src/plugin/shared.ts +0 -323
- package/src/plugin/sleepy.ts +0 -244
- package/src/plugin/subagent-progress-checker.ts +0 -147
- package/src/project/bootstrap.ts +0 -59
- package/src/project/index.ts +0 -2
- package/src/project/instance.ts +0 -215
- package/src/project/project-id.ts +0 -48
- package/src/project/project.sql.ts +0 -16
- package/src/project/project.ts +0 -522
- package/src/project/schema.ts +0 -15
- package/src/project/vcs.ts +0 -227
- package/src/project/workspace-trust.ts +0 -67
- package/src/provider/auth.ts +0 -234
- package/src/provider/error.ts +0 -216
- package/src/provider/index.ts +0 -5
- package/src/provider/models-snapshot.d.ts +0 -2
- package/src/provider/models-snapshot.js +0 -3
- package/src/provider/models.ts +0 -180
- package/src/provider/provider.ts +0 -2098
- package/src/provider/schema.ts +0 -36
- package/src/provider/sdk/copilot/README.md +0 -5
- package/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +0 -170
- package/src/provider/sdk/copilot/chat/get-response-metadata.ts +0 -15
- package/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +0 -19
- package/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts +0 -64
- package/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts +0 -815
- package/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts +0 -28
- package/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +0 -44
- package/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts +0 -83
- package/src/provider/sdk/copilot/copilot-provider.ts +0 -100
- package/src/provider/sdk/copilot/index.ts +0 -2
- package/src/provider/sdk/copilot/openai-compatible-error.ts +0 -27
- package/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts +0 -335
- package/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts +0 -22
- package/src/provider/sdk/copilot/responses/openai-config.ts +0 -18
- package/src/provider/sdk/copilot/responses/openai-error.ts +0 -22
- package/src/provider/sdk/copilot/responses/openai-responses-api-types.ts +0 -214
- package/src/provider/sdk/copilot/responses/openai-responses-language-model.ts +0 -1770
- package/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts +0 -173
- package/src/provider/sdk/copilot/responses/openai-responses-settings.ts +0 -1
- package/src/provider/sdk/copilot/responses/tool/code-interpreter.ts +0 -87
- package/src/provider/sdk/copilot/responses/tool/file-search.ts +0 -127
- package/src/provider/sdk/copilot/responses/tool/image-generation.ts +0 -114
- package/src/provider/sdk/copilot/responses/tool/local-shell.ts +0 -64
- package/src/provider/sdk/copilot/responses/tool/web-search-preview.ts +0 -103
- package/src/provider/sdk/copilot/responses/tool/web-search.ts +0 -102
- package/src/provider/session-check.ts +0 -163
- package/src/provider/transform.ts +0 -1376
- package/src/pty/index.ts +0 -364
- package/src/pty/pty.bun.ts +0 -26
- package/src/pty/pty.node.ts +0 -27
- package/src/pty/pty.ts +0 -25
- package/src/pty/schema.ts +0 -17
- package/src/question/index.ts +0 -252
- package/src/question/schema.ts +0 -17
- package/src/server/adapter.bun.ts +0 -40
- package/src/server/adapter.node.ts +0 -66
- package/src/server/adapter.ts +0 -21
- package/src/server/auth.ts +0 -16
- package/src/server/error.ts +0 -53
- package/src/server/event.ts +0 -7
- package/src/server/fence.ts +0 -81
- package/src/server/mdns.ts +0 -60
- package/src/server/middleware.ts +0 -94
- package/src/server/projectors.ts +0 -28
- package/src/server/proxy.ts +0 -171
- package/src/server/pty-ticket.ts +0 -42
- package/src/server/rate-limit.ts +0 -38
- package/src/server/routes/control/index.ts +0 -160
- package/src/server/routes/control/workspace.ts +0 -203
- package/src/server/routes/global.ts +0 -367
- package/src/server/routes/instance/bash-interactive.ts +0 -82
- package/src/server/routes/instance/config.ts +0 -89
- package/src/server/routes/instance/event.ts +0 -108
- package/src/server/routes/instance/experimental.ts +0 -408
- package/src/server/routes/instance/file.ts +0 -190
- package/src/server/routes/instance/httpapi/config.ts +0 -51
- package/src/server/routes/instance/httpapi/permission.ts +0 -72
- package/src/server/routes/instance/httpapi/project.ts +0 -62
- package/src/server/routes/instance/httpapi/provider.ts +0 -142
- package/src/server/routes/instance/httpapi/question.ts +0 -121
- package/src/server/routes/instance/httpapi/server.ts +0 -153
- package/src/server/routes/instance/index.ts +0 -301
- package/src/server/routes/instance/mcp.ts +0 -260
- package/src/server/routes/instance/middleware.ts +0 -44
- package/src/server/routes/instance/permission.ts +0 -73
- package/src/server/routes/instance/project.ts +0 -122
- package/src/server/routes/instance/provider.ts +0 -158
- package/src/server/routes/instance/pty.ts +0 -302
- package/src/server/routes/instance/question.ts +0 -162
- package/src/server/routes/instance/session.ts +0 -1328
- package/src/server/routes/instance/sync.ts +0 -143
- package/src/server/routes/instance/trace.ts +0 -59
- package/src/server/routes/instance/tui.ts +0 -384
- package/src/server/routes/instance/workflows.ts +0 -142
- package/src/server/routes/ui.ts +0 -37
- package/src/server/server.ts +0 -146
- package/src/server/workspace.ts +0 -122
- package/src/session/auto-dream.ts +0 -123
- package/src/session/boundary.ts +0 -77
- package/src/session/budgeted-read.ts +0 -118
- package/src/session/checkpoint-align.ts +0 -29
- package/src/session/checkpoint-context.ts +0 -36
- package/src/session/checkpoint-paths.ts +0 -86
- package/src/session/checkpoint-progress-reconcile.ts +0 -111
- package/src/session/checkpoint-retry.ts +0 -192
- package/src/session/checkpoint-templates.ts +0 -114
- package/src/session/checkpoint-validator.ts +0 -259
- package/src/session/checkpoint.ts +0 -1560
- package/src/session/classify.ts +0 -117
- package/src/session/claude-import.ts +0 -381
- package/src/session/codex-import.ts +0 -416
- package/src/session/compaction.ts +0 -545
- package/src/session/external-import.sql.ts +0 -18
- package/src/session/external-import.ts +0 -136
- package/src/session/goal.ts +0 -232
- package/src/session/index.ts +0 -1
- package/src/session/instruction.ts +0 -276
- package/src/session/last-message-info.ts +0 -32
- package/src/session/llm-request-prefix.ts +0 -82
- package/src/session/llm.ts +0 -737
- package/src/session/max-mode.ts +0 -410
- package/src/session/message-v2.ts +0 -1138
- package/src/session/message.ts +0 -191
- package/src/session/opencode-import.ts +0 -281
- package/src/session/overflow.ts +0 -53
- package/src/session/prefix-capture-ref.ts +0 -48
- package/src/session/processor.ts +0 -983
- package/src/session/projectors.ts +0 -137
- package/src/session/prompt/anthropic.txt +0 -154
- package/src/session/prompt/beast.txt +0 -155
- package/src/session/prompt/build-switch.txt +0 -5
- package/src/session/prompt/codex.txt +0 -79
- package/src/session/prompt/compose.txt +0 -119
- package/src/session/prompt/copilot-gpt-5.txt +0 -143
- package/src/session/prompt/deepseek.txt +0 -131
- package/src/session/prompt/default.old.txt +0 -151
- package/src/session/prompt/default.txt +0 -172
- package/src/session/prompt/gemini.txt +0 -155
- package/src/session/prompt/glm.txt +0 -51
- 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/minimax.txt +0 -140
- package/src/session/prompt/text-loop-recovery.ts +0 -40
- package/src/session/prompt/text-ngram-detection.ts +0 -87
- package/src/session/prompt/trinity.txt +0 -97
- package/src/session/prompt.ts +0 -3878
- package/src/session/prune.ts +0 -481
- package/src/session/retry.ts +0 -178
- package/src/session/revert.ts +0 -161
- package/src/session/run-state.ts +0 -135
- package/src/session/schema.ts +0 -36
- package/src/session/session.sql.ts +0 -110
- package/src/session/session.ts +0 -908
- package/src/session/status.ts +0 -89
- package/src/session/summary.ts +0 -163
- package/src/session/system.ts +0 -96
- package/src/session/todo.ts +0 -77
- package/src/session/trajectory.ts +0 -98
- package/src/share/index.ts +0 -2
- package/src/share/session.ts +0 -57
- package/src/share/share-next.ts +0 -381
- package/src/share/share.sql.ts +0 -13
- package/src/shell/shell.ts +0 -124
- package/src/skill/builtin/.bundle/self-extend/SKILL.md +0 -131
- package/src/skill/builtin/.bundle/self-extend/reference/hook-api.md +0 -242
- package/src/skill/builtin/.bundle/self-extend/reference/skill-api.md +0 -114
- package/src/skill/builtin/.bundle/self-extend/reference/tool-api.md +0 -115
- package/src/skill/builtin/.bundle/self-extend/reference/tui-api.md +0 -258
- package/src/skill/builtin/bundle.macro.ts +0 -30
- package/src/skill/builtin/extract.ts +0 -41
- package/src/skill/compose/.bundle/ask/SKILL.md +0 -58
- package/src/skill/compose/.bundle/brainstorm/SKILL.md +0 -200
- package/src/skill/compose/.bundle/brainstorm/scripts/frame-template.html +0 -214
- package/src/skill/compose/.bundle/brainstorm/scripts/helper.js +0 -88
- package/src/skill/compose/.bundle/brainstorm/scripts/server.cjs +0 -354
- package/src/skill/compose/.bundle/brainstorm/scripts/start-server.sh +0 -148
- package/src/skill/compose/.bundle/brainstorm/scripts/stop-server.sh +0 -56
- package/src/skill/compose/.bundle/brainstorm/spec-document-reviewer-prompt.md +0 -50
- package/src/skill/compose/.bundle/brainstorm/visual-companion.md +0 -258
- package/src/skill/compose/.bundle/debug/CREATION-LOG.md +0 -119
- package/src/skill/compose/.bundle/debug/SKILL.md +0 -297
- package/src/skill/compose/.bundle/debug/condition-based-waiting-example.ts +0 -158
- package/src/skill/compose/.bundle/debug/condition-based-waiting.md +0 -106
- package/src/skill/compose/.bundle/debug/defense-in-depth.md +0 -122
- package/src/skill/compose/.bundle/debug/find-polluter.sh +0 -63
- package/src/skill/compose/.bundle/debug/root-cause-tracing.md +0 -144
- package/src/skill/compose/.bundle/debug/test-academic.md +0 -14
- package/src/skill/compose/.bundle/debug/test-pressure-1.md +0 -58
- package/src/skill/compose/.bundle/debug/test-pressure-2.md +0 -68
- package/src/skill/compose/.bundle/debug/test-pressure-3.md +0 -69
- package/src/skill/compose/.bundle/execute/SKILL.md +0 -71
- package/src/skill/compose/.bundle/feedback/SKILL.md +0 -214
- package/src/skill/compose/.bundle/merge/SKILL.md +0 -252
- package/src/skill/compose/.bundle/new-skill/SKILL.md +0 -211
- package/src/skill/compose/.bundle/parallel/SKILL.md +0 -168
- package/src/skill/compose/.bundle/plan/SKILL.md +0 -183
- package/src/skill/compose/.bundle/plan/plan-document-reviewer-prompt.md +0 -50
- package/src/skill/compose/.bundle/report/SKILL.md +0 -180
- package/src/skill/compose/.bundle/review/SKILL.md +0 -104
- package/src/skill/compose/.bundle/review/code-reviewer.md +0 -178
- package/src/skill/compose/.bundle/subagent/SKILL.md +0 -325
- package/src/skill/compose/.bundle/subagent/code-quality-reviewer-prompt.md +0 -26
- package/src/skill/compose/.bundle/subagent/implementer-prompt.md +0 -128
- package/src/skill/compose/.bundle/subagent/spec-reviewer-prompt.md +0 -118
- package/src/skill/compose/.bundle/tdd/SKILL.md +0 -360
- package/src/skill/compose/.bundle/tdd/testing-anti-patterns.md +0 -299
- package/src/skill/compose/.bundle/verify/SKILL.md +0 -140
- package/src/skill/compose/.bundle/worktree/SKILL.md +0 -234
- package/src/skill/compose/LICENSE-karpathy +0 -28
- package/src/skill/compose/bundle.macro.ts +0 -30
- package/src/skill/compose/extract.ts +0 -85
- package/src/skill/discovery.ts +0 -114
- package/src/skill/index.ts +0 -328
- package/src/snapshot/index.ts +0 -777
- package/src/sql.d.ts +0 -4
- package/src/storage/db.bun.ts +0 -8
- package/src/storage/db.node.ts +0 -8
- package/src/storage/db.ts +0 -172
- package/src/storage/index.ts +0 -26
- package/src/storage/json-migration.ts +0 -426
- package/src/storage/read-sqlite.bun.ts +0 -11
- package/src/storage/read-sqlite.node.ts +0 -13
- package/src/storage/read-sqlite.ts +0 -10
- package/src/storage/schema.sql.ts +0 -10
- package/src/storage/schema.ts +0 -7
- package/src/storage/storage.ts +0 -331
- package/src/sync/README.md +0 -179
- package/src/sync/event.sql.ts +0 -16
- package/src/sync/index.ts +0 -278
- package/src/sync/schema.ts +0 -14
- package/src/task/events.ts +0 -28
- package/src/task/gate-state.ts +0 -54
- package/src/task/gate.ts +0 -116
- package/src/task/index.ts +0 -1
- package/src/task/registry.ts +0 -394
- package/src/task/schema.ts +0 -43
- package/src/task/task.sql.ts +0 -50
- package/src/team/events.ts +0 -22
- package/src/team/index.ts +0 -113
- package/src/team/schema.ts +0 -31
- package/src/temporary.ts +0 -33
- package/src/tool/actor.shell.txt +0 -72
- package/src/tool/actor.ts +0 -804
- package/src/tool/actor.txt +0 -103
- package/src/tool/apply_patch.ts +0 -308
- package/src/tool/apply_patch.txt +0 -33
- package/src/tool/bash-interactive.ts +0 -183
- package/src/tool/bash.ts +0 -704
- package/src/tool/bash.txt +0 -123
- package/src/tool/change-directory.ts +0 -91
- package/src/tool/codesearch.ts +0 -63
- package/src/tool/codesearch.txt +0 -12
- package/src/tool/edit.ts +0 -693
- package/src/tool/edit.txt +0 -10
- package/src/tool/external-directory.ts +0 -132
- package/src/tool/glob.ts +0 -100
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.ts +0 -145
- package/src/tool/grep.txt +0 -8
- package/src/tool/history.ts +0 -146
- package/src/tool/history.txt +0 -17
- package/src/tool/index.ts +0 -4
- package/src/tool/invalid.ts +0 -20
- package/src/tool/invocation-style.ts +0 -17
- package/src/tool/lsp.ts +0 -91
- package/src/tool/lsp.txt +0 -19
- package/src/tool/mcp-exa.ts +0 -78
- package/src/tool/memory-path-guard.ts +0 -162
- package/src/tool/memory.ts +0 -81
- package/src/tool/memory.txt +0 -69
- package/src/tool/multiedit.ts +0 -54
- package/src/tool/multiedit.txt +0 -41
- package/src/tool/notebook-edit.ts +0 -225
- package/src/tool/notebook-edit.txt +0 -10
- package/src/tool/plan-enter.txt +0 -16
- package/src/tool/plan-exit.txt +0 -14
- package/src/tool/plan.ts +0 -179
- package/src/tool/question.ts +0 -67
- package/src/tool/question.txt +0 -10
- package/src/tool/read-state.ts +0 -44
- package/src/tool/read.ts +0 -327
- package/src/tool/read.txt +0 -14
- package/src/tool/recoverable.ts +0 -35
- package/src/tool/registry.ts +0 -429
- package/src/tool/schema.ts +0 -17
- package/src/tool/session-cwd.ts +0 -35
- package/src/tool/shell-tokenize.ts +0 -374
- package/src/tool/shell-wrap.ts +0 -235
- package/src/tool/skill.ts +0 -76
- package/src/tool/skill.txt +0 -5
- package/src/tool/task.shell.txt +0 -57
- package/src/tool/task.ts +0 -456
- package/src/tool/task.txt +0 -56
- package/src/tool/tool.ts +0 -166
- package/src/tool/truncate.ts +0 -201
- package/src/tool/truncation-dir.ts +0 -4
- package/src/tool/webfetch.ts +0 -208
- package/src/tool/webfetch.txt +0 -13
- package/src/tool/websearch/index.ts +0 -104
- package/src/tool/websearch/sleepy.ts +0 -118
- package/src/tool/websearch/websearch.txt +0 -14
- package/src/tool/workflow.ts +0 -357
- package/src/tool/workflow.txt +0 -25
- package/src/tool/write.ts +0 -88
- package/src/tool/write.txt +0 -10
- package/src/util/abort.ts +0 -35
- package/src/util/archive.ts +0 -15
- package/src/util/color.ts +0 -17
- 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/effect-zod.ts +0 -367
- package/src/util/env-info.ts +0 -62
- package/src/util/error.ts +0 -78
- package/src/util/filesystem.ts +0 -243
- package/src/util/fn.ts +0 -21
- package/src/util/format.ts +0 -20
- package/src/util/iife.ts +0 -3
- package/src/util/index.ts +0 -14
- package/src/util/keybind.ts +0 -101
- package/src/util/lazy.ts +0 -18
- package/src/util/local-context.ts +0 -23
- package/src/util/locale.ts +0 -79
- package/src/util/lock.ts +0 -96
- package/src/util/log.ts +0 -234
- package/src/util/media.ts +0 -26
- package/src/util/network.ts +0 -9
- package/src/util/process.ts +0 -174
- package/src/util/provider-priority.ts +0 -48
- package/src/util/queue.ts +0 -60
- package/src/util/record.ts +0 -3
- package/src/util/rpc.ts +0 -64
- package/src/util/schema.ts +0 -53
- package/src/util/scrap.ts +0 -10
- package/src/util/signal.ts +0 -12
- package/src/util/sleepy-process.ts +0 -24
- package/src/util/ssrf.ts +0 -116
- package/src/util/timeout.ts +0 -14
- package/src/util/token.ts +0 -5
- package/src/util/tool-compat.ts +0 -144
- package/src/util/update-schema.ts +0 -13
- package/src/util/which.ts +0 -14
- package/src/util/wildcard.ts +0 -57
- package/src/workflow/builtin/compose.js +0 -749
- package/src/workflow/builtin/deep-research.js +0 -398
- package/src/workflow/builtin.ts +0 -59
- package/src/workflow/events.ts +0 -72
- package/src/workflow/meta.ts +0 -335
- package/src/workflow/persistence.ts +0 -312
- package/src/workflow/resolve.ts +0 -45
- package/src/workflow/runtime-ref.ts +0 -18
- package/src/workflow/runtime.ts +0 -1447
- package/src/workflow/sandbox.ts +0 -286
- package/src/workflow/workflow.sql.ts +0 -31
- package/src/workflow/workspace.ts +0 -69
- package/src/worktree/index.ts +0 -629
|
@@ -1,1376 +0,0 @@
|
|
|
1
|
-
import type { ModelMessage } from "ai"
|
|
2
|
-
import { mergeDeep, unique } from "remeda"
|
|
3
|
-
import type { JSONSchema7 } from "@ai-sdk/provider"
|
|
4
|
-
import type { JSONSchema } from "zod/v4/core"
|
|
5
|
-
import type * as Provider from "./provider"
|
|
6
|
-
import type * as ModelsDev from "./models"
|
|
7
|
-
import { iife } from "@/util/iife"
|
|
8
|
-
import { Flag } from "@/flag/flag"
|
|
9
|
-
|
|
10
|
-
type Modality = NonNullable<ModelsDev.Model["modalities"]>["input"][number]
|
|
11
|
-
|
|
12
|
-
function mimeToModality(mime: string): Modality | undefined {
|
|
13
|
-
if (mime.startsWith("image/")) return "image"
|
|
14
|
-
if (mime.startsWith("audio/")) return "audio"
|
|
15
|
-
if (mime.startsWith("video/")) return "video"
|
|
16
|
-
if (mime === "application/pdf") return "pdf"
|
|
17
|
-
return undefined
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Sleepy vision support isn't reflected in models.dev modality data, so the
|
|
21
|
-
// generic capability check would strip images before they reach the model.
|
|
22
|
-
// sleepy-auto and sleepy-v2.5 accept images; sleepy-v2.5-pro is text-only.
|
|
23
|
-
function supportsImageInput(model: Provider.Model): boolean {
|
|
24
|
-
if (model.providerID === "sleepy" || model.providerID === "sleepy" || model.providerID === "sleepy") {
|
|
25
|
-
const id = model.id.toLowerCase()
|
|
26
|
-
if (id.includes("v2.5-pro")) return false
|
|
27
|
-
if (id === "sleepy-auto" || id.includes("v2.5")) return true
|
|
28
|
-
}
|
|
29
|
-
// Claude and GPT models are all multimodal regardless of catalog data.
|
|
30
|
-
const id = model.id.toLowerCase()
|
|
31
|
-
const apiID = model.api.id.toLowerCase()
|
|
32
|
-
if (id.includes("claude") || apiID.includes("claude") || model.providerID === "anthropic") return true
|
|
33
|
-
if (id.includes("gpt") || apiID.includes("gpt")) return true
|
|
34
|
-
return model.capabilities.input.image
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const OUTPUT_TOKEN_MAX = Flag.SLEEPYCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX || 32_000
|
|
38
|
-
const SLEEPY_OUTPUT_TOKEN_MAX = 128_000
|
|
39
|
-
|
|
40
|
-
// Maps npm package to the key the AI SDK expects for providerOptions
|
|
41
|
-
function sdkKey(npm: string): string | undefined {
|
|
42
|
-
switch (npm) {
|
|
43
|
-
case "@ai-sdk/github-copilot":
|
|
44
|
-
return "copilot"
|
|
45
|
-
case "@ai-sdk/azure":
|
|
46
|
-
return "azure"
|
|
47
|
-
case "@ai-sdk/openai":
|
|
48
|
-
return "openai"
|
|
49
|
-
case "@ai-sdk/amazon-bedrock":
|
|
50
|
-
return "bedrock"
|
|
51
|
-
case "@ai-sdk/anthropic":
|
|
52
|
-
case "@ai-sdk/google-vertex/anthropic":
|
|
53
|
-
return "anthropic"
|
|
54
|
-
case "@ai-sdk/google-vertex":
|
|
55
|
-
return "vertex"
|
|
56
|
-
case "@ai-sdk/google":
|
|
57
|
-
return "google"
|
|
58
|
-
case "@ai-sdk/gateway":
|
|
59
|
-
return "gateway"
|
|
60
|
-
case "@openrouter/ai-sdk-provider":
|
|
61
|
-
return "openrouter"
|
|
62
|
-
}
|
|
63
|
-
return undefined
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function normalizeMessages(
|
|
67
|
-
msgs: ModelMessage[],
|
|
68
|
-
model: Provider.Model,
|
|
69
|
-
_options: Record<string, unknown>,
|
|
70
|
-
): ModelMessage[] {
|
|
71
|
-
// Anthropic rejects messages with empty content - filter out empty string messages
|
|
72
|
-
// and remove empty text/reasoning parts from array content
|
|
73
|
-
if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/amazon-bedrock") {
|
|
74
|
-
msgs = msgs
|
|
75
|
-
.map((msg) => {
|
|
76
|
-
if (typeof msg.content === "string") {
|
|
77
|
-
if (msg.content === "") return undefined
|
|
78
|
-
return msg
|
|
79
|
-
}
|
|
80
|
-
if (!Array.isArray(msg.content)) return msg
|
|
81
|
-
const filtered = msg.content.filter((part) => {
|
|
82
|
-
if (part.type === "text" || part.type === "reasoning") {
|
|
83
|
-
return part.text !== ""
|
|
84
|
-
}
|
|
85
|
-
return true
|
|
86
|
-
})
|
|
87
|
-
if (filtered.length === 0) return undefined
|
|
88
|
-
return { ...msg, content: filtered }
|
|
89
|
-
})
|
|
90
|
-
.filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "")
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (model.api.id.includes("claude")) {
|
|
94
|
-
const scrub = (id: string) => id.replace(/[^a-zA-Z0-9_-]/g, "_")
|
|
95
|
-
msgs = msgs.map((msg) => {
|
|
96
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
97
|
-
return {
|
|
98
|
-
...msg,
|
|
99
|
-
content: msg.content.map((part) => {
|
|
100
|
-
if (part.type === "tool-call" || part.type === "tool-result") {
|
|
101
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
102
|
-
}
|
|
103
|
-
return part
|
|
104
|
-
}),
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (msg.role === "tool" && Array.isArray(msg.content)) {
|
|
108
|
-
return {
|
|
109
|
-
...msg,
|
|
110
|
-
content: msg.content.map((part) => {
|
|
111
|
-
if (part.type === "tool-result") {
|
|
112
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
113
|
-
}
|
|
114
|
-
return part
|
|
115
|
-
}),
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return msg
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
if (["@ai-sdk/anthropic", "@ai-sdk/google-vertex/anthropic"].includes(model.api.npm)) {
|
|
122
|
-
// Anthropic rejects assistant turns where tool_use blocks are followed by non-tool
|
|
123
|
-
// content, e.g. [tool_use, tool_use, text], with:
|
|
124
|
-
// `tool_use` ids were found without `tool_result` blocks immediately after...
|
|
125
|
-
//
|
|
126
|
-
// Reorder that invalid shape into [text] + [tool_use, tool_use]. Consecutive
|
|
127
|
-
// assistant messages are later merged by the provider/SDK, so preserving the
|
|
128
|
-
// original [tool_use...] then [text] order still produces the invalid payload.
|
|
129
|
-
//
|
|
130
|
-
// The root cause appears to be somewhere upstream where the stream is originally
|
|
131
|
-
// processed. We were unable to locate an exact narrower reproduction elsewhere,
|
|
132
|
-
// so we keep this transform in place for the time being.
|
|
133
|
-
msgs = msgs.flatMap((msg) => {
|
|
134
|
-
if (msg.role !== "assistant" || !Array.isArray(msg.content)) return [msg]
|
|
135
|
-
|
|
136
|
-
const parts = msg.content
|
|
137
|
-
const first = parts.findIndex((part) => part.type === "tool-call")
|
|
138
|
-
if (first === -1) return [msg]
|
|
139
|
-
if (!parts.slice(first).some((part) => part.type !== "tool-call")) return [msg]
|
|
140
|
-
return [
|
|
141
|
-
{ ...msg, content: parts.filter((part) => part.type !== "tool-call") },
|
|
142
|
-
{ ...msg, content: parts.filter((part) => part.type === "tool-call") },
|
|
143
|
-
]
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
if (
|
|
147
|
-
model.providerID === "mistral" ||
|
|
148
|
-
model.api.id.toLowerCase().includes("mistral") ||
|
|
149
|
-
model.api.id.toLocaleLowerCase().includes("devstral")
|
|
150
|
-
) {
|
|
151
|
-
const scrub = (id: string) => {
|
|
152
|
-
return id
|
|
153
|
-
.replace(/[^a-zA-Z0-9]/g, "") // Remove non-alphanumeric characters
|
|
154
|
-
.substring(0, 9) // Take first 9 characters
|
|
155
|
-
.padEnd(9, "0") // Pad with zeros if less than 9 characters
|
|
156
|
-
}
|
|
157
|
-
const result: ModelMessage[] = []
|
|
158
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
159
|
-
const msg = msgs[i]
|
|
160
|
-
const nextMsg = msgs[i + 1]
|
|
161
|
-
|
|
162
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
163
|
-
msg.content = msg.content.map((part) => {
|
|
164
|
-
if (part.type === "tool-call" || part.type === "tool-result") {
|
|
165
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
166
|
-
}
|
|
167
|
-
return part
|
|
168
|
-
})
|
|
169
|
-
}
|
|
170
|
-
if (msg.role === "tool" && Array.isArray(msg.content)) {
|
|
171
|
-
msg.content = msg.content.map((part) => {
|
|
172
|
-
if (part.type === "tool-result") {
|
|
173
|
-
return { ...part, toolCallId: scrub(part.toolCallId) }
|
|
174
|
-
}
|
|
175
|
-
return part
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
result.push(msg)
|
|
179
|
-
|
|
180
|
-
// Fix message sequence: tool messages cannot be followed by user messages
|
|
181
|
-
if (msg.role === "tool" && nextMsg?.role === "user") {
|
|
182
|
-
result.push({
|
|
183
|
-
role: "assistant",
|
|
184
|
-
content: [
|
|
185
|
-
{
|
|
186
|
-
type: "text",
|
|
187
|
-
text: "Done.",
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
})
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return result
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (typeof model.capabilities.interleaved === "object" && model.capabilities.interleaved.field) {
|
|
197
|
-
const field = model.capabilities.interleaved.field
|
|
198
|
-
return msgs.map((msg) => {
|
|
199
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
200
|
-
const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
|
|
201
|
-
const reasoningText = reasoningParts.map((part: any) => part.text).join("")
|
|
202
|
-
|
|
203
|
-
// Filter out reasoning parts from content
|
|
204
|
-
const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
|
|
205
|
-
|
|
206
|
-
// Include reasoning_content | reasoning_details directly on the message for all assistant messages
|
|
207
|
-
if (reasoningText) {
|
|
208
|
-
return {
|
|
209
|
-
...msg,
|
|
210
|
-
content: filteredContent,
|
|
211
|
-
providerOptions: {
|
|
212
|
-
...msg.providerOptions,
|
|
213
|
-
openaiCompatible: {
|
|
214
|
-
...msg.providerOptions?.openaiCompatible,
|
|
215
|
-
[field]: reasoningText,
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return {
|
|
222
|
-
...msg,
|
|
223
|
-
content: filteredContent,
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return msg
|
|
228
|
-
})
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return msgs
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Determines whether a model's provider respects inline cache_control / cachePoint
|
|
235
|
-
// markers. Pure name matching (model.api.id.includes("claude")) is fragile — a Claude
|
|
236
|
-
// model behind an OpenAI-compatible proxy gets matched but markers are silently dropped.
|
|
237
|
-
// See docs/cache-policy.md and upstream opencode#26786.
|
|
238
|
-
function supportsCacheMarkers(model: Provider.Model): boolean {
|
|
239
|
-
// Anthropic-only SDKs — always support inline markers
|
|
240
|
-
if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/google-vertex/anthropic") return true
|
|
241
|
-
if (model.providerID === "anthropic" || model.providerID === "google-vertex-anthropic") return true
|
|
242
|
-
// Bedrock cachePoint is a Converse API feature, works across model families
|
|
243
|
-
if (model.api.npm === "@ai-sdk/amazon-bedrock") return true
|
|
244
|
-
// Multi-model providers: only Anthropic/Claude models support cache markers
|
|
245
|
-
if (
|
|
246
|
-
model.api.npm === "@openrouter/ai-sdk-provider" ||
|
|
247
|
-
model.api.npm === "@ai-sdk/github-copilot" ||
|
|
248
|
-
model.api.npm === "@ai-sdk/alibaba"
|
|
249
|
-
) {
|
|
250
|
-
return (
|
|
251
|
-
model.api.id.includes("claude") ||
|
|
252
|
-
model.api.id.includes("anthropic") ||
|
|
253
|
-
model.id.includes("claude") ||
|
|
254
|
-
model.id.includes("anthropic")
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
return false
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// The cache-control marker shape differs per provider/SDK. This is the single
|
|
261
|
-
// source of truth, keyed by the SDK provider-options namespace. `applyCaching`
|
|
262
|
-
// attaches the whole object (keyed by stored providerID) and lets `message()`
|
|
263
|
-
// remap the active provider's namespace to its SDK key; `tools()` (which
|
|
264
|
-
// bypasses that remap) resolves a single namespace up front via `cacheMarkerFor`.
|
|
265
|
-
// Only Anthropic and OpenRouter expose a TTL in their AI SDK — the others ignore
|
|
266
|
-
// an unknown `ttl`, so we thread it only there.
|
|
267
|
-
function cacheMarkerOptions(model: Provider.Model) {
|
|
268
|
-
const ttl = model.cachePromptTTL === "1h" ? { ttl: "1h" as const } : {}
|
|
269
|
-
return {
|
|
270
|
-
anthropic: { cacheControl: { type: "ephemeral", ...ttl } },
|
|
271
|
-
openrouter: { cacheControl: { type: "ephemeral", ...ttl } },
|
|
272
|
-
bedrock: { cachePoint: { type: "default" } },
|
|
273
|
-
openaiCompatible: { cache_control: { type: "ephemeral" } },
|
|
274
|
-
copilot: { copilot_cache_control: { type: "ephemeral" } },
|
|
275
|
-
alibaba: { cacheControl: { type: "ephemeral" } },
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Resolve the marker for a single model, already keyed under the SDK namespace
|
|
280
|
-
// the AI SDK expects — i.e. the remap that `message()` performs for messages,
|
|
281
|
-
// done up front. Used by `tools()`, whose tools never pass through `message()`.
|
|
282
|
-
// Returns undefined for providers that don't take inline markers (callers gate
|
|
283
|
-
// on `supportsCacheMarkers` first, so this is just a type-safety fallback).
|
|
284
|
-
function cacheMarkerFor(model: Provider.Model): Record<string, unknown> | undefined {
|
|
285
|
-
const shapes = cacheMarkerOptions(model)
|
|
286
|
-
const ns: keyof typeof shapes | undefined =
|
|
287
|
-
model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/google-vertex/anthropic"
|
|
288
|
-
? "anthropic"
|
|
289
|
-
: model.api.npm === "@openrouter/ai-sdk-provider"
|
|
290
|
-
? "openrouter"
|
|
291
|
-
: model.api.npm === "@ai-sdk/amazon-bedrock"
|
|
292
|
-
? "bedrock"
|
|
293
|
-
: model.api.npm === "@ai-sdk/github-copilot"
|
|
294
|
-
? "copilot"
|
|
295
|
-
: model.api.npm === "@ai-sdk/alibaba"
|
|
296
|
-
? "alibaba"
|
|
297
|
-
: undefined
|
|
298
|
-
if (!ns) return undefined
|
|
299
|
-
return { [ns]: shapes[ns] }
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function applyCaching(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
|
|
303
|
-
const providerOptions = cacheMarkerOptions(model)
|
|
304
|
-
|
|
305
|
-
// Strategy: prefix caching is longest-common-prefix based with a backward
|
|
306
|
-
// lookback window (Anthropic walks back ~20 blocks from a breakpoint to find
|
|
307
|
-
// a prior write). The markers that grow the cached prefix are pinned to the
|
|
308
|
-
// *tail* of the request. We place up to three stable breakpoints (Anthropic
|
|
309
|
-
// allows max 4):
|
|
310
|
-
// 1. Last system message — the immutable prompt prefix.
|
|
311
|
-
// 2+3. The last TWO messages — a "rolling double buffer". Each turn marks
|
|
312
|
-
// messages[-2] and messages[-1]; next turn the old [-1] is now [-2] and
|
|
313
|
-
// still carries its marker, so the lookback gets a cache READ hit, while
|
|
314
|
-
// the new [-1] is the WRITE for the turn after.
|
|
315
|
-
//
|
|
316
|
-
// Why two and not one: the second (next-to-last) marker is the safety
|
|
317
|
-
// net for the tail boundary. When the last message is removed — a
|
|
318
|
-
// tool-call retry, a Ctrl-C, or the user editing/deleting their latest
|
|
319
|
-
// message — a lone tail marker disappears with it, and how much of the
|
|
320
|
-
// surrounding prefix the provider then evicts depends on the upstream
|
|
321
|
-
// (Anthropic) KV-cache implementation. The next-to-last marker is a
|
|
322
|
-
// still-present, further-back write the next lookback can land on, so the
|
|
323
|
-
// worst case degrades to "recompute only the removed message" instead of
|
|
324
|
-
// "recompute the whole history". It also covers turns that append >20
|
|
325
|
-
// blocks (tool spam pushes the prior write outside the lookback window).
|
|
326
|
-
// Cost is ~equal to a single marker: the two adjacent breakpoints write
|
|
327
|
-
// roughly the same incremental bytes as one, split in two, and a hit
|
|
328
|
-
// never rewrites. A third marker would write a segment never read
|
|
329
|
-
// independently, so two is the minimum that covers the boundary.
|
|
330
|
-
// We deliberately do NOT mark a drifting midpoint or a fixed before-last-user
|
|
331
|
-
// INDEX: those shift every turn without tracking the tail.
|
|
332
|
-
const targets: ModelMessage[] = []
|
|
333
|
-
|
|
334
|
-
const systemMsgs = msgs.filter((msg) => msg.role === "system")
|
|
335
|
-
if (systemMsgs.length > 0) targets.push(systemMsgs[systemMsgs.length - 1])
|
|
336
|
-
|
|
337
|
-
const nonSystem = msgs.filter((msg) => msg.role !== "system")
|
|
338
|
-
for (const msg of nonSystem.slice(-2)) targets.push(msg)
|
|
339
|
-
|
|
340
|
-
for (const msg of unique(targets)) {
|
|
341
|
-
const useMessageLevelOptions =
|
|
342
|
-
model.providerID === "anthropic" ||
|
|
343
|
-
model.providerID.includes("bedrock") ||
|
|
344
|
-
model.api.npm === "@ai-sdk/amazon-bedrock"
|
|
345
|
-
const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(msg.content) && msg.content.length > 0
|
|
346
|
-
|
|
347
|
-
if (shouldUseContentOptions) {
|
|
348
|
-
const lastContent = msg.content[msg.content.length - 1]
|
|
349
|
-
if (
|
|
350
|
-
lastContent &&
|
|
351
|
-
typeof lastContent === "object" &&
|
|
352
|
-
lastContent.type !== "tool-approval-request" &&
|
|
353
|
-
lastContent.type !== "tool-approval-response"
|
|
354
|
-
) {
|
|
355
|
-
lastContent.providerOptions = mergeDeep(lastContent.providerOptions ?? {}, providerOptions)
|
|
356
|
-
continue
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
msg.providerOptions = mergeDeep(msg.providerOptions ?? {}, providerOptions)
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return msgs
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function unsupportedParts(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] {
|
|
367
|
-
return msgs.map((msg) => {
|
|
368
|
-
if (msg.role !== "user" || !Array.isArray(msg.content)) return msg
|
|
369
|
-
|
|
370
|
-
const filtered = msg.content.map((part) => {
|
|
371
|
-
if (part.type !== "file" && part.type !== "image") return part
|
|
372
|
-
|
|
373
|
-
// Check for empty base64 image data
|
|
374
|
-
if (part.type === "image") {
|
|
375
|
-
const imageStr = String(part.image)
|
|
376
|
-
if (imageStr.startsWith("data:")) {
|
|
377
|
-
const match = imageStr.match(/^data:([^;]+);base64,(.*)$/)
|
|
378
|
-
if (match && (!match[2] || match[2].length === 0)) {
|
|
379
|
-
return {
|
|
380
|
-
type: "text" as const,
|
|
381
|
-
text: "ERROR: Image file is empty or corrupted. Please provide a valid image.",
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const mime = part.type === "image" ? String(part.image).split(";")[0].replace("data:", "") : part.mediaType
|
|
388
|
-
const filename = part.type === "file" ? part.filename : undefined
|
|
389
|
-
const modality = mimeToModality(mime)
|
|
390
|
-
if (!modality) return part
|
|
391
|
-
const supported = modality === "image" ? supportsImageInput(model) : model.capabilities.input[modality]
|
|
392
|
-
if (supported) return part
|
|
393
|
-
|
|
394
|
-
const name = filename ? `"${filename}"` : modality
|
|
395
|
-
return {
|
|
396
|
-
type: "text" as const,
|
|
397
|
-
text: `ERROR: Cannot read ${name} (this model does not support ${modality} input). Inform the user.`,
|
|
398
|
-
}
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
return { ...msg, content: filtered }
|
|
402
|
-
})
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Returns the decoded byte size of a base64 data URL, or undefined for inputs
|
|
406
|
-
// that aren't data URLs (remote URLs, raw binary) and therefore can't be sized.
|
|
407
|
-
function imageByteSize(image: string): number | undefined {
|
|
408
|
-
if (!image.startsWith("data:")) return undefined
|
|
409
|
-
const base64 = image.slice(image.indexOf(",") + 1)
|
|
410
|
-
if (!base64) return 0
|
|
411
|
-
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0
|
|
412
|
-
return Math.floor((base64.length * 3) / 4) - padding
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
function limitImages(msgs: ModelMessage[]): ModelMessage[] {
|
|
416
|
-
const maxImages = Flag.SLEEPYCODE_MAX_PROMPT_IMAGES
|
|
417
|
-
const maxSize = Flag.SLEEPYCODE_MAX_PROMPT_IMAGE_SIZE
|
|
418
|
-
if (maxImages === undefined && maxSize === undefined) return msgs
|
|
419
|
-
|
|
420
|
-
const total = msgs.reduce(
|
|
421
|
-
(sum, msg) =>
|
|
422
|
-
msg.role === "user" && Array.isArray(msg.content)
|
|
423
|
-
? sum + msg.content.filter((part) => part.type === "image").length
|
|
424
|
-
: sum,
|
|
425
|
-
0,
|
|
426
|
-
)
|
|
427
|
-
// Drop the oldest excess images so the most recent ones reach the model.
|
|
428
|
-
let toDrop = maxImages === undefined ? 0 : Math.max(0, total - maxImages)
|
|
429
|
-
|
|
430
|
-
return msgs.map((msg) => {
|
|
431
|
-
if (msg.role !== "user" || !Array.isArray(msg.content)) return msg
|
|
432
|
-
const content = msg.content.map((part) => {
|
|
433
|
-
if (part.type !== "image") return part
|
|
434
|
-
if (toDrop > 0) {
|
|
435
|
-
toDrop--
|
|
436
|
-
return { type: "text" as const, text: `[Image omitted: exceeds the configured limit of ${maxImages} prompt image(s).]` }
|
|
437
|
-
}
|
|
438
|
-
if (maxSize !== undefined) {
|
|
439
|
-
const size = imageByteSize(String(part.image))
|
|
440
|
-
if (size !== undefined && size > maxSize) {
|
|
441
|
-
return { type: "text" as const, text: `[Image omitted: exceeds the configured ${maxSize}-byte prompt image size limit.]` }
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return part
|
|
445
|
-
})
|
|
446
|
-
return { ...msg, content }
|
|
447
|
-
})
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
export function message(msgs: ModelMessage[], model: Provider.Model, options: Record<string, unknown>) {
|
|
451
|
-
msgs = unsupportedParts(msgs, model)
|
|
452
|
-
msgs = limitImages(msgs)
|
|
453
|
-
msgs = normalizeMessages(msgs, model, options)
|
|
454
|
-
if (supportsCacheMarkers(model)) {
|
|
455
|
-
msgs = applyCaching(msgs, model)
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Remap providerOptions keys from stored providerID to expected SDK key
|
|
459
|
-
const key = sdkKey(model.api.npm)
|
|
460
|
-
if (key && key !== model.providerID) {
|
|
461
|
-
const remap = (opts: Record<string, any> | undefined) => {
|
|
462
|
-
if (!opts) return opts
|
|
463
|
-
if (!(model.providerID in opts)) return opts
|
|
464
|
-
const result = { ...opts }
|
|
465
|
-
result[key] = result[model.providerID]
|
|
466
|
-
delete result[model.providerID]
|
|
467
|
-
return result
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
msgs = msgs.map((msg) => {
|
|
471
|
-
if (!Array.isArray(msg.content)) return { ...msg, providerOptions: remap(msg.providerOptions) }
|
|
472
|
-
return {
|
|
473
|
-
...msg,
|
|
474
|
-
providerOptions: remap(msg.providerOptions),
|
|
475
|
-
content: msg.content.map((part) => {
|
|
476
|
-
if (part.type === "tool-approval-request" || part.type === "tool-approval-response") {
|
|
477
|
-
return { ...part }
|
|
478
|
-
}
|
|
479
|
-
return { ...part, providerOptions: remap(part.providerOptions) }
|
|
480
|
-
}),
|
|
481
|
-
} as typeof msg
|
|
482
|
-
})
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
return msgs
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Place a cache breakpoint on the tool definitions. The cache hierarchy is
|
|
489
|
-
// `tools` → `system` → `messages`, so marking the LAST tool caches the entire
|
|
490
|
-
// tool-schema block (often several KB) as a stable prefix that sits in front of
|
|
491
|
-
// the system + message caches. Tools are passed to the SDK separately from
|
|
492
|
-
// `message()` and never go through its providerID→SDK-key remap, so we resolve
|
|
493
|
-
// the SDK-keyed marker via `cacheMarkerFor`. Tool registration order is stable
|
|
494
|
-
// (insertion order of the tools record), so "last tool" is deterministic.
|
|
495
|
-
export function tools<T extends Record<string, any>>(tools: T, model: Provider.Model): T {
|
|
496
|
-
if (!supportsCacheMarkers(model)) return tools
|
|
497
|
-
const marker = cacheMarkerFor(model)
|
|
498
|
-
if (!marker) return tools
|
|
499
|
-
const names = Object.keys(tools)
|
|
500
|
-
if (names.length === 0) return tools
|
|
501
|
-
|
|
502
|
-
const last = tools[names[names.length - 1]]
|
|
503
|
-
last.providerOptions = mergeDeep(last.providerOptions ?? {}, marker)
|
|
504
|
-
return tools
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export function temperature(model: Provider.Model) {
|
|
508
|
-
const id = model.id.toLowerCase()
|
|
509
|
-
if (id.includes("qwen")) return 0.55
|
|
510
|
-
if (id.includes("claude")) return undefined
|
|
511
|
-
if (id.includes("gemini")) return 1.0
|
|
512
|
-
if (id.includes("glm-4.6")) return 1.0
|
|
513
|
-
if (id.includes("glm-4.7")) return 1.0
|
|
514
|
-
if (id.includes("minimax-m2")) return 1.0
|
|
515
|
-
if (id.includes("sleepy")) return 1.0
|
|
516
|
-
if (id.includes("kimi-k2")) {
|
|
517
|
-
// kimi-k2-thinking & kimi-k2.5 && kimi-k2p5 && kimi-k2-5
|
|
518
|
-
if (["thinking", "k2.", "k2p", "k2-5"].some((s) => id.includes(s))) {
|
|
519
|
-
return 1.0
|
|
520
|
-
}
|
|
521
|
-
return 0.6
|
|
522
|
-
}
|
|
523
|
-
return undefined
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
export function topP(model: Provider.Model) {
|
|
527
|
-
const id = model.id.toLowerCase()
|
|
528
|
-
if (id.includes("qwen")) return 1
|
|
529
|
-
if (["minimax-m2", "gemini", "kimi-k2.5", "kimi-k2p5", "kimi-k2-5"].some((s) => id.includes(s))) {
|
|
530
|
-
return 0.95
|
|
531
|
-
}
|
|
532
|
-
return undefined
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
export function topK(model: Provider.Model) {
|
|
536
|
-
const id = model.id.toLowerCase()
|
|
537
|
-
if (id.includes("minimax-m2")) {
|
|
538
|
-
if (["m2.", "m25", "m21"].some((s) => id.includes(s))) return 40
|
|
539
|
-
return 20
|
|
540
|
-
}
|
|
541
|
-
if (id.includes("gemini")) return 64
|
|
542
|
-
return undefined
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const WIDELY_SUPPORTED_EFFORTS = ["low", "medium", "high"]
|
|
546
|
-
const OPENAI_EFFORTS = ["none", "minimal", ...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
547
|
-
|
|
548
|
-
function anthropicAdaptiveEfforts(apiId: string): string[] | null {
|
|
549
|
-
if (["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => apiId.includes(v))) {
|
|
550
|
-
return ["low", "medium", "high", "xhigh", "max"]
|
|
551
|
-
}
|
|
552
|
-
if (["opus-4-6", "opus-4.6", "sonnet-4-6", "sonnet-4.6"].some((v) => apiId.includes(v))) {
|
|
553
|
-
return ["low", "medium", "high", "max"]
|
|
554
|
-
}
|
|
555
|
-
return null
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
export function variants(model: Provider.Model): Record<string, Record<string, any>> {
|
|
559
|
-
if (!model.capabilities.reasoning) return {}
|
|
560
|
-
|
|
561
|
-
const id = model.id.toLowerCase()
|
|
562
|
-
const adaptiveEfforts = anthropicAdaptiveEfforts(model.api.id)
|
|
563
|
-
if (
|
|
564
|
-
id.includes("deepseek") ||
|
|
565
|
-
id.includes("minimax") ||
|
|
566
|
-
id.includes("glm") ||
|
|
567
|
-
id.includes("mistral") ||
|
|
568
|
-
id.includes("kimi") ||
|
|
569
|
-
id.includes("k2p5") ||
|
|
570
|
-
id.includes("qwen") ||
|
|
571
|
-
id.includes("big-pickle")
|
|
572
|
-
)
|
|
573
|
-
return {}
|
|
574
|
-
|
|
575
|
-
// see: https://docs.x.ai/docs/guides/reasoning#control-how-hard-the-model-thinks
|
|
576
|
-
if (id.includes("grok") && id.includes("grok-3-mini")) {
|
|
577
|
-
if (model.api.npm === "@openrouter/ai-sdk-provider") {
|
|
578
|
-
return {
|
|
579
|
-
low: { reasoning: { effort: "low" } },
|
|
580
|
-
high: { reasoning: { effort: "high" } },
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
return {
|
|
584
|
-
low: { reasoningEffort: "low" },
|
|
585
|
-
high: { reasoningEffort: "high" },
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
if (id.includes("grok")) return {}
|
|
589
|
-
|
|
590
|
-
switch (model.api.npm) {
|
|
591
|
-
case "@openrouter/ai-sdk-provider":
|
|
592
|
-
if (!model.id.includes("gpt") && !model.id.includes("gemini-3") && !model.id.includes("claude")) return {}
|
|
593
|
-
return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }]))
|
|
594
|
-
|
|
595
|
-
case "@ai-sdk/gateway":
|
|
596
|
-
if (model.id.includes("anthropic")) {
|
|
597
|
-
if (adaptiveEfforts) {
|
|
598
|
-
return Object.fromEntries(
|
|
599
|
-
adaptiveEfforts.map((effort) => [
|
|
600
|
-
effort,
|
|
601
|
-
{
|
|
602
|
-
thinking: {
|
|
603
|
-
type: "adaptive",
|
|
604
|
-
},
|
|
605
|
-
effort,
|
|
606
|
-
},
|
|
607
|
-
]),
|
|
608
|
-
)
|
|
609
|
-
}
|
|
610
|
-
return {
|
|
611
|
-
high: {
|
|
612
|
-
thinking: {
|
|
613
|
-
type: "enabled",
|
|
614
|
-
budgetTokens: 16000,
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
max: {
|
|
618
|
-
thinking: {
|
|
619
|
-
type: "enabled",
|
|
620
|
-
budgetTokens: 31999,
|
|
621
|
-
},
|
|
622
|
-
},
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
if (model.id.includes("google")) {
|
|
626
|
-
if (id.includes("2.5")) {
|
|
627
|
-
return {
|
|
628
|
-
high: {
|
|
629
|
-
thinkingConfig: {
|
|
630
|
-
includeThoughts: true,
|
|
631
|
-
thinkingBudget: 16000,
|
|
632
|
-
},
|
|
633
|
-
},
|
|
634
|
-
max: {
|
|
635
|
-
thinkingConfig: {
|
|
636
|
-
includeThoughts: true,
|
|
637
|
-
thinkingBudget: 24576,
|
|
638
|
-
},
|
|
639
|
-
},
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
return Object.fromEntries(
|
|
643
|
-
["low", "high"].map((effort) => [
|
|
644
|
-
effort,
|
|
645
|
-
{
|
|
646
|
-
includeThoughts: true,
|
|
647
|
-
thinkingLevel: effort,
|
|
648
|
-
},
|
|
649
|
-
]),
|
|
650
|
-
)
|
|
651
|
-
}
|
|
652
|
-
return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
653
|
-
|
|
654
|
-
case "@ai-sdk/github-copilot":
|
|
655
|
-
if (model.id.includes("gemini")) {
|
|
656
|
-
// currently github copilot only returns thinking
|
|
657
|
-
return {}
|
|
658
|
-
}
|
|
659
|
-
if (model.id.includes("claude")) {
|
|
660
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
661
|
-
}
|
|
662
|
-
const copilotEfforts = iife(() => {
|
|
663
|
-
if (id.includes("5.1-codex-max") || id.includes("5.2") || id.includes("5.3"))
|
|
664
|
-
return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
665
|
-
const arr = [...WIDELY_SUPPORTED_EFFORTS]
|
|
666
|
-
if (id.includes("gpt-5") && model.release_date >= "2025-12-04") arr.push("xhigh")
|
|
667
|
-
return arr
|
|
668
|
-
})
|
|
669
|
-
return Object.fromEntries(
|
|
670
|
-
copilotEfforts.map((effort) => [
|
|
671
|
-
effort,
|
|
672
|
-
{
|
|
673
|
-
reasoningEffort: effort,
|
|
674
|
-
reasoningSummary: "auto",
|
|
675
|
-
include: ["reasoning.encrypted_content"],
|
|
676
|
-
},
|
|
677
|
-
]),
|
|
678
|
-
)
|
|
679
|
-
|
|
680
|
-
case "@ai-sdk/cerebras":
|
|
681
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/cerebras
|
|
682
|
-
case "@ai-sdk/togetherai":
|
|
683
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/togetherai
|
|
684
|
-
case "@ai-sdk/xai":
|
|
685
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/xai
|
|
686
|
-
case "@ai-sdk/deepinfra":
|
|
687
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/deepinfra
|
|
688
|
-
case "venice-ai-sdk-provider":
|
|
689
|
-
// https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort
|
|
690
|
-
case "@ai-sdk/openai-compatible":
|
|
691
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
692
|
-
|
|
693
|
-
case "@ai-sdk/azure":
|
|
694
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/azure
|
|
695
|
-
if (id === "o1-mini") return {}
|
|
696
|
-
const azureEfforts = ["low", "medium", "high"]
|
|
697
|
-
if (id.includes("gpt-5-") || id === "gpt-5") {
|
|
698
|
-
azureEfforts.unshift("minimal")
|
|
699
|
-
}
|
|
700
|
-
return Object.fromEntries(
|
|
701
|
-
azureEfforts.map((effort) => [
|
|
702
|
-
effort,
|
|
703
|
-
{
|
|
704
|
-
reasoningEffort: effort,
|
|
705
|
-
reasoningSummary: "auto",
|
|
706
|
-
include: ["reasoning.encrypted_content"],
|
|
707
|
-
},
|
|
708
|
-
]),
|
|
709
|
-
)
|
|
710
|
-
case "@ai-sdk/openai":
|
|
711
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/openai
|
|
712
|
-
if (id === "gpt-5-pro") return {}
|
|
713
|
-
const openaiEfforts = iife(() => {
|
|
714
|
-
if (id.includes("codex")) {
|
|
715
|
-
if (id.includes("5.2") || id.includes("5.3")) return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"]
|
|
716
|
-
return WIDELY_SUPPORTED_EFFORTS
|
|
717
|
-
}
|
|
718
|
-
const arr = [...WIDELY_SUPPORTED_EFFORTS]
|
|
719
|
-
if (id.includes("gpt-5-") || id === "gpt-5") {
|
|
720
|
-
arr.unshift("minimal")
|
|
721
|
-
}
|
|
722
|
-
if (model.release_date >= "2025-11-13") {
|
|
723
|
-
arr.unshift("none")
|
|
724
|
-
}
|
|
725
|
-
if (model.release_date >= "2025-12-04") {
|
|
726
|
-
arr.push("xhigh")
|
|
727
|
-
}
|
|
728
|
-
return arr
|
|
729
|
-
})
|
|
730
|
-
return Object.fromEntries(
|
|
731
|
-
openaiEfforts.map((effort) => [
|
|
732
|
-
effort,
|
|
733
|
-
{
|
|
734
|
-
reasoningEffort: effort,
|
|
735
|
-
reasoningSummary: "auto",
|
|
736
|
-
include: ["reasoning.encrypted_content"],
|
|
737
|
-
},
|
|
738
|
-
]),
|
|
739
|
-
)
|
|
740
|
-
|
|
741
|
-
case "@ai-sdk/anthropic":
|
|
742
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/anthropic
|
|
743
|
-
case "@ai-sdk/google-vertex/anthropic":
|
|
744
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex#anthropic-provider
|
|
745
|
-
|
|
746
|
-
if (model.providerID === "github-copilot") {
|
|
747
|
-
if (model.api.id.includes("opus-4.7")) {
|
|
748
|
-
return Object.fromEntries(["medium"].map((effort) => [effort, { reasoningEffort: effort }]))
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
if (adaptiveEfforts) {
|
|
753
|
-
return Object.fromEntries(
|
|
754
|
-
adaptiveEfforts.map((effort) => [
|
|
755
|
-
effort,
|
|
756
|
-
{
|
|
757
|
-
thinking: {
|
|
758
|
-
type: "adaptive",
|
|
759
|
-
...(["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => model.api.id.includes(v))
|
|
760
|
-
? { display: "summarized" }
|
|
761
|
-
: {}),
|
|
762
|
-
},
|
|
763
|
-
effort,
|
|
764
|
-
},
|
|
765
|
-
]),
|
|
766
|
-
)
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
return {
|
|
770
|
-
high: {
|
|
771
|
-
thinking: {
|
|
772
|
-
type: "enabled",
|
|
773
|
-
budgetTokens: Math.min(16_000, Math.floor(model.limit.output / 2 - 1)),
|
|
774
|
-
},
|
|
775
|
-
},
|
|
776
|
-
max: {
|
|
777
|
-
thinking: {
|
|
778
|
-
type: "enabled",
|
|
779
|
-
budgetTokens: Math.min(31_999, model.limit.output - 1),
|
|
780
|
-
},
|
|
781
|
-
},
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
case "@ai-sdk/amazon-bedrock":
|
|
785
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock
|
|
786
|
-
if (adaptiveEfforts) {
|
|
787
|
-
return Object.fromEntries(
|
|
788
|
-
adaptiveEfforts.map((effort) => [
|
|
789
|
-
effort,
|
|
790
|
-
{
|
|
791
|
-
reasoningConfig: {
|
|
792
|
-
type: "adaptive",
|
|
793
|
-
maxReasoningEffort: effort,
|
|
794
|
-
...(["opus-4-7", "opus-4.7", "opus-4-8", "opus-4.8"].some((v) => model.api.id.includes(v))
|
|
795
|
-
? { display: "summarized" }
|
|
796
|
-
: {}),
|
|
797
|
-
},
|
|
798
|
-
},
|
|
799
|
-
]),
|
|
800
|
-
)
|
|
801
|
-
}
|
|
802
|
-
// For Anthropic models on Bedrock, use reasoningConfig with budgetTokens
|
|
803
|
-
if (model.api.id.includes("anthropic")) {
|
|
804
|
-
return {
|
|
805
|
-
high: {
|
|
806
|
-
reasoningConfig: {
|
|
807
|
-
type: "enabled",
|
|
808
|
-
budgetTokens: 16000,
|
|
809
|
-
},
|
|
810
|
-
},
|
|
811
|
-
max: {
|
|
812
|
-
reasoningConfig: {
|
|
813
|
-
type: "enabled",
|
|
814
|
-
budgetTokens: 31999,
|
|
815
|
-
},
|
|
816
|
-
},
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
// For Amazon Nova models, use reasoningConfig with maxReasoningEffort
|
|
821
|
-
return Object.fromEntries(
|
|
822
|
-
WIDELY_SUPPORTED_EFFORTS.map((effort) => [
|
|
823
|
-
effort,
|
|
824
|
-
{
|
|
825
|
-
reasoningConfig: {
|
|
826
|
-
type: "enabled",
|
|
827
|
-
maxReasoningEffort: effort,
|
|
828
|
-
},
|
|
829
|
-
},
|
|
830
|
-
]),
|
|
831
|
-
)
|
|
832
|
-
|
|
833
|
-
case "@ai-sdk/google-vertex":
|
|
834
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex
|
|
835
|
-
case "@ai-sdk/google":
|
|
836
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai
|
|
837
|
-
if (id.includes("2.5")) {
|
|
838
|
-
return {
|
|
839
|
-
high: {
|
|
840
|
-
thinkingConfig: {
|
|
841
|
-
includeThoughts: true,
|
|
842
|
-
thinkingBudget: 16000,
|
|
843
|
-
},
|
|
844
|
-
},
|
|
845
|
-
max: {
|
|
846
|
-
thinkingConfig: {
|
|
847
|
-
includeThoughts: true,
|
|
848
|
-
thinkingBudget: 24576,
|
|
849
|
-
},
|
|
850
|
-
},
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
let levels = ["low", "high"]
|
|
854
|
-
if (id.includes("3.1")) {
|
|
855
|
-
levels = ["low", "medium", "high"]
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
return Object.fromEntries(
|
|
859
|
-
levels.map((effort) => [
|
|
860
|
-
effort,
|
|
861
|
-
{
|
|
862
|
-
thinkingConfig: {
|
|
863
|
-
includeThoughts: true,
|
|
864
|
-
thinkingLevel: effort,
|
|
865
|
-
},
|
|
866
|
-
},
|
|
867
|
-
]),
|
|
868
|
-
)
|
|
869
|
-
|
|
870
|
-
case "@ai-sdk/mistral":
|
|
871
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/mistral
|
|
872
|
-
return {}
|
|
873
|
-
|
|
874
|
-
case "@ai-sdk/cohere":
|
|
875
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/cohere
|
|
876
|
-
return {}
|
|
877
|
-
|
|
878
|
-
case "@ai-sdk/groq":
|
|
879
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/groq
|
|
880
|
-
const groqEffort = ["none", ...WIDELY_SUPPORTED_EFFORTS]
|
|
881
|
-
return Object.fromEntries(
|
|
882
|
-
groqEffort.map((effort) => [
|
|
883
|
-
effort,
|
|
884
|
-
{
|
|
885
|
-
reasoningEffort: effort,
|
|
886
|
-
},
|
|
887
|
-
]),
|
|
888
|
-
)
|
|
889
|
-
|
|
890
|
-
case "@ai-sdk/perplexity":
|
|
891
|
-
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/perplexity
|
|
892
|
-
return {}
|
|
893
|
-
|
|
894
|
-
case "@jerome-benoit/sap-ai-provider-v2":
|
|
895
|
-
if (model.api.id.includes("anthropic")) {
|
|
896
|
-
if (adaptiveEfforts) {
|
|
897
|
-
return Object.fromEntries(
|
|
898
|
-
adaptiveEfforts.map((effort) => [
|
|
899
|
-
effort,
|
|
900
|
-
{
|
|
901
|
-
thinking: {
|
|
902
|
-
type: "adaptive",
|
|
903
|
-
},
|
|
904
|
-
effort,
|
|
905
|
-
},
|
|
906
|
-
]),
|
|
907
|
-
)
|
|
908
|
-
}
|
|
909
|
-
return {
|
|
910
|
-
high: {
|
|
911
|
-
thinking: {
|
|
912
|
-
type: "enabled",
|
|
913
|
-
budgetTokens: 16000,
|
|
914
|
-
},
|
|
915
|
-
},
|
|
916
|
-
max: {
|
|
917
|
-
thinking: {
|
|
918
|
-
type: "enabled",
|
|
919
|
-
budgetTokens: 31999,
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
if (model.api.id.includes("gemini") && id.includes("2.5")) {
|
|
925
|
-
return {
|
|
926
|
-
high: {
|
|
927
|
-
thinkingConfig: {
|
|
928
|
-
includeThoughts: true,
|
|
929
|
-
thinkingBudget: 16000,
|
|
930
|
-
},
|
|
931
|
-
},
|
|
932
|
-
max: {
|
|
933
|
-
thinkingConfig: {
|
|
934
|
-
includeThoughts: true,
|
|
935
|
-
thinkingBudget: 24576,
|
|
936
|
-
},
|
|
937
|
-
},
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
if (model.api.id.includes("gpt") || /\bo[1-9]/.test(model.api.id)) {
|
|
941
|
-
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
|
942
|
-
}
|
|
943
|
-
return {}
|
|
944
|
-
}
|
|
945
|
-
return {}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
export function options(input: {
|
|
949
|
-
model: Provider.Model
|
|
950
|
-
sessionID: string
|
|
951
|
-
providerOptions?: Record<string, any>
|
|
952
|
-
}): Record<string, any> {
|
|
953
|
-
const result: Record<string, any> = {}
|
|
954
|
-
|
|
955
|
-
// openai and providers using openai package should set store to false by default.
|
|
956
|
-
if (
|
|
957
|
-
input.model.providerID === "openai" ||
|
|
958
|
-
input.model.api.npm === "@ai-sdk/openai" ||
|
|
959
|
-
input.model.api.npm === "@ai-sdk/github-copilot"
|
|
960
|
-
) {
|
|
961
|
-
result["store"] = false
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
if (input.model.api.npm === "@ai-sdk/azure") {
|
|
965
|
-
result["store"] = true
|
|
966
|
-
result["promptCacheKey"] = input.sessionID
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
if (input.model.api.npm === "@openrouter/ai-sdk-provider" || input.model.api.npm === "@llmgateway/ai-sdk-provider") {
|
|
970
|
-
result["usage"] = {
|
|
971
|
-
include: true,
|
|
972
|
-
}
|
|
973
|
-
if (input.model.api.id.includes("gemini-3")) {
|
|
974
|
-
result["reasoning"] = { effort: "high" }
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
if (
|
|
979
|
-
input.model.providerID === "baseten" ||
|
|
980
|
-
(input.model.providerID === "opencode" && ["kimi-k2-thinking", "glm-4.6"].includes(input.model.api.id))
|
|
981
|
-
) {
|
|
982
|
-
result["chat_template_args"] = { enable_thinking: true }
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
if (
|
|
986
|
-
["zai", "zhipuai"].some((id) => input.model.providerID.includes(id)) &&
|
|
987
|
-
input.model.api.npm === "@ai-sdk/openai-compatible"
|
|
988
|
-
) {
|
|
989
|
-
result["thinking"] = {
|
|
990
|
-
type: "enabled",
|
|
991
|
-
clear_thinking: false,
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
if (input.model.providerID === "openai" || input.providerOptions?.setCacheKey) {
|
|
996
|
-
result["promptCacheKey"] = input.sessionID
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
if (input.model.api.npm === "@ai-sdk/google" || input.model.api.npm === "@ai-sdk/google-vertex") {
|
|
1000
|
-
if (input.model.capabilities.reasoning) {
|
|
1001
|
-
result["thinkingConfig"] = {
|
|
1002
|
-
includeThoughts: true,
|
|
1003
|
-
}
|
|
1004
|
-
if (input.model.api.id.includes("gemini-3")) {
|
|
1005
|
-
result["thinkingConfig"]["thinkingLevel"] = "high"
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Enable thinking by default for kimi-k2.5/k2p5 models using anthropic SDK
|
|
1011
|
-
const modelId = input.model.api.id.toLowerCase()
|
|
1012
|
-
if (
|
|
1013
|
-
(input.model.api.npm === "@ai-sdk/anthropic" || input.model.api.npm === "@ai-sdk/google-vertex/anthropic") &&
|
|
1014
|
-
(modelId.includes("k2p5") || modelId.includes("kimi-k2.5") || modelId.includes("kimi-k2p5"))
|
|
1015
|
-
) {
|
|
1016
|
-
result["thinking"] = {
|
|
1017
|
-
type: "enabled",
|
|
1018
|
-
budgetTokens: Math.min(16_000, Math.floor(input.model.limit.output / 2 - 1)),
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
// Enable thinking for reasoning models on alibaba-cn (DashScope).
|
|
1023
|
-
// DashScope's OpenAI-compatible API requires `enable_thinking: true` in the request body
|
|
1024
|
-
// to return reasoning_content. Without it, models like kimi-k2.5, qwen-plus, qwen3, qwq,
|
|
1025
|
-
// deepseek-r1, etc. never output thinking/reasoning tokens.
|
|
1026
|
-
// Note: kimi-k2-thinking is excluded as it returns reasoning_content by default.
|
|
1027
|
-
if (
|
|
1028
|
-
input.model.providerID === "alibaba-cn" &&
|
|
1029
|
-
input.model.capabilities.reasoning &&
|
|
1030
|
-
input.model.api.npm === "@ai-sdk/openai-compatible" &&
|
|
1031
|
-
!modelId.includes("kimi-k2-thinking")
|
|
1032
|
-
) {
|
|
1033
|
-
result["enable_thinking"] = true
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
if (input.model.api.id.includes("gpt-5") && !input.model.api.id.includes("gpt-5-chat")) {
|
|
1037
|
-
if (!input.model.api.id.includes("gpt-5-pro")) {
|
|
1038
|
-
result["reasoningEffort"] = "medium"
|
|
1039
|
-
// Only inject reasoningSummary for providers that support it natively.
|
|
1040
|
-
// @ai-sdk/openai-compatible proxies (e.g. LiteLLM) do not understand this
|
|
1041
|
-
// parameter and return "Unknown parameter: 'reasoningSummary'".
|
|
1042
|
-
if (
|
|
1043
|
-
input.model.api.npm === "@ai-sdk/openai" ||
|
|
1044
|
-
input.model.api.npm === "@ai-sdk/azure" ||
|
|
1045
|
-
input.model.api.npm === "@ai-sdk/github-copilot"
|
|
1046
|
-
) {
|
|
1047
|
-
result["reasoningSummary"] = "auto"
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
// Only set textVerbosity for non-chat gpt-5.x models
|
|
1052
|
-
// Chat models (e.g. gpt-5.2-chat-latest) only support "medium" verbosity
|
|
1053
|
-
if (
|
|
1054
|
-
input.model.api.id.includes("gpt-5.") &&
|
|
1055
|
-
!input.model.api.id.includes("codex") &&
|
|
1056
|
-
!input.model.api.id.includes("-chat") &&
|
|
1057
|
-
input.model.providerID !== "azure"
|
|
1058
|
-
) {
|
|
1059
|
-
result["textVerbosity"] = "low"
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
if (input.model.providerID.startsWith("opencode")) {
|
|
1063
|
-
result["promptCacheKey"] = input.sessionID
|
|
1064
|
-
result["include"] = ["reasoning.encrypted_content"]
|
|
1065
|
-
result["reasoningSummary"] = "auto"
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
if (input.model.providerID === "venice") {
|
|
1070
|
-
result["promptCacheKey"] = input.sessionID
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
if (input.model.providerID === "openrouter") {
|
|
1074
|
-
result["prompt_cache_key"] = input.sessionID
|
|
1075
|
-
}
|
|
1076
|
-
if (input.model.api.npm === "@ai-sdk/gateway") {
|
|
1077
|
-
result["gateway"] = {
|
|
1078
|
-
caching: "auto",
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
return result
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
export function smallOptions(model: Provider.Model) {
|
|
1086
|
-
if (
|
|
1087
|
-
model.providerID === "openai" ||
|
|
1088
|
-
model.api.npm === "@ai-sdk/openai" ||
|
|
1089
|
-
model.api.npm === "@ai-sdk/github-copilot"
|
|
1090
|
-
) {
|
|
1091
|
-
if (model.api.id.includes("gpt-5")) {
|
|
1092
|
-
if (model.api.id.includes("5.") || model.api.id.includes("5-mini")) {
|
|
1093
|
-
return { store: false, reasoningEffort: "low" }
|
|
1094
|
-
}
|
|
1095
|
-
return { store: false, reasoningEffort: "minimal" }
|
|
1096
|
-
}
|
|
1097
|
-
return { store: false }
|
|
1098
|
-
}
|
|
1099
|
-
if (model.providerID === "google") {
|
|
1100
|
-
// gemini-3 uses thinkingLevel, gemini-2.5 uses thinkingBudget
|
|
1101
|
-
if (model.api.id.includes("gemini-3")) {
|
|
1102
|
-
return { thinkingConfig: { thinkingLevel: "minimal" } }
|
|
1103
|
-
}
|
|
1104
|
-
return { thinkingConfig: { thinkingBudget: 0 } }
|
|
1105
|
-
}
|
|
1106
|
-
if (model.providerID === "openrouter" || model.providerID === "llmgateway") {
|
|
1107
|
-
if (model.api.id.includes("google")) {
|
|
1108
|
-
return { reasoning: { enabled: false } }
|
|
1109
|
-
}
|
|
1110
|
-
return { reasoningEffort: "minimal" }
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
if (model.providerID === "venice") {
|
|
1114
|
-
return { veniceParameters: { disableThinking: true } }
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
return {}
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
// Maps model ID prefix to provider slug used in providerOptions.
|
|
1121
|
-
// Example: "amazon/nova-2-lite" → "bedrock"
|
|
1122
|
-
const SLUG_OVERRIDES: Record<string, string> = {
|
|
1123
|
-
amazon: "bedrock",
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
export function providerOptions(model: Provider.Model, options: { [x: string]: any }) {
|
|
1127
|
-
if (model.api.npm === "@ai-sdk/gateway") {
|
|
1128
|
-
// Gateway providerOptions are split across two namespaces:
|
|
1129
|
-
// - `gateway`: gateway-native routing/caching controls (order, only, byok, etc.)
|
|
1130
|
-
// - `<upstream slug>`: provider-specific model options (anthropic/openai/...)
|
|
1131
|
-
// We keep `gateway` as-is and route every other top-level option under the
|
|
1132
|
-
// model-derived upstream slug.
|
|
1133
|
-
const i = model.api.id.indexOf("/")
|
|
1134
|
-
const rawSlug = i > 0 ? model.api.id.slice(0, i) : undefined
|
|
1135
|
-
const slug = rawSlug ? (SLUG_OVERRIDES[rawSlug] ?? rawSlug) : undefined
|
|
1136
|
-
const gateway = options.gateway
|
|
1137
|
-
const rest = Object.fromEntries(Object.entries(options).filter(([k]) => k !== "gateway"))
|
|
1138
|
-
const has = Object.keys(rest).length > 0
|
|
1139
|
-
|
|
1140
|
-
const result: Record<string, any> = {}
|
|
1141
|
-
if (gateway !== undefined) result.gateway = gateway
|
|
1142
|
-
|
|
1143
|
-
if (has) {
|
|
1144
|
-
if (slug) {
|
|
1145
|
-
// Route model-specific options under the provider slug
|
|
1146
|
-
result[slug] = rest
|
|
1147
|
-
} else if (gateway && typeof gateway === "object" && !Array.isArray(gateway)) {
|
|
1148
|
-
result.gateway = { ...gateway, ...rest }
|
|
1149
|
-
} else {
|
|
1150
|
-
result.gateway = rest
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
return result
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
const key = sdkKey(model.api.npm) ?? model.providerID
|
|
1158
|
-
// @ai-sdk/azure delegates to OpenAIChatLanguageModel which reads from
|
|
1159
|
-
// providerOptions["openai"], but OpenAIResponsesLanguageModel checks
|
|
1160
|
-
// "azure" first. Pass both so model options work on either code path.
|
|
1161
|
-
if (model.api.npm === "@ai-sdk/azure") {
|
|
1162
|
-
return { openai: options, azure: options }
|
|
1163
|
-
}
|
|
1164
|
-
return { [key]: options }
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
export function maxOutputTokens(model: Provider.Model): number {
|
|
1168
|
-
if (model.providerID === "sleepy" || model.providerID === "sleepy" || model.providerID === "sleepy" || model.id.toLowerCase().includes("sleepy")) {
|
|
1169
|
-
return SLEEPY_OUTPUT_TOKEN_MAX
|
|
1170
|
-
}
|
|
1171
|
-
return Math.min(model.limit.output, OUTPUT_TOKEN_MAX) || OUTPUT_TOKEN_MAX
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// Flatten a root-level `anyOf` / `oneOf` (typically from `z.discriminatedUnion`)
|
|
1175
|
-
// into a single `type: "object"` schema with all variant properties merged at
|
|
1176
|
-
// the root. The discriminator key becomes an `enum`, and per-variant required
|
|
1177
|
-
// fields are encoded as a textual hint on the discriminator's description.
|
|
1178
|
-
//
|
|
1179
|
-
// OpenAI's function-calling validator rejects oneOf/anyOf/allOf/enum/not at the
|
|
1180
|
-
// top level outright, so this is the only shape that gets through. We retain
|
|
1181
|
-
// `additionalProperties: false` to keep the model from inventing fields, and
|
|
1182
|
-
// rely on zod's runtime parse (still using the original discriminated union)
|
|
1183
|
-
// to enforce per-action required fields strictly.
|
|
1184
|
-
function flattenDiscriminatedUnion(schema: JSONSchema.BaseSchema | JSONSchema7): JSONSchema7 {
|
|
1185
|
-
const root = schema as Record<string, any>
|
|
1186
|
-
const variants = (root.anyOf ?? root.oneOf) as Array<Record<string, any>> | undefined
|
|
1187
|
-
if (!variants?.length) return schema as JSONSchema7
|
|
1188
|
-
|
|
1189
|
-
// Find the discriminator: a property whose `const` differs across all variants.
|
|
1190
|
-
const constByKey = new Map<string, Set<unknown>>()
|
|
1191
|
-
for (const v of variants) {
|
|
1192
|
-
if (!v.properties) continue
|
|
1193
|
-
for (const [key, prop] of Object.entries(v.properties as Record<string, any>)) {
|
|
1194
|
-
if (prop && typeof prop === "object" && "const" in prop) {
|
|
1195
|
-
if (!constByKey.has(key)) constByKey.set(key, new Set())
|
|
1196
|
-
constByKey.get(key)!.add(prop.const)
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
let discriminator: string | undefined
|
|
1201
|
-
for (const [key, values] of constByKey) {
|
|
1202
|
-
if (values.size === variants.length) {
|
|
1203
|
-
discriminator = key
|
|
1204
|
-
break
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
// Merge non-discriminator properties from every variant. Track which variants
|
|
1209
|
-
// each property appeared in so the description can tell the model
|
|
1210
|
-
// "(only when action='X'|'Y')" — flat schemas tempt some models (notably
|
|
1211
|
-
// gpt-5.5) to fill every property regardless of which action they chose.
|
|
1212
|
-
const properties: Record<string, any> = {}
|
|
1213
|
-
const propertyOwners: Record<string, unknown[]> = {}
|
|
1214
|
-
for (const v of variants) {
|
|
1215
|
-
if (!v.properties) continue
|
|
1216
|
-
const variantValue = discriminator
|
|
1217
|
-
? (v.properties as Record<string, any>)[discriminator]?.const
|
|
1218
|
-
: undefined
|
|
1219
|
-
for (const [key, prop] of Object.entries(v.properties as Record<string, any>)) {
|
|
1220
|
-
if (key === discriminator) continue
|
|
1221
|
-
if (!(key in properties)) properties[key] = prop
|
|
1222
|
-
if (variantValue !== undefined) {
|
|
1223
|
-
if (!propertyOwners[key]) propertyOwners[key] = []
|
|
1224
|
-
propertyOwners[key].push(variantValue)
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
if (discriminator) {
|
|
1229
|
-
for (const [key, owners] of Object.entries(propertyOwners)) {
|
|
1230
|
-
if (owners.length === variants.length) continue // present in every variant — no annotation
|
|
1231
|
-
const tag = `(only when ${discriminator}=${owners.map((o) => JSON.stringify(o)).join("|")})`
|
|
1232
|
-
const original = (properties[key] as Record<string, any>).description as string | undefined
|
|
1233
|
-
properties[key] = {
|
|
1234
|
-
...properties[key],
|
|
1235
|
-
description: original ? `${tag} ${original}` : tag,
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
// Discriminator becomes an enum with per-variant required fields hinted in
|
|
1241
|
-
// its description. Without this hint the model only sees a flat bag of
|
|
1242
|
-
// optional fields and forgets what to provide for each action.
|
|
1243
|
-
if (discriminator) {
|
|
1244
|
-
const proto = (variants[0].properties as Record<string, any>)[discriminator]
|
|
1245
|
-
const enumValues = variants.map((v) => (v.properties as Record<string, any>)[discriminator!]?.const)
|
|
1246
|
-
const baseDescription = (proto?.description as string | undefined) ?? ""
|
|
1247
|
-
const hints = variants
|
|
1248
|
-
.map((v) => {
|
|
1249
|
-
const value = (v.properties as Record<string, any>)[discriminator!]?.const
|
|
1250
|
-
const required = ((v.required as string[] | undefined) ?? []).filter((r) => r !== discriminator)
|
|
1251
|
-
return required.length > 0 ? `${value}: requires ${required.join(", ")}` : `${value}: no extra required fields`
|
|
1252
|
-
})
|
|
1253
|
-
.join("; ")
|
|
1254
|
-
properties[discriminator] = {
|
|
1255
|
-
type: "string",
|
|
1256
|
-
enum: enumValues,
|
|
1257
|
-
description: baseDescription ? `${baseDescription}\n\nPer-${discriminator}: ${hints}.` : `Per-${discriminator}: ${hints}.`,
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
return {
|
|
1262
|
-
type: "object",
|
|
1263
|
-
properties,
|
|
1264
|
-
required: discriminator ? [discriminator] : [],
|
|
1265
|
-
additionalProperties: false,
|
|
1266
|
-
} as JSONSchema7
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
export function schema(model: Provider.Model, schema: JSONSchema.BaseSchema | JSONSchema7): JSONSchema7 {
|
|
1270
|
-
/*
|
|
1271
|
-
if (["openai", "azure"].includes(providerID)) {
|
|
1272
|
-
if (schema.type === "object" && schema.properties) {
|
|
1273
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
1274
|
-
if (schema.required?.includes(key)) continue
|
|
1275
|
-
schema.properties[key] = {
|
|
1276
|
-
anyOf: [
|
|
1277
|
-
value as JSONSchema.JSONSchema,
|
|
1278
|
-
{
|
|
1279
|
-
type: "null",
|
|
1280
|
-
},
|
|
1281
|
-
],
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
*/
|
|
1287
|
-
|
|
1288
|
-
// Many providers reject root-level `anyOf`/`oneOf` in tool schemas:
|
|
1289
|
-
// - OpenAI/Azure: "schema must have type 'object' and not have 'oneOf'/'anyOf'"
|
|
1290
|
-
// - Bedrock: "input_schema.type: Field required"
|
|
1291
|
-
// - Anthropic proxies to Bedrock: same Bedrock error
|
|
1292
|
-
// Flatten unconditionally — all providers accept a flat `type: "object"` schema,
|
|
1293
|
-
// and zod's runtime parse still enforces per-variant required fields strictly.
|
|
1294
|
-
schema = flattenDiscriminatedUnion(schema)
|
|
1295
|
-
|
|
1296
|
-
// Convert integer enums to string enums for Google/Gemini
|
|
1297
|
-
if (model.providerID === "google" || model.api.id.includes("gemini")) {
|
|
1298
|
-
const isPlainObject = (node: unknown): node is Record<string, any> =>
|
|
1299
|
-
typeof node === "object" && node !== null && !Array.isArray(node)
|
|
1300
|
-
const hasCombiner = (node: unknown) =>
|
|
1301
|
-
isPlainObject(node) && (Array.isArray(node.anyOf) || Array.isArray(node.oneOf) || Array.isArray(node.allOf))
|
|
1302
|
-
const hasSchemaIntent = (node: unknown) => {
|
|
1303
|
-
if (!isPlainObject(node)) return false
|
|
1304
|
-
if (hasCombiner(node)) return true
|
|
1305
|
-
return [
|
|
1306
|
-
"type",
|
|
1307
|
-
"properties",
|
|
1308
|
-
"items",
|
|
1309
|
-
"prefixItems",
|
|
1310
|
-
"enum",
|
|
1311
|
-
"const",
|
|
1312
|
-
"$ref",
|
|
1313
|
-
"additionalProperties",
|
|
1314
|
-
"patternProperties",
|
|
1315
|
-
"required",
|
|
1316
|
-
"not",
|
|
1317
|
-
"if",
|
|
1318
|
-
"then",
|
|
1319
|
-
"else",
|
|
1320
|
-
].some((key) => key in node)
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
const sanitizeGemini = (obj: any): any => {
|
|
1324
|
-
if (obj === null || typeof obj !== "object") {
|
|
1325
|
-
return obj
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
if (Array.isArray(obj)) {
|
|
1329
|
-
return obj.map(sanitizeGemini)
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
const result: any = {}
|
|
1333
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1334
|
-
if (key === "enum" && Array.isArray(value)) {
|
|
1335
|
-
// Convert all enum values to strings
|
|
1336
|
-
result[key] = value.map((v) => String(v))
|
|
1337
|
-
// If we have integer type with enum, change type to string
|
|
1338
|
-
if (result.type === "integer" || result.type === "number") {
|
|
1339
|
-
result.type = "string"
|
|
1340
|
-
}
|
|
1341
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1342
|
-
result[key] = sanitizeGemini(value)
|
|
1343
|
-
} else {
|
|
1344
|
-
result[key] = value
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
// Filter required array to only include fields that exist in properties
|
|
1349
|
-
if (result.type === "object" && result.properties && Array.isArray(result.required)) {
|
|
1350
|
-
result.required = result.required.filter((field: any) => field in result.properties)
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
if (result.type === "array" && !hasCombiner(result)) {
|
|
1354
|
-
if (result.items == null) {
|
|
1355
|
-
result.items = {}
|
|
1356
|
-
}
|
|
1357
|
-
// Ensure items has a type only when it's still schema-empty.
|
|
1358
|
-
if (isPlainObject(result.items) && !hasSchemaIntent(result.items)) {
|
|
1359
|
-
result.items.type = "string"
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
// Remove properties/required from non-object types (Gemini rejects these)
|
|
1364
|
-
if (result.type && result.type !== "object" && !hasCombiner(result)) {
|
|
1365
|
-
delete result.properties
|
|
1366
|
-
delete result.required
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
return result
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
schema = sanitizeGemini(schema)
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
return schema as JSONSchema7
|
|
1376
|
-
}
|