@circuitwall/jarela 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +5 -5
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +14 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/access/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +27 -33
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +9 -2
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js +19 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/events/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/health/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +27 -12
- package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/profile/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +585 -58
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/state/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +12 -6
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +125 -26
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +1 -2
- package/.next/standalone/.next/server/app/api/v1/threads/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/tools/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/watchers/route.js +1 -1
- package/.next/standalone/.next/server/app/page.js +27323 -27034
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup/page.js +8 -0
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +5 -5
- package/.next/standalone/.next/server/chunks/1388.js +106 -36
- package/.next/standalone/.next/server/chunks/2068.js +47 -10
- package/.next/standalone/.next/server/chunks/210.js +6 -6
- package/.next/standalone/.next/server/chunks/2447.js +10 -5
- package/.next/standalone/.next/server/chunks/2653.js +80 -1
- package/.next/standalone/.next/server/chunks/3042.js +10 -8
- package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
- package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
- package/.next/standalone/.next/server/chunks/3524.js +150 -67
- package/.next/standalone/.next/server/chunks/3566.js +1 -1
- package/.next/standalone/.next/server/chunks/4189.js +1 -1
- package/.next/standalone/.next/server/chunks/4596.js +28 -4
- package/.next/standalone/.next/server/chunks/46.js +91 -31
- package/.next/standalone/.next/server/chunks/466.js +53 -7
- package/.next/standalone/.next/server/chunks/4955.js +30 -3
- package/.next/standalone/.next/server/chunks/5585.js +28 -4
- package/.next/standalone/.next/server/chunks/5908.js +63 -42
- package/.next/standalone/.next/server/chunks/6142.js +10 -2
- package/.next/standalone/.next/server/chunks/8461.js +10 -8
- package/.next/standalone/.next/server/chunks/9032.js +5 -5
- package/.next/standalone/.next/server/chunks/9164.js +487 -177
- package/.next/standalone/.next/server/chunks/9304.js +51 -12
- package/.next/standalone/.next/server/chunks/{423.js → 9590.js} +84 -24
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/middleware.js +89 -21
- package/.next/standalone/.next/server/pages/404.html +14 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{1395-e4a99912b8f83044.js → 1395-bfe1f3ef760c0f50.js} +54 -8
- package/.next/standalone/.next/static/chunks/app/{layout-9bc0b10127cb7d42.js → layout-7b24ad13faa3944b.js} +69 -2
- package/.next/standalone/.next/static/chunks/app/{page-213a623b37226452.js → page-2ef8d75d40eb4311.js} +10643 -10295
- package/.next/standalone/.next/static/css/c160ea862133acd2.css +5 -0
- package/.next/standalone/docs/adoption/changesets.json +2805 -0
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +52 -0
- package/api/client.models.test.ts +10 -0
- package/api/client.startup.test.ts +129 -0
- package/api/client.ts +51 -9
- package/api/thread-metadata.test.ts +72 -0
- package/api/types.ts +6 -3
- package/app/api/v1/providers/[provider]/models/route.test.ts +216 -6
- package/app/api/v1/providers/[provider]/models/route.ts +259 -40
- package/app/api/v1/threads/[thread_id]/route.ts +26 -23
- package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
- package/app/globals.css +119 -29
- package/app/layout.tsx +12 -0
- package/components/agents/AgentsPanel.tsx +5 -13
- package/components/chat/ChatView.tsx +9 -18
- package/components/chat/InputBar.tsx +1 -1
- package/components/chat/MessageBubble.tsx +13 -1
- package/components/chat/MessageList.test.tsx +45 -4
- package/components/chat/MessageList.tsx +123 -89
- package/components/chat/ToolList.tsx +88 -84
- package/components/chat/useThreadActivity.test.tsx +2 -2
- package/components/chat/useThreadActivity.ts +2 -2
- package/components/chat/useThreadData.ts +1 -30
- package/components/chat/useThreadMetadataPolling.test.tsx +128 -0
- package/components/chat/useThreadMetadataPolling.ts +50 -0
- package/components/chat/useUserProfileAndAgent.test.tsx +31 -0
- package/components/chat/useUserProfileAndAgent.ts +13 -2
- package/components/dashboard/DashboardPanel.tsx +1 -1
- package/components/dashboard/Series.tsx +34 -21
- package/components/dashboard/SummaryCards.tsx +1 -1
- package/components/integrations/NetworkSection.tsx +2 -2
- package/components/layout/AppShell.tsx +22 -7
- package/components/layout/MenuPanel.tsx +14 -24
- package/components/profile/ProfilePanel.tsx +2 -2
- package/components/settings/AppearancePanel.tsx +70 -3
- package/components/settings/SettingsPanel.tsx +2 -2
- package/components/tools/ToolsPanel.tsx +2 -7
- package/components/ui/AppearancePreferences.test.tsx +68 -0
- package/components/ui/BootScreen.test.tsx +44 -0
- package/components/ui/BootScreen.tsx +24 -11
- package/components/ui/NotificationStatus.test.tsx +2 -2
- package/components/ui/NotificationStatus.tsx +5 -5
- package/components/ui/SubTabBar.tsx +2 -3
- package/contexts/ThemeContext.tsx +84 -1
- package/hooks/useAgentSession.test.ts +12 -1
- package/hooks/useAgentSession.ts +6 -4
- package/hooks/useUrlSync.test.ts +13 -0
- package/hooks/useUrlSync.ts +0 -4
- package/lib/agents/citation-checker.test.ts +40 -2
- package/lib/agents/citation-checker.ts +56 -11
- package/lib/agents/context-boundary.ts +5 -6
- package/lib/agents/instruction-edits.test.ts +120 -0
- package/lib/agents/instruction-edits.ts +65 -42
- package/lib/agents/prepare/request.ts +0 -2
- package/lib/agents/prepare/system-prompt.test.ts +10 -0
- package/lib/agents/prepare/system-prompt.ts +8 -2
- package/lib/agents/proposals.test.ts +76 -0
- package/lib/agents/proposals.ts +13 -5
- package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
- package/lib/agents/run-thread.ts +24 -9
- package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
- package/lib/agents/warm-summary-background.ts +22 -2
- package/lib/agents/warm-topics.test.ts +155 -1
- package/lib/agents/warm-topics.ts +27 -7
- package/lib/bridges/dispatcher.ts +1 -0
- package/lib/bridges/message-role.test.ts +81 -0
- package/lib/bridges/message-role.ts +23 -10
- package/lib/bridges/types.ts +6 -0
- package/lib/bridges/whatsapp-link.test.ts +32 -0
- package/lib/bridges/whatsapp-link.ts +21 -0
- package/lib/bridges/whatsapp.inbound.test.ts +239 -0
- package/lib/bridges/whatsapp.sender.test.ts +80 -1
- package/lib/bridges/whatsapp.ts +76 -38
- package/lib/db/migrations.test.ts +61 -0
- package/lib/db/migrations.ts +13 -0
- package/lib/embeddings/performance.test.ts +114 -0
- package/lib/pricing/snapshot.test.ts +70 -0
- package/lib/pricing/snapshot.ts +10 -2
- package/lib/proxy/dispatcher.test.ts +119 -1
- package/lib/proxy/dispatcher.ts +22 -9
- package/lib/stores/agent-configs.ts +10 -5
- package/lib/stores/bridges.test.ts +81 -0
- package/lib/stores/bridges.ts +9 -8
- package/lib/stores/dashboard-metrics-cache.test.ts +99 -0
- package/lib/stores/dashboard-metrics.ts +30 -4
- package/lib/stores/message-embedding-jobs.test.ts +27 -0
- package/lib/stores/message-embedding-jobs.ts +5 -3
- package/lib/stores/message-usage.test.ts +21 -1
- package/lib/stores/pricing-cache.test.ts +31 -0
- package/lib/stores/pricing.ts +3 -0
- package/lib/stores/proxy-config.test.ts +120 -0
- package/lib/stores/proxy-config.ts +22 -4
- package/lib/stores/threads.ts +12 -8
- package/lib/tools/communications/calendar.test.ts +43 -2
- package/lib/tools/communications/calendar.ts +2 -0
- package/lib/tools/communications/gmail.test.ts +51 -1
- package/lib/tools/communications/gmail.ts +44 -2
- package/lib/tools/communications/outlook-calendar.ts +2 -0
- package/lib/tools/communications/outlook.test.ts +33 -2
- package/lib/tools/communications/outlook.ts +2 -0
- package/lib/tools/filesystem/edit-match.test.ts +133 -0
- package/lib/tools/filesystem/edit-match.ts +7 -2
- package/lib/tools/packages/default-packages.test.ts +21 -0
- package/lib/tools/packages/optional-package.test.ts +72 -0
- package/lib/tools/packages/optional-package.ts +33 -4
- package/lib/tools/support/result-refs.test.ts +131 -0
- package/lib/tools/support/result-refs.ts +41 -9
- package/lib/ui/navigate.test.ts +13 -0
- package/lib/ui/navigate.ts +10 -2
- package/lib/utils/source-link.test.ts +51 -0
- package/lib/utils/source-link.ts +45 -0
- package/package.json +1 -1
- package/.next/standalone/.next/static/css/312542a5725ba0d5.css +0 -5
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_ssgManifest.js +0 -0
|
@@ -510,6 +510,266 @@ module.exports = require("node:async_hooks");
|
|
|
510
510
|
|
|
511
511
|
module.exports = require("next/dist/server/app-render/action-async-storage.external.js");
|
|
512
512
|
|
|
513
|
+
/***/ }),
|
|
514
|
+
|
|
515
|
+
/***/ 23619:
|
|
516
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
517
|
+
|
|
518
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
519
|
+
/* harmony export */ AT: () => (/* binding */ thinkingReductionParams),
|
|
520
|
+
/* harmony export */ _8: () => (/* binding */ modelCapabilities),
|
|
521
|
+
/* harmony export */ ne: () => (/* binding */ modelThinksByDefault)
|
|
522
|
+
/* harmony export */ });
|
|
523
|
+
/* unused harmony exports modelSupportsImages, isProviderClassified */
|
|
524
|
+
/**
|
|
525
|
+
* Static per-provider classification of which model ids accept image inputs.
|
|
526
|
+
*
|
|
527
|
+
* Used purely to surface UI hints — "this agent's model can read WhatsApp
|
|
528
|
+
* images" — so a user can pick a vision-capable model BEFORE pointing a
|
|
529
|
+
* bridge route at an agent. The runtime never enforces this: the bridge
|
|
530
|
+
* always forwards whatever payload it captured, and the provider returns
|
|
531
|
+
* whatever ignore/error behaviour the upstream model chose if it isn't
|
|
532
|
+
* actually multi-modal.
|
|
533
|
+
*
|
|
534
|
+
* Patterns intentionally err on the *generous* side. A false positive just
|
|
535
|
+
* means the user sees no warning for a model that quietly ignores images;
|
|
536
|
+
* a false negative would mean users see a scary warning on a model that
|
|
537
|
+
* actually works fine. We update the patterns as new model families ship.
|
|
538
|
+
*
|
|
539
|
+
* NOTE: this module is intentionally free of server-only imports so the
|
|
540
|
+
* BridgeEditor / AgentEditor UIs can import it directly.
|
|
541
|
+
*/ const PATTERNS = {
|
|
542
|
+
// OpenAI — every modern flagship is multi-modal; only the legacy
|
|
543
|
+
// gpt-3.5-* / text-davinci-* / o3-mini-text family stay text-only.
|
|
544
|
+
openai: [
|
|
545
|
+
/^gpt-4o/i,
|
|
546
|
+
/^gpt-4\.1/i,
|
|
547
|
+
/^gpt-4-turbo/i,
|
|
548
|
+
/^gpt-4-vision/i,
|
|
549
|
+
/^gpt-5/i,
|
|
550
|
+
/^chatgpt-4o/i,
|
|
551
|
+
/^o[134](?:-|$)/i
|
|
552
|
+
],
|
|
553
|
+
// Anthropic — Claude 3 onwards is vision-native across all tiers.
|
|
554
|
+
anthropic: [
|
|
555
|
+
/^claude-3/i,
|
|
556
|
+
/^claude-sonnet/i,
|
|
557
|
+
/^claude-opus/i,
|
|
558
|
+
/^claude-haiku-4/i,
|
|
559
|
+
/^claude-[45](?:-|$)/i
|
|
560
|
+
],
|
|
561
|
+
// Google — Gemini 1.5+ are multi-modal; legacy gemini-pro is text-only,
|
|
562
|
+
// but gemini-pro-vision was the explicit vision SKU before 1.5.
|
|
563
|
+
gemini: [
|
|
564
|
+
/^gemini-(1\.5|2|3)/i,
|
|
565
|
+
/^gemini-pro-vision/i
|
|
566
|
+
],
|
|
567
|
+
// GitHub Copilot — proxies vision-capable models from OpenAI / Anthropic /
|
|
568
|
+
// Google. Mirror those families (the actual capability is gated server-
|
|
569
|
+
// side by Copilot; we just don't warn).
|
|
570
|
+
"github-copilot": [
|
|
571
|
+
/^gpt-4o/i,
|
|
572
|
+
/^gpt-4\.1/i,
|
|
573
|
+
/^gpt-5/i,
|
|
574
|
+
/^o[134](?:-|$)/i,
|
|
575
|
+
/^claude-3/i,
|
|
576
|
+
/^claude-sonnet/i,
|
|
577
|
+
/^claude-opus/i,
|
|
578
|
+
/^claude-haiku-4/i,
|
|
579
|
+
/^claude-[45](?:-|$)/i,
|
|
580
|
+
/^gemini-(1\.5|2|3)/i
|
|
581
|
+
],
|
|
582
|
+
// DeepSeek V4.1 Flash is multimodal (`deepseek-v4-flash` is a legacy alias for it);
|
|
583
|
+
// V4 Pro and Cohere chat SKUs are text-only.
|
|
584
|
+
deepseek: [
|
|
585
|
+
/^deepseek-(?:v4-)?flash/i
|
|
586
|
+
],
|
|
587
|
+
cohere: [],
|
|
588
|
+
// LangChain pass-through could be anything; treat as unknown (handled
|
|
589
|
+
// separately below) rather than yes/no.
|
|
590
|
+
langchain: [],
|
|
591
|
+
// Tests assume the mock accepts images.
|
|
592
|
+
mock: [
|
|
593
|
+
/.*/
|
|
594
|
+
]
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* Returns true when the given (provider, model_id) pair is known to accept
|
|
598
|
+
* image inputs. Unknown providers / models return false — call
|
|
599
|
+
* `isProviderClassified` if you want to distinguish "definitely no" from
|
|
600
|
+
* "we don't recognize this".
|
|
601
|
+
*/ function modelSupportsImages(provider, modelId) {
|
|
602
|
+
const pats = PATTERNS[provider.toLowerCase()] ?? [];
|
|
603
|
+
return pats.some((re)=>re.test(modelId));
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* True when we have an explicit capability list for the provider. Used by
|
|
607
|
+
* the UI to soften the warning copy ("might not support images") for
|
|
608
|
+
* pass-through providers like `langchain` or unknown external ones.
|
|
609
|
+
*/ function isProviderClassified(provider) {
|
|
610
|
+
return provider.toLowerCase() in PATTERNS;
|
|
611
|
+
}
|
|
612
|
+
// ── extended capabilities for badge rendering ────────────────────────────────
|
|
613
|
+
// Mirrors CatalogModel["capabilities"] so saved ModelConfigs can render the
|
|
614
|
+
// same icon set the catalog browser uses. Heuristics err on the conservative
|
|
615
|
+
// side for audio (vanilla gpt-4o is NOT audio-capable — only *-audio-preview /
|
|
616
|
+
// *-realtime are) and generous side for files (PDF / document input).
|
|
617
|
+
const AUDIO_PATTERNS = {
|
|
618
|
+
openai: [
|
|
619
|
+
/audio/i,
|
|
620
|
+
/realtime/i
|
|
621
|
+
],
|
|
622
|
+
gemini: [
|
|
623
|
+
/^gemini-(1\.5|2|3)/i
|
|
624
|
+
],
|
|
625
|
+
anthropic: [],
|
|
626
|
+
"github-copilot": [
|
|
627
|
+
/audio/i,
|
|
628
|
+
/realtime/i,
|
|
629
|
+
/^gemini-(1\.5|2|3)/i
|
|
630
|
+
],
|
|
631
|
+
deepseek: [],
|
|
632
|
+
cohere: [],
|
|
633
|
+
langchain: [],
|
|
634
|
+
mock: [
|
|
635
|
+
/.*/
|
|
636
|
+
]
|
|
637
|
+
};
|
|
638
|
+
const FILES_PATTERNS = {
|
|
639
|
+
// PDF / document upload support.
|
|
640
|
+
openai: [
|
|
641
|
+
/^gpt-4o/i,
|
|
642
|
+
/^gpt-4\.1/i,
|
|
643
|
+
/^gpt-4-turbo/i,
|
|
644
|
+
/^gpt-5/i,
|
|
645
|
+
/^o[134](?:-|$)/i,
|
|
646
|
+
/^chatgpt-4o/i
|
|
647
|
+
],
|
|
648
|
+
anthropic: [
|
|
649
|
+
/^claude-3/i,
|
|
650
|
+
/^claude-sonnet/i,
|
|
651
|
+
/^claude-opus/i,
|
|
652
|
+
/^claude-haiku-4/i,
|
|
653
|
+
/^claude-[45](?:-|$)/i
|
|
654
|
+
],
|
|
655
|
+
gemini: [
|
|
656
|
+
/^gemini-(1\.5|2|3)/i
|
|
657
|
+
],
|
|
658
|
+
"github-copilot": [
|
|
659
|
+
/^gpt-4o/i,
|
|
660
|
+
/^gpt-4\.1/i,
|
|
661
|
+
/^gpt-5/i,
|
|
662
|
+
/^o[134](?:-|$)/i,
|
|
663
|
+
/^claude-3/i,
|
|
664
|
+
/^claude-sonnet/i,
|
|
665
|
+
/^claude-opus/i,
|
|
666
|
+
/^claude-haiku-4/i,
|
|
667
|
+
/^claude-[45](?:-|$)/i,
|
|
668
|
+
/^gemini-(1\.5|2|3)/i
|
|
669
|
+
],
|
|
670
|
+
deepseek: [],
|
|
671
|
+
cohere: [],
|
|
672
|
+
langchain: [],
|
|
673
|
+
mock: [
|
|
674
|
+
/.*/
|
|
675
|
+
]
|
|
676
|
+
};
|
|
677
|
+
const WEB_SEARCH_PATTERNS = {
|
|
678
|
+
// Built-in provider-side web tool.
|
|
679
|
+
anthropic: [
|
|
680
|
+
/^claude-3\.5/i,
|
|
681
|
+
/^claude-3\.7/i,
|
|
682
|
+
/^claude-sonnet/i,
|
|
683
|
+
/^claude-opus/i,
|
|
684
|
+
/^claude-haiku-4/i,
|
|
685
|
+
/^claude-[45](?:-|$)/i
|
|
686
|
+
],
|
|
687
|
+
openai: [],
|
|
688
|
+
gemini: [],
|
|
689
|
+
"github-copilot": [],
|
|
690
|
+
deepseek: [],
|
|
691
|
+
cohere: [],
|
|
692
|
+
langchain: [],
|
|
693
|
+
mock: []
|
|
694
|
+
};
|
|
695
|
+
const JSON_MODE_PROVIDERS = new Set([
|
|
696
|
+
"openai",
|
|
697
|
+
"gemini",
|
|
698
|
+
"deepseek",
|
|
699
|
+
"mock"
|
|
700
|
+
]);
|
|
701
|
+
// Models whose reasoning tokens are spent from the same max_tokens budget as the
|
|
702
|
+
// visible answer, so a tight output cap truncates them before they reply.
|
|
703
|
+
const THINKS_BY_DEFAULT = {
|
|
704
|
+
openai: [
|
|
705
|
+
/^gpt-5/i,
|
|
706
|
+
/^o[134](?:-|$)/i
|
|
707
|
+
],
|
|
708
|
+
gemini: [
|
|
709
|
+
/^gemini-(2\.5|3)/i
|
|
710
|
+
],
|
|
711
|
+
"github-copilot": [
|
|
712
|
+
/^gpt-5/i,
|
|
713
|
+
/^o[134](?:-|$)/i,
|
|
714
|
+
/^gemini-(2\.5|3)/i
|
|
715
|
+
],
|
|
716
|
+
deepseek: [
|
|
717
|
+
/^deepseek-(?:v4|flash|reasoner)/i
|
|
718
|
+
]
|
|
719
|
+
};
|
|
720
|
+
function modelThinksByDefault(provider, modelId) {
|
|
721
|
+
return (THINKS_BY_DEFAULT[provider.toLowerCase()] ?? []).some((re)=>re.test(modelId));
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Request params that turn a default-thinking model's reasoning down. `off` is
|
|
725
|
+
* true only when the provider can disable it outright; OpenAI reasoning models
|
|
726
|
+
* can only be lowered, so they still reason a little. Null when the model has
|
|
727
|
+
* no known control, so nothing is sent.
|
|
728
|
+
*/ function thinkingReductionParams(provider, modelId) {
|
|
729
|
+
const p = provider.toLowerCase();
|
|
730
|
+
if (p === "deepseek" && /^deepseek-(?:v4|flash)/i.test(modelId)) {
|
|
731
|
+
return {
|
|
732
|
+
params: {
|
|
733
|
+
thinking: {
|
|
734
|
+
type: "disabled"
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
off: true
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
// "low" is accepted by every OpenAI reasoning model; "minimal" is not on newer gpt-5 releases.
|
|
741
|
+
if (p === "openai" && /^(gpt-5|o[134](?:-|$))/i.test(modelId)) return {
|
|
742
|
+
params: {
|
|
743
|
+
reasoning_effort: "low"
|
|
744
|
+
},
|
|
745
|
+
off: false
|
|
746
|
+
};
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
function matchesAny(map, provider, modelId) {
|
|
750
|
+
const pats = map[provider.toLowerCase()] ?? [];
|
|
751
|
+
return pats.some((re)=>re.test(modelId));
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Best-effort capability inference for a saved (provider, model_id) pair —
|
|
755
|
+
* used to render capability badges in surfaces that don't have a live
|
|
756
|
+
* catalog fetch (ModelsPanel, AgentEditor dropdowns, etc.).
|
|
757
|
+
*/ function modelCapabilities(provider, modelId) {
|
|
758
|
+
const p = provider.toLowerCase();
|
|
759
|
+
// Reasoner-style models that don't expose tool calling.
|
|
760
|
+
const noTools = /^deepseek-reasoner/i.test(modelId);
|
|
761
|
+
return {
|
|
762
|
+
vision: modelSupportsImages(provider, modelId),
|
|
763
|
+
tools: isProviderClassified(p) && !noTools,
|
|
764
|
+
streaming: true,
|
|
765
|
+
json_mode: JSON_MODE_PROVIDERS.has(p),
|
|
766
|
+
web_search: matchesAny(WEB_SEARCH_PATTERNS, provider, modelId),
|
|
767
|
+
audio: matchesAny(AUDIO_PATTERNS, provider, modelId),
|
|
768
|
+
files: matchesAny(FILES_PATTERNS, provider, modelId)
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
|
|
513
773
|
/***/ }),
|
|
514
774
|
|
|
515
775
|
/***/ 27910:
|
|
@@ -566,6 +826,91 @@ module.exports = require("node:http");
|
|
|
566
826
|
|
|
567
827
|
module.exports = require("node:zlib");
|
|
568
828
|
|
|
829
|
+
/***/ }),
|
|
830
|
+
|
|
831
|
+
/***/ 39947:
|
|
832
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
833
|
+
|
|
834
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
835
|
+
/* harmony export */ Bm: () => (/* binding */ cachedJson),
|
|
836
|
+
/* harmony export */ HN: () => (/* binding */ notFoundResponse),
|
|
837
|
+
/* harmony export */ Jb: () => (/* binding */ validateBody),
|
|
838
|
+
/* harmony export */ K2: () => (/* binding */ createdResponse),
|
|
839
|
+
/* harmony export */ Ng: () => (/* binding */ noStoreJson),
|
|
840
|
+
/* harmony export */ yj: () => (/* binding */ errorResponse)
|
|
841
|
+
/* harmony export */ });
|
|
842
|
+
/* harmony import */ var next_server__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23211);
|
|
843
|
+
// Shared HTTP response builders for app/api/v1/** route handlers.
|
|
844
|
+
//
|
|
845
|
+
// Goal: every error/success payload across the v1 surface has the same
|
|
846
|
+
// shape. Before this lived inline, response bodies drifted —
|
|
847
|
+
// `{error: "x"}` vs `{message: "x"}`, 400 vs 422 for the same condition,
|
|
848
|
+
// some routes returned Zod's raw issue array, others stringified it.
|
|
849
|
+
|
|
850
|
+
function errorResponse(message, status = 400) {
|
|
851
|
+
return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json({
|
|
852
|
+
error: message
|
|
853
|
+
}, {
|
|
854
|
+
status
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
function notFoundResponse(message = "Not found") {
|
|
858
|
+
return errorResponse(message, 404);
|
|
859
|
+
}
|
|
860
|
+
function createdResponse(data) {
|
|
861
|
+
return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
|
|
862
|
+
status: 201
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
// Wrap a 200 JSON response with a private Cache-Control header. Use on safe
|
|
866
|
+
// GET endpoints that serve user-scoped data the client refetches often (panel
|
|
867
|
+
// mounts, navigation back/forward) but mutates rarely. The TTL is short
|
|
868
|
+
// enough that explicit mutations — which patch the client-side ApiClient
|
|
869
|
+
// cache in place — stay observably consistent without an extra roundtrip.
|
|
870
|
+
//
|
|
871
|
+
// swrSeconds (optional): stale-while-revalidate window. When set, the browser
|
|
872
|
+
// serves the cached response immediately and refreshes in the background,
|
|
873
|
+
// making navigation feel instant. Use for data that can tolerate brief
|
|
874
|
+
// staleness (tool list, agent configs, model list). Omit for real-time data
|
|
875
|
+
// (dashboard metrics, credential state).
|
|
876
|
+
function cachedJson(data, maxAgeSeconds, swrSeconds) {
|
|
877
|
+
const swr = swrSeconds ? `, stale-while-revalidate=${swrSeconds}` : "";
|
|
878
|
+
return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
|
|
879
|
+
headers: {
|
|
880
|
+
"Cache-Control": `private, max-age=${maxAgeSeconds}${swr}`
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
// Use for endpoints whose response contains live state that must never be
|
|
885
|
+
// served from cache — credentials, connection status, live config values.
|
|
886
|
+
function noStoreJson(data) {
|
|
887
|
+
return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
|
|
888
|
+
headers: {
|
|
889
|
+
"Cache-Control": "no-store"
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
// Validate a JSON request body against a zod schema.
|
|
894
|
+
// Returns either the parsed data or a 400 NextResponse explaining the issue.
|
|
895
|
+
// Caller pattern:
|
|
896
|
+
// const parsed = await validateBody(req, Schema);
|
|
897
|
+
// if (parsed instanceof NextResponse) return parsed;
|
|
898
|
+
// // use parsed.field
|
|
899
|
+
async function validateBody(req, schema) {
|
|
900
|
+
let raw;
|
|
901
|
+
try {
|
|
902
|
+
raw = await req.json();
|
|
903
|
+
} catch {
|
|
904
|
+
return errorResponse("Request body must be valid JSON", 400);
|
|
905
|
+
}
|
|
906
|
+
const parsed = schema.safeParse(raw);
|
|
907
|
+
if (!parsed.success) {
|
|
908
|
+
return errorResponse(parsed.error.issues[0]?.message ?? "invalid body", 400);
|
|
909
|
+
}
|
|
910
|
+
return parsed.data;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
|
|
569
914
|
/***/ }),
|
|
570
915
|
|
|
571
916
|
/***/ 44708:
|
|
@@ -916,6 +1261,13 @@ module.exports = require("node:path");
|
|
|
916
1261
|
|
|
917
1262
|
/***/ }),
|
|
918
1263
|
|
|
1264
|
+
/***/ 77030:
|
|
1265
|
+
/***/ ((module) => {
|
|
1266
|
+
|
|
1267
|
+
module.exports = require("node:net");
|
|
1268
|
+
|
|
1269
|
+
/***/ }),
|
|
1270
|
+
|
|
919
1271
|
/***/ 77598:
|
|
920
1272
|
/***/ ((module) => {
|
|
921
1273
|
|
|
@@ -967,18 +1319,26 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
967
1319
|
/* harmony export */ POST: () => (/* binding */ POST)
|
|
968
1320
|
/* harmony export */ });
|
|
969
1321
|
/* harmony import */ var next_server__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23211);
|
|
1322
|
+
/* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(97377);
|
|
970
1323
|
/* harmony import */ var _lib_providers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(60034);
|
|
971
|
-
/* harmony import */ var
|
|
972
|
-
/* harmony import */ var
|
|
973
|
-
/* harmony import */ var
|
|
1324
|
+
/* harmony import */ var _lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(23619);
|
|
1325
|
+
/* harmony import */ var _lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(80937);
|
|
1326
|
+
/* harmony import */ var _lib_api_responses__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(39947);
|
|
1327
|
+
/* harmony import */ var _lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(45552);
|
|
1328
|
+
/* harmony import */ var _lib_utils_error__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(22032);
|
|
1329
|
+
|
|
974
1330
|
|
|
975
1331
|
|
|
976
1332
|
|
|
977
1333
|
|
|
978
1334
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
const CatalogBody = zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
1338
|
+
params: zod__WEBPACK_IMPORTED_MODULE_6__/* .record */ .g1P(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP(), zod__WEBPACK_IMPORTED_MODULE_6__/* .unknown */ .L5J()).optional()
|
|
1339
|
+
});
|
|
1340
|
+
// Live provider catalogs hit external APIs. Cache per-provider briefly so
|
|
1341
|
+
// opening the model browser repeatedly doesn't re-hit upstream.
|
|
982
1342
|
const PROVIDER_CATALOG_TTL_MS = 10 * 60 * 1000;
|
|
983
1343
|
const catalogCache = new Map();
|
|
984
1344
|
async function getCachedCatalog(provider, force) {
|
|
@@ -1025,12 +1385,11 @@ function catalogErrorResponse(err) {
|
|
|
1025
1385
|
// these responses since they're keyed on user-supplied secrets.
|
|
1026
1386
|
async function POST(req, { params }) {
|
|
1027
1387
|
const { provider } = await params;
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
body = await req.json();
|
|
1031
|
-
} catch {}
|
|
1388
|
+
const body = await (0,_lib_api_responses__WEBPACK_IMPORTED_MODULE_4__/* .validateBody */ .Jb)(req, CatalogBody);
|
|
1389
|
+
if (body instanceof next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse) return body;
|
|
1032
1390
|
try {
|
|
1033
1391
|
const models = await fetchCatalog(provider, body.params);
|
|
1392
|
+
catalogCache.delete(provider);
|
|
1034
1393
|
return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(models, {
|
|
1035
1394
|
headers: {
|
|
1036
1395
|
"Cache-Control": "no-store"
|
|
@@ -1043,19 +1402,70 @@ async function POST(req, { params }) {
|
|
|
1043
1402
|
async function fetchCatalog(provider, overrides) {
|
|
1044
1403
|
switch(provider){
|
|
1045
1404
|
case "openai":
|
|
1046
|
-
return fetchOpenAICatalog();
|
|
1405
|
+
return fetchOpenAICatalog(overrides);
|
|
1047
1406
|
case "github-copilot":
|
|
1048
1407
|
return fetchGitHubCopilotCatalog();
|
|
1049
1408
|
case "anthropic":
|
|
1050
|
-
return
|
|
1409
|
+
return fetchAnthropicCatalog(overrides);
|
|
1051
1410
|
case "gemini":
|
|
1052
|
-
return
|
|
1411
|
+
return fetchGeminiCatalog(overrides);
|
|
1053
1412
|
case "deepseek":
|
|
1054
|
-
return
|
|
1413
|
+
return fetchDeepseekCatalog(overrides);
|
|
1055
1414
|
default:
|
|
1056
1415
|
return fetchExternalCatalog(provider, overrides);
|
|
1057
1416
|
}
|
|
1058
1417
|
}
|
|
1418
|
+
const PROVIDER_API_KEY_ENV = {
|
|
1419
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
1420
|
+
openai: "OPENAI_API_KEY",
|
|
1421
|
+
gemini: "GEMINI_API_KEY",
|
|
1422
|
+
deepseek: "DEEPSEEK_API_KEY"
|
|
1423
|
+
};
|
|
1424
|
+
function catalogParamsCandidates(provider, overrides) {
|
|
1425
|
+
const envKey = process.env[PROVIDER_API_KEY_ENV[provider] ?? ""];
|
|
1426
|
+
const configs = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().filter((cfg)=>cfg.provider === provider);
|
|
1427
|
+
const candidates = configs.map((cfg)=>{
|
|
1428
|
+
const params = {
|
|
1429
|
+
...(0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(cfg),
|
|
1430
|
+
...overrides ?? {}
|
|
1431
|
+
};
|
|
1432
|
+
if (!params.api_key && envKey) params.api_key = envKey;
|
|
1433
|
+
return params;
|
|
1434
|
+
});
|
|
1435
|
+
if (overrides) {
|
|
1436
|
+
const params = {
|
|
1437
|
+
...overrides
|
|
1438
|
+
};
|
|
1439
|
+
if (!params.api_key && envKey) params.api_key = envKey;
|
|
1440
|
+
candidates.push(params);
|
|
1441
|
+
}
|
|
1442
|
+
if (candidates.length === 0 && envKey) candidates.push({
|
|
1443
|
+
api_key: envKey
|
|
1444
|
+
});
|
|
1445
|
+
if (candidates.length === 0) candidates.push({});
|
|
1446
|
+
return candidates;
|
|
1447
|
+
}
|
|
1448
|
+
async function fetchConfiguredCatalog(provider, overrides, fetcher, fallback) {
|
|
1449
|
+
const candidates = catalogParamsCandidates(provider, overrides).filter((params)=>typeof params.api_key === "string" && params.api_key.length > 0);
|
|
1450
|
+
if (candidates.length === 0) return fallback();
|
|
1451
|
+
let lastErr;
|
|
1452
|
+
for (const params of candidates){
|
|
1453
|
+
try {
|
|
1454
|
+
return await fetcher(params, params.api_key);
|
|
1455
|
+
} catch (err) {
|
|
1456
|
+
lastErr = err;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
throw lastErr ?? new Error(`${provider} catalog request failed`);
|
|
1460
|
+
}
|
|
1461
|
+
async function requestCatalogJson(provider, url, init) {
|
|
1462
|
+
const res = await fetch(url, {
|
|
1463
|
+
...init,
|
|
1464
|
+
signal: AbortSignal.timeout(15000)
|
|
1465
|
+
});
|
|
1466
|
+
if (!res.ok) throw new Error(`${provider} catalog error: ${res.status}`);
|
|
1467
|
+
return res.json();
|
|
1468
|
+
}
|
|
1059
1469
|
async function fetchExternalCatalog(providerName, overrides) {
|
|
1060
1470
|
let provider;
|
|
1061
1471
|
try {
|
|
@@ -1070,9 +1480,9 @@ async function fetchExternalCatalog(providerName, overrides) {
|
|
|
1070
1480
|
// row is misconfigured. Overrides are merged on top of each candidate,
|
|
1071
1481
|
// then also tried standalone, so a freshly-typed api_key works before
|
|
1072
1482
|
// the user has saved it.
|
|
1073
|
-
const cfgs = (0,
|
|
1483
|
+
const cfgs = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().filter((c)=>c.provider === providerName);
|
|
1074
1484
|
const candidates = cfgs.map((c)=>({
|
|
1075
|
-
...(0,
|
|
1485
|
+
...(0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(c),
|
|
1076
1486
|
...overrides ?? {}
|
|
1077
1487
|
}));
|
|
1078
1488
|
if (overrides && Object.keys(overrides).length > 0) candidates.push(overrides);
|
|
@@ -1089,42 +1499,159 @@ async function fetchExternalCatalog(providerName, overrides) {
|
|
|
1089
1499
|
throw lastErr ?? new Error(`${providerName}: no usable credentials for catalog`);
|
|
1090
1500
|
}
|
|
1091
1501
|
// ── OpenAI ────────────────────────────────────────────────────────────────────
|
|
1092
|
-
async function fetchOpenAICatalog() {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1502
|
+
async function fetchOpenAICatalog(overrides) {
|
|
1503
|
+
return fetchConfiguredCatalog("openai", overrides, async (params, apiKey)=>{
|
|
1504
|
+
const url = endpointUrl(params.base_url, "https://api.openai.com/v1", "/models");
|
|
1505
|
+
const data = await requestCatalogJson("OpenAI", url, {
|
|
1506
|
+
headers: {
|
|
1507
|
+
...params.extra_headers,
|
|
1508
|
+
Authorization: "Bearer " + apiKey
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
const chatPrefixes = [
|
|
1512
|
+
"gpt-",
|
|
1513
|
+
"o1",
|
|
1514
|
+
"o3",
|
|
1515
|
+
"o4",
|
|
1516
|
+
"chatgpt-"
|
|
1517
|
+
];
|
|
1518
|
+
return (data.data ?? []).filter((m)=>chatPrefixes.some((p)=>m.id.startsWith(p))).map((m)=>({
|
|
1519
|
+
id: m.id,
|
|
1520
|
+
context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("openai", m.id),
|
|
1521
|
+
max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("openai", m.id),
|
|
1522
|
+
hosted_on: "azure/openai",
|
|
1523
|
+
capabilities: {
|
|
1524
|
+
vision: m.id.includes("vision") || m.id.startsWith("gpt-4"),
|
|
1525
|
+
tools: true,
|
|
1526
|
+
streaming: true,
|
|
1527
|
+
json_mode: true,
|
|
1528
|
+
web_search: false,
|
|
1529
|
+
audio: m.id.includes("audio") || m.id.startsWith("gpt-4o") || m.id.startsWith("gpt-5"),
|
|
1530
|
+
files: m.id.startsWith("gpt-4") || m.id.startsWith("gpt-5") || m.id.startsWith("o")
|
|
1531
|
+
}
|
|
1532
|
+
})).sort((a, b)=>a.id.localeCompare(b.id));
|
|
1533
|
+
}, ()=>{
|
|
1534
|
+
throw new Error("OpenAI: no api_key configured.");
|
|
1102
1535
|
});
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
"
|
|
1107
|
-
"
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1536
|
+
}
|
|
1537
|
+
async function fetchAnthropicCatalog(overrides) {
|
|
1538
|
+
return fetchConfiguredCatalog("anthropic", overrides, async (params, apiKey)=>{
|
|
1539
|
+
const url = endpointUrl(params.base_url, "https://api.anthropic.com", "/v1/models");
|
|
1540
|
+
url.searchParams.set("limit", "1000");
|
|
1541
|
+
const models = [];
|
|
1542
|
+
let afterId;
|
|
1543
|
+
do {
|
|
1544
|
+
const pageUrl = new URL(url);
|
|
1545
|
+
if (afterId) pageUrl.searchParams.set("after_id", afterId);
|
|
1546
|
+
const page = await requestCatalogJson("Anthropic", pageUrl, {
|
|
1547
|
+
headers: {
|
|
1548
|
+
...params.extra_headers,
|
|
1549
|
+
"x-api-key": apiKey,
|
|
1550
|
+
"anthropic-version": "2023-06-01"
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
models.push(...page.data ?? []);
|
|
1554
|
+
if (page.has_more && !page.last_id) throw new Error("Anthropic catalog response is missing its next-page cursor");
|
|
1555
|
+
if (page.has_more && page.last_id === afterId) throw new Error("Anthropic catalog pagination did not advance");
|
|
1556
|
+
afterId = page.has_more ? page.last_id ?? undefined : undefined;
|
|
1557
|
+
}while (afterId);
|
|
1558
|
+
return models.map((model)=>{
|
|
1559
|
+
const known = (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("anthropic", model.id);
|
|
1560
|
+
const vision = model.capabilities?.image_input?.supported ?? known.vision;
|
|
1561
|
+
return {
|
|
1562
|
+
id: model.id,
|
|
1563
|
+
context_length: model.max_input_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("anthropic", model.id),
|
|
1564
|
+
max_output_tokens: model.max_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("anthropic", model.id),
|
|
1565
|
+
hosted_on: "anthropic",
|
|
1566
|
+
capabilities: {
|
|
1567
|
+
vision,
|
|
1568
|
+
tools: known.tools,
|
|
1569
|
+
streaming: known.streaming,
|
|
1570
|
+
json_mode: model.capabilities?.structured_outputs?.supported ?? known.json_mode,
|
|
1571
|
+
web_search: model.capabilities?.server_tools?.web_search?.supported ?? known.web_search,
|
|
1572
|
+
audio: known.audio,
|
|
1573
|
+
files: model.capabilities?.pdf_input?.supported ?? known.files
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
});
|
|
1577
|
+
}, anthropicKnownModels);
|
|
1578
|
+
}
|
|
1579
|
+
async function fetchGeminiCatalog(overrides) {
|
|
1580
|
+
return fetchConfiguredCatalog("gemini", overrides, async (params, apiKey)=>{
|
|
1581
|
+
const url = endpointUrl(params.gemini_native_base_url, "https://generativelanguage.googleapis.com/v1beta", "/models");
|
|
1582
|
+
url.searchParams.set("pageSize", "1000");
|
|
1583
|
+
const models = [];
|
|
1584
|
+
let pageToken;
|
|
1585
|
+
do {
|
|
1586
|
+
const pageUrl = new URL(url);
|
|
1587
|
+
if (pageToken) pageUrl.searchParams.set("pageToken", pageToken);
|
|
1588
|
+
const page = await requestCatalogJson("Gemini", pageUrl, {
|
|
1589
|
+
headers: {
|
|
1590
|
+
"x-goog-api-key": apiKey
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
models.push(...page.models ?? []);
|
|
1594
|
+
if (page.nextPageToken && page.nextPageToken === pageToken) {
|
|
1595
|
+
throw new Error("Gemini catalog pagination did not advance");
|
|
1596
|
+
}
|
|
1597
|
+
pageToken = page.nextPageToken;
|
|
1598
|
+
}while (pageToken);
|
|
1599
|
+
return models.map((model)=>{
|
|
1600
|
+
const id = model.name.replace(/^models\//, "");
|
|
1601
|
+
if (!id.startsWith("gemini-") || !model.supportedGenerationMethods?.includes("generateContent")) return null;
|
|
1602
|
+
return {
|
|
1603
|
+
id,
|
|
1604
|
+
context_length: model.inputTokenLimit ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("gemini", id),
|
|
1605
|
+
max_output_tokens: model.outputTokenLimit ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("gemini", id),
|
|
1606
|
+
hosted_on: "google",
|
|
1607
|
+
capabilities: (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("gemini", id)
|
|
1608
|
+
};
|
|
1609
|
+
}).filter((model)=>model !== null).sort((a, b)=>a.id.localeCompare(b.id));
|
|
1610
|
+
}, geminiKnownModels);
|
|
1611
|
+
}
|
|
1612
|
+
async function fetchDeepseekCatalog(overrides) {
|
|
1613
|
+
return fetchConfiguredCatalog("deepseek", overrides, async (params, apiKey)=>{
|
|
1614
|
+
const url = endpointUrl(params.base_url, "https://api.deepseek.com", "/models");
|
|
1615
|
+
const data = await requestCatalogJson("DeepSeek", url, {
|
|
1616
|
+
headers: {
|
|
1617
|
+
...params.extra_headers,
|
|
1618
|
+
Authorization: "Bearer " + apiKey
|
|
1125
1619
|
}
|
|
1126
|
-
})
|
|
1127
|
-
|
|
1620
|
+
});
|
|
1621
|
+
return (data.data ?? []).map((model)=>{
|
|
1622
|
+
const known = (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("deepseek", model.id);
|
|
1623
|
+
const vision = model.input_modalities?.includes("image") ?? known.vision;
|
|
1624
|
+
return {
|
|
1625
|
+
id: model.id,
|
|
1626
|
+
context_length: model.context_window ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("deepseek", model.id),
|
|
1627
|
+
max_output_tokens: model.max_output_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("deepseek", model.id),
|
|
1628
|
+
hosted_on: "deepseek",
|
|
1629
|
+
capabilities: {
|
|
1630
|
+
...known,
|
|
1631
|
+
vision,
|
|
1632
|
+
audio: model.input_modalities?.includes("audio") ?? known.audio
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
});
|
|
1636
|
+
}, deepseekKnownModels);
|
|
1637
|
+
}
|
|
1638
|
+
function endpointUrl(baseUrl, defaultBaseUrl, path) {
|
|
1639
|
+
const base = typeof baseUrl === "string" && baseUrl.trim() ? baseUrl.trim() : defaultBaseUrl;
|
|
1640
|
+
let url;
|
|
1641
|
+
try {
|
|
1642
|
+
url = new URL(base);
|
|
1643
|
+
} catch {
|
|
1644
|
+
throw new Error("Provider base URL must be a valid absolute URL");
|
|
1645
|
+
}
|
|
1646
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
1647
|
+
throw new Error("Provider base URL must use HTTP or HTTPS");
|
|
1648
|
+
}
|
|
1649
|
+
const normalizedPath = url.pathname.replace(/\/+$/, "");
|
|
1650
|
+
const suffix = path === "/v1/models" && normalizedPath.endsWith("/v1") ? "/models" : path;
|
|
1651
|
+
url.pathname = `${normalizedPath}${suffix}` || "/";
|
|
1652
|
+
url.search = "";
|
|
1653
|
+
url.hash = "";
|
|
1654
|
+
return url;
|
|
1128
1655
|
}
|
|
1129
1656
|
// ── GitHub Copilot ────────────────────────────────────────────────────────────
|
|
1130
1657
|
async function fetchGitHubCopilotCatalog() {
|
|
@@ -1142,9 +1669,9 @@ async function fetchGitHubCopilotCatalog() {
|
|
|
1142
1669
|
}
|
|
1143
1670
|
// 2. Look up a saved github-copilot model config for an explicit session
|
|
1144
1671
|
// token or a non-PAT credential that supports exchange.
|
|
1145
|
-
const cfg = (0,
|
|
1672
|
+
const cfg = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().find((c)=>c.provider === "github-copilot");
|
|
1146
1673
|
if (cfg) {
|
|
1147
|
-
const params = (0,
|
|
1674
|
+
const params = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(cfg);
|
|
1148
1675
|
const sessionTok = params.copilot_session_token?.trim();
|
|
1149
1676
|
if (sessionTok) {
|
|
1150
1677
|
try {
|
|
@@ -1179,14 +1706,14 @@ async function fetchCopilotChatCatalog(sessionToken) {
|
|
|
1179
1706
|
}
|
|
1180
1707
|
});
|
|
1181
1708
|
if (!res.ok) {
|
|
1182
|
-
const body = await (0,
|
|
1709
|
+
const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_7__/* .readErrorBody */ .N)(res);
|
|
1183
1710
|
throw new Error(`GitHub Copilot catalog error: ${res.status} ${body}`);
|
|
1184
1711
|
}
|
|
1185
1712
|
const data = await res.json();
|
|
1186
1713
|
return data.data.map((m)=>({
|
|
1187
1714
|
id: m.id,
|
|
1188
|
-
context_length: (0,
|
|
1189
|
-
max_output_tokens: (0,
|
|
1715
|
+
context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("github-copilot", m.id),
|
|
1716
|
+
max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", m.id),
|
|
1190
1717
|
hosted_on: "github",
|
|
1191
1718
|
capabilities: {
|
|
1192
1719
|
vision: m.capabilities?.supports?.vision ?? false,
|
|
@@ -1210,7 +1737,7 @@ async function exchangeCopilotSessionToken(githubToken) {
|
|
|
1210
1737
|
}
|
|
1211
1738
|
});
|
|
1212
1739
|
if (!res.ok) {
|
|
1213
|
-
const body = await (0,
|
|
1740
|
+
const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_7__/* .readErrorBody */ .N)(res);
|
|
1214
1741
|
throw new Error(`GitHub Copilot token exchange failed: ${res.status} ${body}`);
|
|
1215
1742
|
}
|
|
1216
1743
|
const json = await res.json();
|
|
@@ -1223,8 +1750,8 @@ function githubCopilotKnownModels() {
|
|
|
1223
1750
|
// stored, exchange failed, etc.). Keep in sync with Copilot's current line-up.
|
|
1224
1751
|
const v = (id, vision = false, tools = true)=>({
|
|
1225
1752
|
id,
|
|
1226
|
-
context_length: (0,
|
|
1227
|
-
max_output_tokens: (0,
|
|
1753
|
+
context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("github-copilot", id),
|
|
1754
|
+
max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", id),
|
|
1228
1755
|
hosted_on: "github",
|
|
1229
1756
|
capabilities: {
|
|
1230
1757
|
vision,
|