@agent-native/core 0.187.0 → 0.187.1-nightly-20260925003003

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +4 -3
  3. package/corpus/templates/analytics/changelog/2026-09-24-analytics-sidebar-footer-aligns-consistently.md +6 -0
  4. package/corpus/templates/analytics/changelog/2026-09-24-dashboard-emails-match-stacked-area-totals.md +6 -0
  5. package/corpus/templates/analytics/server/lib/report-chart-svg.ts +47 -20
  6. package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +1 -1
  7. package/corpus/templates/calendar/changelog/2026-09-24-guest-inputs-wrap-beneath-existing-guests-so-the-active-inpu.md +6 -0
  8. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +8 -3
  9. package/corpus/templates/clips/app/lib/recording-link.ts +21 -0
  10. package/corpus/templates/clips/app/routes/record.tsx +27 -8
  11. package/corpus/templates/clips/changelog/2026-09-24-the-camera-bubble-stays-visible-while-you-reposition-it-befo.md +6 -0
  12. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -0
  13. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +63 -55
  14. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +251 -74
  15. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +66 -56
  16. package/corpus/templates/design/app/components/design/EditPanel.tsx +19 -0
  17. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +59 -9
  18. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +4 -0
  19. package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +119 -0
  20. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +48 -51
  21. package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +1 -0
  22. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +298 -187
  23. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +2 -2
  24. package/corpus/templates/design/app/components/design/inspector/index.ts +4 -0
  25. package/corpus/templates/design/app/components/design/multi-screen/types.ts +4 -2
  26. package/corpus/templates/design/app/i18n/en-US.ts +6 -0
  27. package/corpus/templates/design/app/pages/Present.tsx +101 -87
  28. package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +75 -14
  29. package/corpus/templates/design/app/pages/design-editor/commands/README.md +1 -0
  30. package/corpus/templates/design/app/pages/design-editor/commands/commit-relative-style-delta-to-selected-layers.ts +69 -56
  31. package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +16 -0
  32. package/corpus/templates/design/app/pages/design-editor/commands/scale-selection.ts +17 -2
  33. package/corpus/templates/design/app/pages/design-editor/commands/styles-change.ts +23 -30
  34. package/corpus/templates/design/app/pages/design-editor/commands/swap-fill-stroke.ts +105 -0
  35. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +21 -0
  36. package/corpus/templates/design/app/pages/present-review-state.ts +7 -1
  37. package/corpus/templates/design/changelog/2026-09-24-a-vector-s-stroke-row-shows-position-beside-weight-instead-o.md +6 -0
  38. package/corpus/templates/design/changelog/2026-09-24-css-margins-can-be-adjusted-on-the-canvas-and-in-the-layout-.md +6 -0
  39. package/corpus/templates/design/changelog/2026-09-24-design-reviews-show-the-real-canvas-beside-its-conversation.md +6 -0
  40. package/corpus/templates/design/changelog/2026-09-24-double-clicking-text-or-a-vector-on-the-board-starts-editing.md +6 -0
  41. package/corpus/templates/design/changelog/2026-09-24-interact-opens-a-focused-responsive-preview-without-reloadin.md +6 -0
  42. package/corpus/templates/design/changelog/2026-09-24-keep-gradient-values-visible-and-limit-canvas-paints-to-supp.md +6 -0
  43. package/corpus/templates/design/changelog/2026-09-24-open-pen-paths-no-longer-paint-a-filled-triangle-after-shift.md +6 -0
  44. package/corpus/templates/design/changelog/2026-09-24-re-clicking-the-active-responsive-preview-returns-to-the-can.md +6 -0
  45. package/corpus/templates/design/changelog/2026-09-24-resized-vectors-can-be-point-edited-and-the-k-scale-tool-sho.md +6 -0
  46. package/corpus/templates/design/changelog/2026-09-24-while-editing-text-click-to-place-the-caret-and-double-click.md +6 -0
  47. package/corpus/templates/design/e2e/helpers.ts +19 -2
  48. package/corpus/templates/mail/app/components/email/ComposeModal.tsx +1 -1
  49. package/corpus/templates/mail/changelog/2026-09-24-gmail-push-ack.md +6 -0
  50. package/corpus/templates/mail/changelog/2026-09-24-the-composer-keeps-its-taller-layout-in-a-narrower-window.md +6 -0
  51. package/corpus/templates/mail/server/db/schema.ts +26 -1
  52. package/corpus/templates/mail/server/lib/inbox-store.ts +68 -23
  53. package/corpus/templates/mail/server/lib/inbox-sync.ts +43 -17
  54. package/corpus/templates/mail/server/plugins/db.ts +19 -0
  55. package/corpus/templates/mail/server/routes/api/gmail/push.post.ts +4 -15
  56. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +45 -30
  57. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +18 -2
  58. package/corpus/templates/slides/actions/export-html.ts +28 -17
  59. package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +27 -15
  60. package/corpus/templates/slides/app/pages/DeckEditor.tsx +1 -1
  61. package/corpus/templates/slides/changelog/2026-09-23-decks-with-no-design-system-now-follow-a-theme-chosen-for-th.md +6 -0
  62. package/corpus/templates/slides/shared/slide-background.ts +3 -1
  63. package/dist/agent/engine/builder-engine.js +11 -0
  64. package/dist/agent/engine/types.d.ts +1 -0
  65. package/dist/agent/production-agent.d.ts +2 -0
  66. package/dist/agent/production-agent.js +32 -4
  67. package/dist/agent/run-loop-with-resume.js +6 -0
  68. package/dist/cli/index.js +4 -4
  69. package/dist/cli/process.d.ts +10 -1
  70. package/dist/cli/process.js +66 -0
  71. package/dist/cli/workspace-dev.js +2 -0
  72. package/dist/client/agent-chat.js +13 -14
  73. package/dist/client/error-format.js +4 -4
  74. package/dist/client/observability/ObservabilityDashboard.js +95 -65
  75. package/dist/client/observability/OutputPreview.d.ts +2 -1
  76. package/dist/client/observability/OutputPreview.js +64 -7
  77. package/dist/client/observability/useObservability.d.ts +2 -1
  78. package/dist/client/observability/useObservability.js +5 -1
  79. package/dist/client/settings/UsageSection.js +105 -17
  80. package/dist/collab/routes.d.ts +1 -1
  81. package/dist/collab/struct-routes.d.ts +1 -1
  82. package/dist/db/client.d.ts +44 -0
  83. package/dist/db/client.js +62 -3
  84. package/dist/db/create-get-db.js +23 -1
  85. package/dist/db/embedded-runtime.d.ts +21 -0
  86. package/dist/db/embedded-runtime.js +27 -0
  87. package/dist/db/migrations.js +2 -0
  88. package/dist/db/server-runtime.d.ts +22 -0
  89. package/dist/db/server-runtime.js +26 -0
  90. package/dist/deploy/build.d.ts +29 -0
  91. package/dist/deploy/build.js +204 -121
  92. package/dist/feature-flags/index.d.ts +1 -1
  93. package/dist/feature-flags/index.js +1 -1
  94. package/dist/feature-flags/registry.d.ts +1 -0
  95. package/dist/feature-flags/registry.js +5 -0
  96. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  97. package/dist/index.d.ts +1 -1
  98. package/dist/index.js +1 -1
  99. package/dist/integrations/webhook-handler.js +4 -1
  100. package/dist/jobs/background-automation-runner.js +6 -1
  101. package/dist/localization/core-messages/ar-SA.js +9 -1
  102. package/dist/localization/core-messages/de-DE.js +9 -1
  103. package/dist/localization/core-messages/en-US.d.ts +9 -1
  104. package/dist/localization/core-messages/en-US.js +9 -1
  105. package/dist/localization/core-messages/es-ES.js +9 -1
  106. package/dist/localization/core-messages/fr-FR.js +9 -1
  107. package/dist/localization/core-messages/hi-IN.js +9 -1
  108. package/dist/localization/core-messages/ja-JP.js +9 -1
  109. package/dist/localization/core-messages/ko-KR.js +9 -1
  110. package/dist/localization/core-messages/pt-BR.js +9 -1
  111. package/dist/localization/core-messages/supplemental/ar-SA.js +1 -0
  112. package/dist/localization/core-messages/supplemental/de-DE.js +1 -0
  113. package/dist/localization/core-messages/supplemental/en-US.js +1 -0
  114. package/dist/localization/core-messages/supplemental/es-ES.js +1 -0
  115. package/dist/localization/core-messages/supplemental/fr-FR.js +1 -0
  116. package/dist/localization/core-messages/supplemental/hi-IN.js +1 -0
  117. package/dist/localization/core-messages/supplemental/ja-JP.js +1 -0
  118. package/dist/localization/core-messages/supplemental/ko-KR.js +1 -0
  119. package/dist/localization/core-messages/supplemental/pt-BR.js +1 -0
  120. package/dist/localization/core-messages/supplemental/zh-CN.js +1 -0
  121. package/dist/localization/core-messages/supplemental/zh-TW.js +1 -0
  122. package/dist/localization/core-messages/zh-CN.js +9 -1
  123. package/dist/localization/core-messages/zh-TW.js +9 -1
  124. package/dist/localization/core-messages.d.ts +9 -1
  125. package/dist/localization/mcp-settings-messages.d.ts +1 -0
  126. package/dist/mcp/connect-route.js +45 -8
  127. package/dist/mcp/connect-store.d.ts +7 -5
  128. package/dist/mcp/connect-store.js +30 -39
  129. package/dist/notifications/routes.d.ts +3 -3
  130. package/dist/observability/actions/get-observability-review-detail.d.ts +7 -0
  131. package/dist/observability/actions/get-observability-review-detail.js +25 -0
  132. package/dist/observability/reviews.d.ts +9 -1
  133. package/dist/observability/reviews.js +20 -0
  134. package/dist/observability/routes.d.ts +3 -3
  135. package/dist/observability/types.d.ts +8 -0
  136. package/dist/org/handlers.d.ts +1 -1
  137. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  138. package/dist/provider-api/actions/provider-api.d.ts +9 -9
  139. package/dist/scripts/db/query.js +6 -1
  140. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  141. package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
  142. package/dist/server/agent-teams.js +4 -1
  143. package/dist/server/auth.js +60 -20
  144. package/dist/server/better-auth-instance.js +7 -1
  145. package/dist/server/core-routes-plugin.d.ts +1 -1
  146. package/dist/server/core-routes-plugin.js +2 -0
  147. package/dist/server/embedded.js +6 -0
  148. package/dist/server/framework-request-handler.js +6 -0
  149. package/dist/server/realtime-token.d.ts +1 -1
  150. package/dist/usage/actions/get-usage-metrics.js +4 -1
  151. package/dist/usage/metrics-store.d.ts +19 -0
  152. package/dist/usage/metrics-store.js +106 -14
  153. package/dist/usage/store.d.ts +7 -2
  154. package/dist/usage/store.js +25 -4
  155. package/dist/vite/action-types-plugin.js +4 -0
  156. package/dist/vite/client.d.ts +6 -1
  157. package/dist/vite/client.js +40 -1
  158. package/package.json +4 -3
@@ -598,7 +598,8 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
598
598
  (usage.inputTokens > 0 ||
599
599
  usage.outputTokens > 0 ||
600
600
  usage.cacheReadTokens > 0 ||
601
- usage.cacheWriteTokens > 0)) {
601
+ usage.cacheWriteTokens > 0 ||
602
+ usage.builderCreditsUsed != null)) {
602
603
  try {
603
604
  const { recordUsage } = await import("../usage/store.js");
604
605
  await recordUsage({
@@ -607,6 +608,10 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
607
608
  outputTokens: usage.outputTokens,
608
609
  cacheReadTokens: usage.cacheReadTokens,
609
610
  cacheWriteTokens: usage.cacheWriteTokens,
611
+ ...(usage.builderCreditsUsed == null
612
+ ? {}
613
+ : { builderCreditsUsed: usage.builderCreditsUsed }),
614
+ engineName: usage.engineName ?? engine.name,
610
615
  model: usage.model,
611
616
  label: usageLabel,
612
617
  app: deps.appId,
@@ -425,7 +425,7 @@ const messages = {
425
425
  "errorMessages.providerRateLimit": "يفرض مزوّد النموذج حاليًا حدًا على معدل طلبات هذه المحادثة. انتظر قليلًا، ثم أعد المحاولة.",
426
426
  "errorMessages.providerTransientRejection": "رفض مزوّد الذكاء الاصطناعي هذا الطلب مؤقتًا. عادةً ما يُحل هذا خلال دقيقة — أعد المحاولة.",
427
427
  "errorMessages.startNewChat": "بدء محادثة جديدة",
428
- "errorMessages.upgradeAtBuilder": "الترقية عبر Builder.io",
428
+ "errorMessages.addCreditsInBuilder": "إضافة أرصدة في Builder",
429
429
  "feedback.inaccurate": "غير دقيق",
430
430
  "feedback.keyboardHint": "{{shortcut}} Enter للإرسال",
431
431
  "feedback.notHelpful": "غير مفيد",
@@ -753,5 +753,13 @@ const messages = {
753
753
  "settings.emailChangeError": "تعذر إرسال التأكيد.",
754
754
  "settings.emailNewLabel": "البريد الإلكتروني الجديد",
755
755
  "settings.emailNewPlaceholder": "أدخل بريدًا إلكترونيًا جديدًا",
756
+ "usage.builderCredits": "أرصدة Builder",
757
+ "usage.estimatedBuilderCredits": "~{{amount}} رصيد مقدّر",
758
+ "usage.otherUsdSpend": "{{amount}} دولار أمريكي أخرى",
759
+ "usage.noBuilderCredits": "0 من أرصدة Builder",
760
+ "usage.otherUnclassifiedSpend": "إنفاق آخر أو غير مصنّف بالدولار الأمريكي",
761
+ "usage.providerSpendDetail": "استخدام المزوّد أو المكالمات الأقدم خارج فوترة Builder",
762
+ "usage.providerSpendToday": "استخدام آخر أو غير مصنّف اليوم: {{amount}}",
763
+ "usage.driverCreditsAndUsd": "أرصدة Builder / دولار أمريكي",
756
764
  };
757
765
  export default messages;
@@ -595,7 +595,7 @@ const messages = {
595
595
  "errorMessages.providerRateLimit": "Der Modellanbieter begrenzt diesen Chat derzeit. Warte einen Moment und versuche es dann erneut.",
596
596
  "errorMessages.providerTransientRejection": "Der KI-Anbieter hat diese Anfrage vorübergehend abgelehnt. Das behebt sich meist innerhalb einer Minute – versuche es erneut.",
597
597
  "errorMessages.startNewChat": "Neuen Chat starten",
598
- "errorMessages.upgradeAtBuilder": "Bei Builder.io upgraden",
598
+ "errorMessages.addCreditsInBuilder": "Credits bei Builder hinzufügen",
599
599
  "feedback.inaccurate": "Ungenau",
600
600
  "feedback.keyboardHint": "{{shortcut}} Enter zum Senden",
601
601
  "feedback.notHelpful": "Nicht hilfreich",
@@ -725,5 +725,13 @@ const messages = {
725
725
  "settings.emailChangeError": "Bestätigung konnte nicht gesendet werden.",
726
726
  "settings.emailNewLabel": "Neue E-Mail-Adresse",
727
727
  "settings.emailNewPlaceholder": "Neue E-Mail-Adresse eingeben",
728
+ "usage.builderCredits": "Builder-Credits",
729
+ "usage.estimatedBuilderCredits": "~{{amount}} geschätzte Credits",
730
+ "usage.otherUsdSpend": "{{amount}} USD sonstige",
731
+ "usage.noBuilderCredits": "0 Builder-Credits",
732
+ "usage.otherUnclassifiedSpend": "Sonstige oder nicht zugeordnete Ausgaben in USD",
733
+ "usage.providerSpendDetail": "Anbieteraufrufe oder ältere Aufrufe außerhalb der Builder-Abrechnung",
734
+ "usage.providerSpendToday": "Sonstige oder nicht zugeordnete Nutzung heute: {{amount}}",
735
+ "usage.driverCreditsAndUsd": "Builder-Credits / USD",
728
736
  };
729
737
  export default messages;
@@ -417,7 +417,7 @@ declare const messages: {
417
417
  readonly "errorMessages.providerRateLimit": "The model provider is rate-limiting this chat right now. Wait a moment, then retry.";
418
418
  readonly "errorMessages.providerTransientRejection": "The AI provider temporarily refused this request. This usually clears within a minute — retry.";
419
419
  readonly "errorMessages.startNewChat": "Start new chat";
420
- readonly "errorMessages.upgradeAtBuilder": "Upgrade at Builder.io";
420
+ readonly "errorMessages.addCreditsInBuilder": "Add credits in Builder";
421
421
  readonly "feedback.inaccurate": "Inaccurate";
422
422
  readonly "feedback.keyboardHint": "{{shortcut}} Enter to send";
423
423
  readonly "feedback.notHelpful": "Not helpful";
@@ -725,5 +725,13 @@ declare const messages: {
725
725
  readonly "settings.emailChangeError": "Could not send confirmation.";
726
726
  readonly "settings.emailNewLabel": "New email";
727
727
  readonly "settings.emailNewPlaceholder": "Enter new email";
728
+ readonly "usage.builderCredits": "Builder credits";
729
+ readonly "usage.estimatedBuilderCredits": "~{{amount}} estimated credits";
730
+ readonly "usage.otherUsdSpend": "{{amount}} other USD";
731
+ readonly "usage.noBuilderCredits": "0 Builder credits";
732
+ readonly "usage.otherUnclassifiedSpend": "Other or unclassified USD spend";
733
+ readonly "usage.providerSpendDetail": "Provider or older calls outside Builder billing";
734
+ readonly "usage.providerSpendToday": "Other or unclassified usage: {{amount}} today";
735
+ readonly "usage.driverCreditsAndUsd": "Builder credits / USD";
728
736
  };
729
737
  export default messages;
@@ -417,7 +417,7 @@ const messages = {
417
417
  "errorMessages.providerRateLimit": "The model provider is rate-limiting this chat right now. Wait a moment, then retry.",
418
418
  "errorMessages.providerTransientRejection": "The AI provider temporarily refused this request. This usually clears within a minute — retry.",
419
419
  "errorMessages.startNewChat": "Start new chat",
420
- "errorMessages.upgradeAtBuilder": "Upgrade at Builder.io",
420
+ "errorMessages.addCreditsInBuilder": "Add credits in Builder",
421
421
  "feedback.inaccurate": "Inaccurate",
422
422
  "feedback.keyboardHint": "{{shortcut}} Enter to send",
423
423
  "feedback.notHelpful": "Not helpful",
@@ -725,5 +725,13 @@ const messages = {
725
725
  "settings.emailChangeError": "Could not send confirmation.",
726
726
  "settings.emailNewLabel": "New email",
727
727
  "settings.emailNewPlaceholder": "Enter new email",
728
+ "usage.builderCredits": "Builder credits",
729
+ "usage.estimatedBuilderCredits": "~{{amount}} estimated credits",
730
+ "usage.otherUsdSpend": "{{amount}} other USD",
731
+ "usage.noBuilderCredits": "0 Builder credits",
732
+ "usage.otherUnclassifiedSpend": "Other or unclassified USD spend",
733
+ "usage.providerSpendDetail": "Provider or older calls outside Builder billing",
734
+ "usage.providerSpendToday": "Other or unclassified usage: {{amount}} today",
735
+ "usage.driverCreditsAndUsd": "Builder credits / USD",
728
736
  };
729
737
  export default messages;
@@ -602,7 +602,7 @@ const messages = {
602
602
  "errorMessages.providerRateLimit": "El proveedor del modelo está limitando temporalmente este chat. Espera un momento y vuelve a intentarlo.",
603
603
  "errorMessages.providerTransientRejection": "El proveedor de IA rechazó temporalmente esta solicitud. Esto suele resolverse en menos de un minuto: vuelve a intentarlo.",
604
604
  "errorMessages.startNewChat": "Iniciar un chat nuevo",
605
- "errorMessages.upgradeAtBuilder": "Mejorar el plan en Builder.io",
605
+ "errorMessages.addCreditsInBuilder": "Añadir créditos en Builder",
606
606
  "feedback.inaccurate": "Impreciso",
607
607
  "feedback.keyboardHint": "{{shortcut}} Enter para enviar",
608
608
  "feedback.notHelpful": "Poco útil",
@@ -732,5 +732,13 @@ const messages = {
732
732
  "settings.emailChangeError": "No se pudo enviar la confirmación.",
733
733
  "settings.emailNewLabel": "Correo electrónico nuevo",
734
734
  "settings.emailNewPlaceholder": "Introduce un correo nuevo",
735
+ "usage.builderCredits": "Créditos de Builder",
736
+ "usage.estimatedBuilderCredits": "~{{amount}} créditos estimados",
737
+ "usage.otherUsdSpend": "{{amount}} USD adicional",
738
+ "usage.noBuilderCredits": "0 créditos de Builder",
739
+ "usage.otherUnclassifiedSpend": "Gasto en USD adicional o sin clasificar",
740
+ "usage.providerSpendDetail": "Uso de proveedores o llamadas antiguas fuera de la facturación de Builder",
741
+ "usage.providerSpendToday": "Uso adicional o sin clasificar hoy: {{amount}}",
742
+ "usage.driverCreditsAndUsd": "Créditos de Builder / USD",
735
743
  };
736
744
  export default messages;
@@ -602,7 +602,7 @@ const messages = {
602
602
  "errorMessages.providerRateLimit": "Le fournisseur du modèle limite temporairement cette discussion. Patientez un instant, puis réessayez.",
603
603
  "errorMessages.providerTransientRejection": "Le fournisseur d'IA a temporairement refusé cette demande. Cela se résout généralement en moins d'une minute : réessayez.",
604
604
  "errorMessages.startNewChat": "Démarrer une nouvelle discussion",
605
- "errorMessages.upgradeAtBuilder": "Mettre à niveau sur Builder.io",
605
+ "errorMessages.addCreditsInBuilder": "Ajouter des crédits dans Builder",
606
606
  "feedback.inaccurate": "Inexact",
607
607
  "feedback.keyboardHint": "{{shortcut}} Entrée pour envoyer",
608
608
  "feedback.notHelpful": "Peu utile",
@@ -732,5 +732,13 @@ const messages = {
732
732
  "settings.emailChangeError": "Impossible d’envoyer la confirmation.",
733
733
  "settings.emailNewLabel": "Nouvelle adresse e-mail",
734
734
  "settings.emailNewPlaceholder": "Saisissez une nouvelle adresse e-mail",
735
+ "usage.builderCredits": "Crédits Builder",
736
+ "usage.estimatedBuilderCredits": "~{{amount}} crédits estimés",
737
+ "usage.otherUsdSpend": "{{amount}} USD supplémentaires",
738
+ "usage.noBuilderCredits": "0 crédit Builder",
739
+ "usage.otherUnclassifiedSpend": "Dépenses USD autres ou non classées",
740
+ "usage.providerSpendDetail": "Utilisation du fournisseur ou anciens appels hors facturation Builder",
741
+ "usage.providerSpendToday": "Autre utilisation ou non classée aujourd’hui : {{amount}}",
742
+ "usage.driverCreditsAndUsd": "Crédits Builder / USD",
735
743
  };
736
744
  export default messages;
@@ -417,7 +417,7 @@ const messages = {
417
417
  "errorMessages.providerRateLimit": "मॉडल प्रदाता अभी इस चैट की अनुरोध दर सीमित कर रहा है। कुछ देर रुकें, फिर से प्रयास करें।",
418
418
  "errorMessages.providerTransientRejection": "AI प्रदाता ने इस अनुरोध को अस्थायी रूप से अस्वीकार कर दिया। यह आमतौर पर एक मिनट के भीतर ठीक हो जाता है — फिर से प्रयास करें।",
419
419
  "errorMessages.startNewChat": "नई चैट शुरू करें",
420
- "errorMessages.upgradeAtBuilder": "Builder.io पर अपग्रेड करें",
420
+ "errorMessages.addCreditsInBuilder": "Builder में क्रेडिट जोड़ें",
421
421
  "feedback.inaccurate": "गलत जानकारी",
422
422
  "feedback.keyboardHint": "भेजने के लिए {{shortcut}} Enter",
423
423
  "feedback.notHelpful": "उपयोगी नहीं",
@@ -725,5 +725,13 @@ const messages = {
725
725
  "settings.emailChangeError": "पुष्टिकरण नहीं भेजा जा सका।",
726
726
  "settings.emailNewLabel": "नया ईमेल",
727
727
  "settings.emailNewPlaceholder": "नया ईमेल दर्ज करें",
728
+ "usage.builderCredits": "Builder क्रेडिट",
729
+ "usage.estimatedBuilderCredits": "~{{amount}} अनुमानित क्रेडिट",
730
+ "usage.otherUsdSpend": "{{amount}} अन्य USD",
731
+ "usage.noBuilderCredits": "0 Builder क्रेडिट",
732
+ "usage.otherUnclassifiedSpend": "अन्य या अवर्गीकृत USD खर्च",
733
+ "usage.providerSpendDetail": "Builder बिलिंग से बाहर प्रदाता या पुराने कॉल",
734
+ "usage.providerSpendToday": "आज का अन्य या अवर्गीकृत उपयोग: {{amount}}",
735
+ "usage.driverCreditsAndUsd": "Builder क्रेडिट / USD",
728
736
  };
729
737
  export default messages;
@@ -415,7 +415,7 @@ const messages = {
415
415
  "errorMessages.providerRateLimit": "現在、モデルプロバイダーがこのチャットのリクエスト数を制限しています。少し待ってから再試行してください。",
416
416
  "errorMessages.providerTransientRejection": "AIプロバイダーがこのリクエストを一時的に拒否しました。通常は1分以内に解消するので、再試行してください。",
417
417
  "errorMessages.startNewChat": "新しいチャットを開始",
418
- "errorMessages.upgradeAtBuilder": "Builder.io でアップグレード",
418
+ "errorMessages.addCreditsInBuilder": "Builderでクレジットを追加",
419
419
  "feedback.inaccurate": "不正確",
420
420
  "feedback.keyboardHint": "{{shortcut}} Enter で送信",
421
421
  "feedback.notHelpful": "役に立たない",
@@ -718,5 +718,13 @@ const messages = {
718
718
  "settings.emailChangeError": "確認メールを送信できませんでした。",
719
719
  "settings.emailNewLabel": "新しいメールアドレス",
720
720
  "settings.emailNewPlaceholder": "新しいメールアドレスを入力",
721
+ "usage.builderCredits": "Builder クレジット",
722
+ "usage.estimatedBuilderCredits": "~{{amount}} 推定クレジット",
723
+ "usage.otherUsdSpend": "{{amount}} その他の USD",
724
+ "usage.noBuilderCredits": "Builder クレジット 0",
725
+ "usage.otherUnclassifiedSpend": "その他または未分類の USD 利用額",
726
+ "usage.providerSpendDetail": "Builder 請求対象外のプロバイダー利用または過去の呼び出し",
727
+ "usage.providerSpendToday": "本日のその他または未分類の利用額: {{amount}}",
728
+ "usage.driverCreditsAndUsd": "Builder クレジット / USD",
721
729
  };
722
730
  export default messages;
@@ -415,7 +415,7 @@ const messages = {
415
415
  "errorMessages.providerRateLimit": "현재 모델 제공업체가 이 채팅의 요청 속도를 제한하고 있습니다. 잠시 후 다시 시도하세요.",
416
416
  "errorMessages.providerTransientRejection": "AI 제공업체가 이 요청을 일시적으로 거부했습니다. 보통 1분 이내에 해결되니 다시 시도하세요.",
417
417
  "errorMessages.startNewChat": "새 채팅 시작",
418
- "errorMessages.upgradeAtBuilder": "Builder.io에서 업그레이드",
418
+ "errorMessages.addCreditsInBuilder": "Builder에서 크레딧 추가",
419
419
  "feedback.inaccurate": "부정확함",
420
420
  "feedback.keyboardHint": "보내려면 {{shortcut}} Enter",
421
421
  "feedback.notHelpful": "도움이 되지 않음",
@@ -718,5 +718,13 @@ const messages = {
718
718
  "settings.emailChangeError": "확인 메일을 보내지 못했습니다.",
719
719
  "settings.emailNewLabel": "새 이메일",
720
720
  "settings.emailNewPlaceholder": "새 이메일 입력",
721
+ "usage.builderCredits": "Builder 크레딧",
722
+ "usage.estimatedBuilderCredits": "~{{amount}} 예상 크레딧",
723
+ "usage.otherUsdSpend": "{{amount}} 기타 USD",
724
+ "usage.noBuilderCredits": "Builder 크레딧 0",
725
+ "usage.otherUnclassifiedSpend": "기타 또는 분류되지 않은 USD 사용액",
726
+ "usage.providerSpendDetail": "Builder 청구 외 제공업체 사용 또는 이전 호출",
727
+ "usage.providerSpendToday": "오늘 기타 또는 분류되지 않은 사용량: {{amount}}",
728
+ "usage.driverCreditsAndUsd": "Builder 크레딧 / USD",
721
729
  };
722
730
  export default messages;
@@ -602,7 +602,7 @@ const messages = {
602
602
  "errorMessages.providerRateLimit": "O provedor do modelo está limitando temporariamente este chat. Aguarde um momento e tente novamente.",
603
603
  "errorMessages.providerTransientRejection": "O provedor de IA recusou temporariamente esta solicitação. Isso costuma se resolver em menos de um minuto — tente novamente.",
604
604
  "errorMessages.startNewChat": "Iniciar novo chat",
605
- "errorMessages.upgradeAtBuilder": "Fazer upgrade no Builder.io",
605
+ "errorMessages.addCreditsInBuilder": "Adicionar créditos no Builder",
606
606
  "feedback.inaccurate": "Impreciso",
607
607
  "feedback.keyboardHint": "{{shortcut}} Enter para enviar",
608
608
  "feedback.notHelpful": "Pouco útil",
@@ -732,5 +732,13 @@ const messages = {
732
732
  "settings.emailChangeError": "Não foi possível enviar a confirmação.",
733
733
  "settings.emailNewLabel": "Novo e-mail",
734
734
  "settings.emailNewPlaceholder": "Digite o novo e-mail",
735
+ "usage.builderCredits": "Créditos do Builder",
736
+ "usage.estimatedBuilderCredits": "~{{amount}} créditos estimados",
737
+ "usage.otherUsdSpend": "{{amount}} USD adicional",
738
+ "usage.noBuilderCredits": "0 créditos do Builder",
739
+ "usage.otherUnclassifiedSpend": "Gastos em USD adicionais ou não classificados",
740
+ "usage.providerSpendDetail": "Uso do provedor ou chamadas antigas fora da cobrança do Builder",
741
+ "usage.providerSpendToday": "Uso adicional ou não classificado hoje: {{amount}}",
742
+ "usage.driverCreditsAndUsd": "Créditos do Builder / USD",
735
743
  };
736
744
  export default messages;
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "إلغاء",
38
38
  couldNotRevoke: "تعذر إلغاء الرمز.",
39
39
  authorizeDevice: "تخويل الجهاز",
40
+ fullCatalogRequested: "يطلب هذا الجهاز الوصول إلى كتالوج الإجراءات الكامل.",
40
41
  createToken: "إنشاء رمز اتصال",
41
42
  authorizingDevice: "جارٍ تخويل الجهاز...",
42
43
  creatingToken: "جارٍ إنشاء الرمز...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Widerrufen",
38
38
  couldNotRevoke: "Token konnte nicht widerrufen werden.",
39
39
  authorizeDevice: "Gerät autorisieren",
40
+ fullCatalogRequested: "Dieses Gerät fordert Zugriff auf den vollständigen Aktionskatalog an.",
40
41
  createToken: "Verbindungstoken erstellen",
41
42
  authorizingDevice: "Gerät wird autorisiert...",
42
43
  creatingToken: "Token wird erstellt...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Revoke",
38
38
  couldNotRevoke: "Could not revoke token.",
39
39
  authorizeDevice: "Authorize device",
40
+ fullCatalogRequested: "This device is requesting access to the full action catalog.",
40
41
  createToken: "Create connection token",
41
42
  authorizingDevice: "Authorizing device...",
42
43
  creatingToken: "Creating token...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Revocar",
38
38
  couldNotRevoke: "No se pudo revocar el token.",
39
39
  authorizeDevice: "Autorizar dispositivo",
40
+ fullCatalogRequested: "Este dispositivo solicita acceso al catálogo completo de acciones.",
40
41
  createToken: "Crear token de conexión",
41
42
  authorizingDevice: "Autorizando dispositivo...",
42
43
  creatingToken: "Creando token...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Révoquer",
38
38
  couldNotRevoke: "Impossible de révoquer le jeton.",
39
39
  authorizeDevice: "Autoriser l’appareil",
40
+ fullCatalogRequested: "Cet appareil demande l’accès au catalogue complet des actions.",
40
41
  createToken: "Créer un jeton de connexion",
41
42
  authorizingDevice: "Autorisation de l’appareil...",
42
43
  creatingToken: "Création du jeton...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Revoke करें",
38
38
  couldNotRevoke: "Token revoke नहीं किया जा सका।",
39
39
  authorizeDevice: "डिवाइस को अनुमति दें",
40
+ fullCatalogRequested: "यह डिवाइस पूरे एक्शन कैटलॉग तक पहुंच का अनुरोध कर रहा है।",
40
41
  createToken: "कनेक्शन token बनाएँ",
41
42
  authorizingDevice: "डिवाइस को अनुमति दी जा रही है...",
42
43
  creatingToken: "Token बनाया जा रहा है...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "取り消す",
38
38
  couldNotRevoke: "トークンを取り消せませんでした。",
39
39
  authorizeDevice: "デバイスを承認",
40
+ fullCatalogRequested: "このデバイスは、すべてのアクションカタログへのアクセスを要求しています。",
40
41
  createToken: "接続トークンを作成",
41
42
  authorizingDevice: "デバイスを承認中...",
42
43
  creatingToken: "トークンを作成中...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "취소",
38
38
  couldNotRevoke: "토큰을 취소할 수 없습니다.",
39
39
  authorizeDevice: "기기 승인",
40
+ fullCatalogRequested: "이 기기는 전체 작업 카탈로그에 대한 액세스를 요청하고 있습니다.",
40
41
  createToken: "연결 토큰 생성",
41
42
  authorizingDevice: "기기 승인 중...",
42
43
  creatingToken: "토큰 생성 중...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "Revogar",
38
38
  couldNotRevoke: "Não foi possível revogar o token.",
39
39
  authorizeDevice: "Autorizar dispositivo",
40
+ fullCatalogRequested: "Este dispositivo está solicitando acesso ao catálogo completo de ações.",
40
41
  createToken: "Criar token de conexão",
41
42
  authorizingDevice: "Autorizando dispositivo...",
42
43
  creatingToken: "Criando token...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "撤销",
38
38
  couldNotRevoke: "无法撤销令牌。",
39
39
  authorizeDevice: "授权设备",
40
+ fullCatalogRequested: "此设备正在请求访问完整的操作目录。",
40
41
  createToken: "创建连接令牌",
41
42
  authorizingDevice: "正在授权设备...",
42
43
  creatingToken: "正在创建令牌...",
@@ -37,6 +37,7 @@ export const mcpConnectMessages = {
37
37
  revoke: "撤銷",
38
38
  couldNotRevoke: "無法撤銷權杖。",
39
39
  authorizeDevice: "授權裝置",
40
+ fullCatalogRequested: "此裝置正在要求存取完整的動作目錄。",
40
41
  createToken: "建立連線權杖",
41
42
  authorizingDevice: "正在授權裝置...",
42
43
  creatingToken: "正在建立權杖...",
@@ -415,7 +415,7 @@ const messages = {
415
415
  "errorMessages.providerRateLimit": "模型提供商目前正在限制此聊天的请求频率。请稍等片刻后重试。",
416
416
  "errorMessages.providerTransientRejection": "AI 提供商暂时拒绝了此请求。这种情况通常在一分钟内自行恢复,请重试。",
417
417
  "errorMessages.startNewChat": "开始新聊天",
418
- "errorMessages.upgradeAtBuilder": "在 Builder.io 升级",
418
+ "errorMessages.addCreditsInBuilder": "在 Builder 中添加积分",
419
419
  "feedback.inaccurate": "不准确",
420
420
  "feedback.keyboardHint": "{{shortcut}} Enter 发送",
421
421
  "feedback.notHelpful": "没有帮助",
@@ -718,5 +718,13 @@ const messages = {
718
718
  "settings.emailChangeError": "无法发送确认邮件。",
719
719
  "settings.emailNewLabel": "新电子邮件",
720
720
  "settings.emailNewPlaceholder": "输入新电子邮件",
721
+ "usage.builderCredits": "Builder 积分",
722
+ "usage.estimatedBuilderCredits": "~{{amount}} 预估积分",
723
+ "usage.otherUsdSpend": "{{amount}} 其他 USD",
724
+ "usage.noBuilderCredits": "Builder 积分 0",
725
+ "usage.otherUnclassifiedSpend": "其他或未分类的 USD 支出",
726
+ "usage.providerSpendDetail": "Builder 计费之外的提供商使用量或旧调用",
727
+ "usage.providerSpendToday": "今日其他或未分类使用量:{{amount}}",
728
+ "usage.driverCreditsAndUsd": "Builder 积分 / USD",
721
729
  };
722
730
  export default messages;
@@ -415,7 +415,7 @@ const messages = {
415
415
  "errorMessages.providerRateLimit": "模型供應商目前正在限制這個聊天的要求頻率。請稍候再試。",
416
416
  "errorMessages.providerTransientRejection": "AI 供應商暫時拒絕了這個請求。這種情況通常會在一分鐘內恢復,請重試。",
417
417
  "errorMessages.startNewChat": "開始新聊天",
418
- "errorMessages.upgradeAtBuilder": "在 Builder.io 升級",
418
+ "errorMessages.addCreditsInBuilder": "在 Builder 中新增點數",
419
419
  "feedback.inaccurate": "不準確",
420
420
  "feedback.keyboardHint": "{{shortcut}} Enter 送出",
421
421
  "feedback.notHelpful": "沒有幫助",
@@ -718,5 +718,13 @@ const messages = {
718
718
  "settings.emailChangeError": "無法傳送確認信。",
719
719
  "settings.emailNewLabel": "新電子郵件",
720
720
  "settings.emailNewPlaceholder": "輸入新電子郵件",
721
+ "usage.builderCredits": "Builder 點數",
722
+ "usage.estimatedBuilderCredits": "~{{amount}} 預估點數",
723
+ "usage.otherUsdSpend": "{{amount}} 其他 USD",
724
+ "usage.noBuilderCredits": "Builder 點數 0",
725
+ "usage.otherUnclassifiedSpend": "其他或未分類的 USD 支出",
726
+ "usage.providerSpendDetail": "Builder 計費以外的供應商使用量或舊呼叫",
727
+ "usage.providerSpendToday": "今日其他或未分類的使用量:{{amount}}",
728
+ "usage.driverCreditsAndUsd": "Builder 點數 / USD",
721
729
  };
722
730
  export default messages;
@@ -419,7 +419,7 @@ export declare const englishAgentChatMessages: {
419
419
  readonly "errorMessages.providerRateLimit": "The model provider is rate-limiting this chat right now. Wait a moment, then retry.";
420
420
  readonly "errorMessages.providerTransientRejection": "The AI provider temporarily refused this request. This usually clears within a minute — retry.";
421
421
  readonly "errorMessages.startNewChat": "Start new chat";
422
- readonly "errorMessages.upgradeAtBuilder": "Upgrade at Builder.io";
422
+ readonly "errorMessages.addCreditsInBuilder": "Add credits in Builder";
423
423
  readonly "feedback.inaccurate": "Inaccurate";
424
424
  readonly "feedback.keyboardHint": "{{shortcut}} Enter to send";
425
425
  readonly "feedback.notHelpful": "Not helpful";
@@ -727,6 +727,14 @@ export declare const englishAgentChatMessages: {
727
727
  readonly "settings.emailChangeError": "Could not send confirmation.";
728
728
  readonly "settings.emailNewLabel": "New email";
729
729
  readonly "settings.emailNewPlaceholder": "Enter new email";
730
+ readonly "usage.builderCredits": "Builder credits";
731
+ readonly "usage.estimatedBuilderCredits": "~{{amount}} estimated credits";
732
+ readonly "usage.otherUsdSpend": "{{amount}} other USD";
733
+ readonly "usage.noBuilderCredits": "0 Builder credits";
734
+ readonly "usage.otherUnclassifiedSpend": "Other or unclassified USD spend";
735
+ readonly "usage.providerSpendDetail": "Provider or older calls outside Builder billing";
736
+ readonly "usage.providerSpendToday": "Other or unclassified usage: {{amount}} today";
737
+ readonly "usage.driverCreditsAndUsd": "Builder credits / USD";
730
738
  };
731
739
  type PluralSuffix = "zero" | "one" | "two" | "few" | "many" | "other";
732
740
  type RequiredAgentChatKey = Exclude<keyof typeof englishAgentChatMessages, `${string}_${PluralSuffix}`>;
@@ -24,6 +24,7 @@ export interface McpConnectMessages {
24
24
  revoke: string;
25
25
  couldNotRevoke: string;
26
26
  authorizeDevice: string;
27
+ fullCatalogRequested: string;
27
28
  createToken: string;
28
29
  authorizingDevice: string;
29
30
  creatingToken: string;
@@ -37,7 +37,7 @@ import { getOrgDomain } from "../org/context.js";
37
37
  import { getSession, getConfiguredLoginHtml, isLoopbackRequest, } from "../server/auth.js";
38
38
  import { readBody } from "../server/h3-helpers.js";
39
39
  import { MCP_CONNECT_MCP_URL_TEMPLATE, getMcpConnectGuides, getMcpStaticTokenFallback, interpolateMcpConnectTemplate, resolveMcpConnectGuideId, } from "../shared/mcp-connect-content.js";
40
- import { recordMintedToken, listTokens, revokeToken, normalizeServiceName, serviceIdentityEmail, createDeviceCode, getDeviceCode, approveDeviceCode, consumeDeviceCode, claimDeviceCodeForMint, finishDeviceCodeMint, releaseDeviceCodeMint, expireDeviceCode, MCP_CONNECT_OAUTH_CLIENT_ID, MCP_CONNECT_SCOPE, DEFAULT_TOKEN_TTL_DAYS, MIN_TOKEN_TTL_DAYS, MAX_TOKEN_TTL_DAYS, DEVICE_CODE_TTL_MS, } from "./connect-store.js";
40
+ import { recordMintedToken, listTokens, revokeToken, normalizeServiceName, serviceIdentityEmail, createDeviceCode, getDeviceCode, getDeviceCodeByUserCode, approveDeviceCode, consumeDeviceCode, claimDeviceCodeForMint, finishDeviceCodeMint, releaseDeviceCodeMint, expireDeviceCode, MCP_CONNECT_OAUTH_CLIENT_ID, MCP_CONNECT_SCOPE, DEFAULT_TOKEN_TTL_DAYS, MIN_TOKEN_TTL_DAYS, MAX_TOKEN_TTL_DAYS, DEVICE_CODE_TTL_MS, } from "./connect-store.js";
41
41
  import { MCP_OAUTH_DEFAULT_SCOPE, signMcpOAuthAccessToken, } from "./oauth-token.js";
42
42
  import { MCP_PUBLIC_ROUTE_PREFIX } from "./route-paths.js";
43
43
  /** Device-flow poll interval hint (seconds). */
@@ -267,12 +267,12 @@ function mcpResultPayload(appUrl, options, auth) {
267
267
  headers.Authorization = `Bearer ${auth.token}`;
268
268
  if (!auth.token && auth.ownerEmail) {
269
269
  headers["X-Agent-Native-Owner-Email"] = auth.ownerEmail;
270
+ if (auth.catalogScope === "full") {
271
+ headers["X-Agent-Native-MCP-Full-Catalog"] = "1";
272
+ }
270
273
  }
271
- // Intentionally do NOT inject the full-catalog header here. Every connector
272
- // used to receive it, which silently forced the ~105-tool full catalog on
273
- // every client. Full-catalog intent now lives durably in the token itself
274
- // (`catalog_scope: "full"`, minted only by `connect --full-catalog`), so a
275
- // normal connection defaults to the compact/connector catalog + tool-search.
274
+ // Token-backed scope lives in the signed token; dev-open has no token, so
275
+ // preserve its explicitly requested scope in connector metadata.
276
276
  return {
277
277
  token: auth.token ?? "",
278
278
  mcpUrl,
@@ -339,7 +339,7 @@ function renderConnectGuide(guide, activeGuideId, values, copyLabel) {
339
339
  return `<div class="tab-panel${guide.id === activeGuideId ? " is-active" : ""}" role="tabpanel" id="mcp-guide-panel-${guideId}" aria-labelledby="mcp-guide-tab-${guideId}" data-panel="${guideId}">${content}</div>`;
340
340
  }
341
341
  function renderConnectPage(params) {
342
- const { connectBasePath, email, appName, appUrl, serverId, userCode, locale, requestedGuide, } = params;
342
+ const { connectBasePath, email, appName, appUrl, serverId, userCode, catalogScope, locale, requestedGuide, } = params;
343
343
  const direction = localeDirection(locale);
344
344
  const messages = mcpSettingsMessagesForLocale(locale);
345
345
  const connectMessages = messages.mcpConnect;
@@ -488,6 +488,11 @@ function renderConnectPage(params) {
488
488
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
489
489
  letter-spacing: 0.08em; color: var(--muted);
490
490
  }
491
+ .scope-notice {
492
+ margin: 0 0 0.9rem; padding: 0.65rem 0.75rem;
493
+ border: 1px solid var(--border-strong); border-radius: 8px;
494
+ color: var(--muted); font-size: 0.8rem; line-height: 1.4;
495
+ }
491
496
  button {
492
497
  cursor: pointer; font: inherit; font-weight: 600; border: none;
493
498
  border-radius: 8px; padding: 0.78rem 1rem;
@@ -757,6 +762,8 @@ function renderConnectPage(params) {
757
762
  <span class="value" id="userCodeValue">${safeUserCode}</span>
758
763
  </div>
759
764
 
765
+ ${safeUserCode && catalogScope === "full" ? `<p class="scope-notice">${localize(connectMessages.fullCatalogRequested)}</p>` : ""}
766
+
760
767
  ${setupHtml}
761
768
 
762
769
  ${safeUserCode
@@ -1106,6 +1113,7 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1106
1113
  appUrl,
1107
1114
  serverId: serverName(appUrl, options),
1108
1115
  userCode: null,
1116
+ catalogScope: null,
1109
1117
  locale,
1110
1118
  requestedGuide: requestUrl?.searchParams.get("guide") ?? null,
1111
1119
  }));
@@ -1114,6 +1122,14 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1114
1122
  const raw = requestUrl?.searchParams.get("user_code");
1115
1123
  if (raw && USER_CODE_RE.test(raw))
1116
1124
  userCode = raw;
1125
+ const deviceCode = userCode
1126
+ ? await getDeviceCodeByUserCode(userCode)
1127
+ : null;
1128
+ const catalogScope = deviceCode?.status === "pending" &&
1129
+ deviceCode.expiresAt != null &&
1130
+ deviceCode.expiresAt >= Date.now()
1131
+ ? deviceCode.catalogScope
1132
+ : null;
1117
1133
  return html(renderConnectPage({
1118
1134
  connectBasePath: basePath,
1119
1135
  email: session.email,
@@ -1121,6 +1137,7 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1121
1137
  appUrl,
1122
1138
  serverId: serverName(appUrl, options),
1123
1139
  userCode,
1140
+ catalogScope,
1124
1141
  locale,
1125
1142
  requestedGuide: requestUrl?.searchParams.get("guide") ?? null,
1126
1143
  }));
@@ -1163,7 +1180,23 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1163
1180
  if (method !== "POST")
1164
1181
  return json({ error: "Method not allowed" }, 405);
1165
1182
  try {
1166
- const row = await createDeviceCode();
1183
+ let parsedBody;
1184
+ try {
1185
+ parsedBody = await readBody(event);
1186
+ }
1187
+ catch {
1188
+ return json({ error: "Invalid request body." }, 400);
1189
+ }
1190
+ if (parsedBody != null &&
1191
+ (typeof parsedBody !== "object" || Array.isArray(parsedBody))) {
1192
+ return json({ error: "Invalid request body." }, 400);
1193
+ }
1194
+ const body = (parsedBody ?? {});
1195
+ if (body.fullCatalog !== undefined &&
1196
+ typeof body.fullCatalog !== "boolean") {
1197
+ return json({ error: "fullCatalog must be a boolean." }, 400);
1198
+ }
1199
+ const row = await createDeviceCode(body.fullCatalog === true ? "full" : null);
1167
1200
  const verificationUri = `${appUrl}${MCP_PUBLIC_ROUTE_PREFIX}/connect`;
1168
1201
  return json({
1169
1202
  device_code: row.deviceCode,
@@ -1245,6 +1278,7 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1245
1278
  status: "approved",
1246
1279
  ...mcpResultPayload(appUrl, options, {
1247
1280
  ownerEmail: row.ownerEmail,
1281
+ catalogScope: row.catalogScope,
1248
1282
  }),
1249
1283
  });
1250
1284
  }
@@ -1269,6 +1303,9 @@ export async function handleMcpConnect(event, subpath, options = {}) {
1269
1303
  appUrl,
1270
1304
  expiresIn: `${DEFAULT_TOKEN_TTL_DAYS}d`,
1271
1305
  jti,
1306
+ ...(claimed.catalogScope
1307
+ ? { catalogScope: claimed.catalogScope }
1308
+ : {}),
1272
1309
  });
1273
1310
  await recordMintedToken({
1274
1311
  jti,
@@ -11,10 +11,10 @@
11
11
  * the OAuth 2.0 device-authorization-style CLI flow. Single-use
12
12
  * (`consumed_at`), rate-limited at creation.
13
13
  *
14
- * Mirrors `application-state/store.ts`: lazy `ensureTable()`, `getDbExec()`,
15
- * `isConnectionError()` swallow so a transient Neon WS drop never 500s.
16
- * `CREATE TABLE IF NOT EXISTS` only — strictly additive, never DROP / ALTER
17
- * (shared prod DB rule).
14
+ * Mirrors `application-state/store.ts`: lazy `ensureTable()` and `getDbExec()`.
15
+ * Device-code reads propagate connection errors so unreadable cannot look
16
+ * like an absent authorization. `CREATE TABLE IF NOT EXISTS` only — strictly
17
+ * additive, never DROP / ALTER (shared prod DB rule).
18
18
  */
19
19
  /**
20
20
  * Scope claim that marks a connect-minted token (vs. an ordinary A2A
@@ -146,6 +146,7 @@ export interface DeviceCodeRow {
146
146
  orgId: string | null;
147
147
  status: "pending" | "approved" | "minting" | "consumed" | "expired";
148
148
  tokenJti: string | null;
149
+ catalogScope: "full" | null;
149
150
  createdAt: number | null;
150
151
  expiresAt: number | null;
151
152
  consumedAt: number | null;
@@ -159,8 +160,9 @@ export interface DeviceCodeRow {
159
160
  * Throws `RATE_LIMITED` when the cap is exceeded so the route can map it to a
160
161
  * 429.
161
162
  */
162
- export declare function createDeviceCode(): Promise<DeviceCodeRow>;
163
+ export declare function createDeviceCode(catalogScope?: "full" | null): Promise<DeviceCodeRow>;
163
164
  export declare function getDeviceCode(deviceCode: string): Promise<DeviceCodeRow | null>;
165
+ export declare function getDeviceCodeByUserCode(userCode: string): Promise<DeviceCodeRow | null>;
164
166
  /**
165
167
  * Bind the logged-in user (email + org) to a pending device code, identified
166
168
  * by its human-typable `user_code`. Only transitions a non-expired, still