@agent-native/core 0.92.7 β 0.92.8
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/pure-agent-apps.mdx +22 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builtin.ts +1 -1
- package/corpus/core/src/agent/model-config.ts +30 -30
- package/corpus/core/src/agent/production-agent.ts +129 -7
- package/corpus/core/src/cli/design-connect.ts +438 -83
- package/corpus/core/src/cli/recap.ts +2 -2
- package/corpus/core/src/client/AgentPanel.tsx +8 -1
- package/corpus/core/src/client/agent-chat-adapter.ts +12 -7
- package/corpus/core/src/client/composer/TiptapComposer.tsx +1 -1
- package/corpus/core/src/client/index.ts +4 -0
- package/corpus/core/src/client/org/TeamPage.tsx +41 -26
- package/corpus/core/src/client/use-action.ts +113 -1
- package/corpus/core/src/db/client.ts +12 -2
- package/corpus/core/src/db/create-get-db.ts +4 -1
- package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
- package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
- package/corpus/core/src/server/transcribe-voice.ts +1 -1
- package/corpus/core/src/usage/store.ts +13 -4
- package/corpus/core/src/vite/client.ts +38 -1
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/get-data-program.ts +78 -0
- package/corpus/templates/analytics/actions/list-data-programs.ts +49 -0
- package/corpus/templates/analytics/app/global.css +11 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +163 -17
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +20 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +96 -3
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +61 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +40 -2
- package/corpus/templates/analytics/changelog/2026-07-09-analytics-no-longer-forgets-successful-data-queries-when-a-l.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-keep-consistent-spacing-when-they-stack-ver.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-tables-and-extensions-can-be-selected-and-d.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-long-running-analytics-requests-now-recover-automatically-wh.md +6 -0
- package/corpus/templates/analytics/server/db/index.ts +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +1 -7
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +102 -15
- package/corpus/templates/content/app/hooks/use-content-database.ts +52 -0
- package/corpus/templates/content/app/hooks/use-document-properties.ts +50 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/content/app/i18n-data.ts +28 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-warnings-no-longer-flash-during-normal-synce.md +6 -0
- package/corpus/templates/content/changelog/2026-07-09-property-menus-and-delete-confirmations-now-open-visibly-and.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +130 -28
- package/corpus/templates/design/actions/add-breakpoint.ts +48 -68
- package/corpus/templates/design/actions/add-localhost-screens.ts +496 -61
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +2 -18
- package/corpus/templates/design/actions/apply-design-token-edit.ts +51 -82
- package/corpus/templates/design/actions/apply-tweaks.ts +63 -41
- package/corpus/templates/design/actions/capture-design-state.ts +2 -2
- package/corpus/templates/design/actions/connect-localhost.ts +58 -12
- package/corpus/templates/design/actions/create-component.ts +2 -18
- package/corpus/templates/design/actions/create-design-branch.ts +38 -18
- package/corpus/templates/design/actions/create-fusion-app.ts +15 -11
- package/corpus/templates/design/actions/delete-file.ts +19 -34
- package/corpus/templates/design/actions/deploy-design-preview.ts +59 -27
- package/corpus/templates/design/actions/deploy-fusion-app.ts +22 -15
- package/corpus/templates/design/actions/export-pdf.ts +2 -1
- package/corpus/templates/design/actions/export-zip.ts +9 -3
- package/corpus/templates/design/actions/generate-design.ts +107 -70
- package/corpus/templates/design/actions/get-component-details.ts +2 -18
- package/corpus/templates/design/actions/get-design-branch-diff.ts +2 -3
- package/corpus/templates/design/actions/get-design-surface-index.ts +2 -18
- package/corpus/templates/design/actions/get-design.ts +2 -1
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +7 -1
- package/corpus/templates/design/actions/import-design-tokens.ts +114 -76
- package/corpus/templates/design/actions/index-components.ts +2 -18
- package/corpus/templates/design/actions/list-design-source-capabilities.ts +23 -28
- package/corpus/templates/design/actions/list-local-files.ts +9 -2
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +82 -98
- package/corpus/templates/design/actions/open-component-source.ts +2 -18
- package/corpus/templates/design/actions/open-visual-edit.ts +19 -1
- package/corpus/templates/design/actions/present-design-variants.ts +70 -70
- package/corpus/templates/design/actions/preview-component-prop-edit.ts +4 -14
- package/corpus/templates/design/actions/read-local-file.ts +9 -2
- package/corpus/templates/design/actions/remove-breakpoint.ts +40 -61
- package/corpus/templates/design/actions/rename-screen.ts +425 -0
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +12 -2
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +9 -2
- package/corpus/templates/design/actions/sync-fusion-app.ts +56 -39
- package/corpus/templates/design/actions/update-design.ts +376 -61
- package/corpus/templates/design/actions/update-file.ts +455 -188
- package/corpus/templates/design/actions/write-local-file.ts +10 -2
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +685 -608
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +43 -15
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +576 -2015
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -14
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +263 -25
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +34 -0
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +40 -0
- package/corpus/templates/design/app/components/design/design-canvas/creation.ts +47 -0
- package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +27 -0
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +62 -0
- package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +137 -0
- package/corpus/templates/design/app/components/design/design-canvas/file-drop.ts +10 -0
- package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +23 -0
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +23 -0
- package/corpus/templates/design/app/components/design/design-canvas/iframe-pan.ts +177 -0
- package/corpus/templates/design/app/components/design/design-canvas/motion-types.ts +7 -0
- package/corpus/templates/design/app/components/design/design-canvas/pending-text-edit.ts +62 -0
- package/corpus/templates/design/app/components/design/index.ts +2 -2
- package/corpus/templates/design/app/components/design/multi-screen/canvas-tools.ts +100 -0
- package/corpus/templates/design/app/components/design/multi-screen/coordinate-transforms.ts +81 -0
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +23 -13
- package/corpus/templates/design/app/components/design/multi-screen/culling.ts +238 -19
- package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +424 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +341 -0
- package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +52 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +62 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +283 -0
- package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +272 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +5 -1
- package/corpus/templates/design/app/components/design/multi-screen/wheel-gesture-state.ts +12 -0
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +325 -84
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +15 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +119 -47
- package/corpus/templates/design/app/i18n/zh-TW.ts +9 -0
- package/corpus/templates/design/app/i18n-data.ts +223 -0
- package/corpus/templates/design/app/lib/design-save-outbox.ts +379 -0
- package/corpus/templates/design/app/lib/png-clipboard.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +229 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +918 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +43 -0
- package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +336 -0
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +270 -0
- package/corpus/templates/design/app/pages/design-editor/dom-guards.ts +24 -0
- package/corpus/templates/design/app/pages/design-editor/dom-utils.ts +11 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +20 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +408 -0
- package/corpus/templates/design/app/pages/design-editor/export-capture.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +93 -0
- package/corpus/templates/design/app/pages/design-editor/history.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +185 -0
- package/corpus/templates/design/app/pages/design-editor/motion-state.ts +309 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +438 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +510 -0
- package/corpus/templates/design/app/pages/design-editor/portable-style.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +337 -0
- package/corpus/templates/design/app/pages/design-editor/style-utils.ts +5 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +92 -0
- package/corpus/templates/design/app/pages/design-editor/tweak-save.ts +87 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +36 -0
- package/corpus/templates/design/app/routes/design.$id.tsx +11 -1
- package/corpus/templates/design/changelog/2026-07-09-design-edits-canvas-positions-tools-and-tab-context-now-pers.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-figma-style-shortcuts-drawing-annotations-and-cross-screen-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hand-and-scale-tools-now-keep-their-active-toolbar-identity-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-large-multi-screen-designs-now-stay-responsive-during-long-c.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-drags-now-land-exactly-where-the-insertion-indicator-s.md +6 -0
- package/corpus/templates/design/server/db/index.ts +2 -52
- package/corpus/templates/design/server/db/schema.ts +16 -0
- package/corpus/templates/design/server/lib/design-data-access.ts +70 -0
- package/corpus/templates/design/server/lib/design-data-mutation.ts +249 -0
- package/corpus/templates/design/server/lib/fusion-screens.ts +89 -76
- package/corpus/templates/design/server/lib/import-design-files.ts +76 -35
- package/corpus/templates/design/server/lib/verify-write-grant.ts +7 -2
- package/corpus/templates/design/server/plugins/db.ts +19 -0
- package/corpus/templates/design/server/source-workspace.ts +12 -13
- package/corpus/templates/design/shared/resolve-tweaks.ts +15 -0
- package/corpus/templates/design/shared/screen-rename.ts +42 -0
- package/corpus/templates/design/shared/source-mode.ts +84 -4
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builtin.js +1 -1
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/agent/model-config.d.ts +9 -9
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +30 -30
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +60 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +106 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/design-connect.d.ts +30 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +359 -75
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/recap.js +2 -2
- package/dist/cli/recap.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +10 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +1 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +6 -5
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/use-action.d.ts +32 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +68 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +3 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +7 -2
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +2 -2
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.js +1 -1
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +13 -4
- package/dist/usage/store.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +36 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
- package/docs/content/pr-visual-recap.mdx +3 -3
- package/docs/content/pure-agent-apps.mdx +22 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcribe-voice.js","sourceRoot":"","sources":["../../src/server/transcribe-voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,GAElB,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GAEtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,2BAA2B,EAC3B,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,GAAG,gDAAgD,CAAC;AACrE,MAAM,QAAQ,GAAG,qDAAqD,CAAC;AACvE,MAAM,aAAa,GAAG,iDAAiD,CAAC;AACxE,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAC5C,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AACrD,MAAM,YAAY,GAAG,WAAW,CAAC;AACjC,MAAM,eAAe,GAAG,4CAA4C,CAAC;AACrE,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAC5C,MAAM,eAAe,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,sBAAsB;AAChE,yEAAyE;AACzE,sEAAsE;AACtE,mEAAmE;AACnE,yEAAyE;AACzE,oEAAoE;AACpE,2EAA2E;AAC3E,+DAA+D;AAC/D,MAAM,oBAAoB,GAAG,OAAO,CAAC;AACrC,0EAA0E;AAC1E,yBAAyB;AACzB,MAAM,kCAAkC,GAAG,uBAAuB,CAAC;AAEnE,iEAAiE;AACjE,2EAA2E;AAC3E,yEAAyE;AACzE,uEAAuE;AACvE,wCAAwC;AACxC,wEAAwE;AACxE,0EAA0E;AAC1E,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAC7C,MAAM,UAAU,GAAG,2DAA2D,YAAY,kBAAkB,CAAC;AAE7G;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,KAAc;IACzC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACjD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YACtC,sEAAsE;YACtE,kEAAkE;YAClE,sEAAsE;YACtE,sEAAsE;YACtE,6BAA6B;YAC7B,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACpE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IACE,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;gBAC7D,MAAM,CAAC,QAAQ,KAAK,iBAAiB;gBACrC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAChE,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IACE,MAAM,CAAC,QAAQ,KAAK,OAAO;gBAC3B,CAAC,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,CAAC;gBACpE,MAAM,CAAC,IAAI,KAAK,MAAM;gBACtB,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAChE,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC5D,IAAI,SAAS;QAAE,OAAO,SAAS,KAAK,aAAa,IAAI,SAAS,KAAK,MAAM,CAAC;IAC1E,sEAAsE;IACtE,8EAA8E;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,sBAAsB,CAAC,KAAc;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,GAEX,CAAC;IACd,IAAI,CAAC,GAAG,EAAE,EAAE;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1C,OAAO,UAAU,CAAC,MAAM,CAAC;AAC3B,CAAC;AAED;uEACuE;AACvE,SAAS,eAAe,CACtB,aAA0B,EAC1B,iBAA+B;IAE/B,OAAO,iBAAiB;QACtB,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;QACrD,CAAC,CAAC,aAAa,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;QACjD,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC;YAChC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;QACpD,CAAC;QAED,gEAAgE;QAChE,uEAAuE;QACvE,uEAAuE;QACvE,gCAAgC;QAChC,MAAM,WAAW,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAElD,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QACvD,MAAM,cAAc,GAAG,QAAQ,EAAE,IAAI;YACnC,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACrE,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5C,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC;QAC1D,CAAC;QACD,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;YAC/D,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;QAClD,CAAC;QAED,MAAM,YAAY,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,YAAY,EAAE,IAAI;YACjC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACpE,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QACvE,MAAM,YAAY,GAAG,gBAAgB,EAAE,IAAI;YACzC,CAAC,CAAC,oBAAoB,CAClB,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACpD;YACH,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAI,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,CAC7D,CAAC;QACF,MAAM,YAAY,GAAG,gBAAgB,EAAE,IAAI;YACzC,CAAC,CAAC,qBAAqB,CACnB,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACpD;YACH,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,aAAa,GAAG,uBAAuB,CAAC;YAC5C,YAAY;YACZ,WAAW,EAAE,qBAAqB,CAAC,YAAY,CAAC;SACjD,CAAC,CAAC;QACH,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAE,EAAE,CAC1C,6BAA6B,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;QAE5D,uEAAuE;QACvE,qEAAqE;QACrE,oEAAoE;QACpE,qEAAqE;QACrE,iBAAiB;QACjB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC7D,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;QAC9C,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,EAAE,KAAK;YAC3B,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YAC9C,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,cAAc,GAAG;YACrB,SAAS,EAAE,OAAO,EAAE,KAAK;YACzB,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,SAAS;SAClC,CAAC;QACF,MAAM,kBAAkB,GAAG,KAAK,EAAK,EAAoB,EAAc,EAAE,CACvE,cAAc,CAAC,SAAS;YACtB,CAAC,CAAC,qBAAqB,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3C,CAAC,CAAC,EAAE,EAAE,CAAC;QACX,MAAM,oBAAoB,GAAG,KAAK,IAAI,EAAE,CACtC,kBAAkB,CAAC,GAAG,EAAE,CAAC,2BAA2B,EAAE,CAAC,CAAC;QAC1D,MAAM,+BAA+B,GAAG,CACtC,IAAiD,EACjD,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC;QAC5C,IAAI,YAAgC,CAAC;QACrC,kEAAkE;QAClE,iEAAiE;QACjE,mEAAmE;QACnE,+DAA+D;QAC/D,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;QAChE,+CAA+C;QAC/C,MAAM,YAAY,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC/D,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,IAAI,YAAY,EAAE,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;iBACrC,QAAQ,CAAC,MAAM,CAAC;iBAChB,IAAI,EAAE;iBACN,WAAW,EAAE,CAAC;YACjB,IACE,CAAC,KAAK,MAAM;gBACZ,CAAC,KAAK,SAAS;gBACf,CAAC,KAAK,SAAS;gBACf,CAAC,KAAK,gBAAgB;gBACtB,CAAC,KAAK,QAAQ;gBACd,CAAC,KAAK,QAAQ;gBACd,CAAC,KAAK,MAAM,EACZ,CAAC;gBACD,gBAAgB,GAAG,IAAI,CAAC;gBACxB,YAAY,GAAG,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;gBACxE,YAAY,GACV,KACD,EAAE,QAAQ,CAAC;gBACZ,YAAY,KAAM,KAAkD;oBAClE,EAAE,KAAK,EAAE,QAAQ,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,oEAAoE;QACpE,oEAAoE;QACpE,4BAA4B;QAC5B,IAAI,YAAY,KAAK,SAAS,IAAI,CAAC,cAAc,EAAE,CAAC;YAClD,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EACH,kJAAkJ;aACrJ,CAAC;QACJ,CAAC;QAED,oEAAoE;QACpE,mDAAmD;QACnD,KAAK,UAAU,aAAa,CAAC,GAAW;YACtC,OAAO,CAAC,MAAM,kBAAkB,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QAC3E,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,MAAM,qBAAqB,CAAC;gBACjC,KAAK;gBACL,IAAI,EAAE,cAAc;gBACpB,YAAY,EAAE,aAAa;gBAC3B,WAAW,EAAE,YAAY;gBACzB,YAAY;gBACZ,oBAAoB;gBACpB,kBAAkB;gBAClB,aAAa;gBACb,iBAAiB,EAAE,WAAW;aAC/B,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACzB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC;QACxC,MAAM,UAAU,GAAG,IAAI,UAAU,CAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,EACjB,KAAK,CAAC,IAAI,CAAC,UAAU,EACrB,KAAK,CAAC,IAAI,CAAC,UAAU,CACtB,CAAC;QAEF,IAAI,YAAY,GAAkB,IAAI,CAAC;QAEvC,uEAAuE;QACvE,uEAAuE;QACvE,qEAAqE;QACrE,kEAAkE;QAClE,mEAAmE;QACnE,oDAAoD;QAEpD,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;YACxD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC9B,OAAO;oBACL,KAAK,EACH,4HAA4H;iBAC/H,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC;oBACtC,UAAU;oBACV,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,QAAQ,IAAI,SAAS;oBAC/B,YAAY,EAAE,aAAa;oBAC3B,iBAAiB,EAAE,WAAW;iBAC/B,CAAC,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAC9B,OAAO,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC;gBAC3D,CAAC;gBACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAC3B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC9B,OAAO;oBACL,KAAK,EAAE,gCAAiC,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;iBAChF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;YACpE,MAAM,KAAK,GACT,YAAY,KAAK,gBAAgB;gBAC/B,CAAC,CAAC,2BAA2B;gBAC7B,CAAC,CAAC,SAAS,CAAC;YAChB,IAAI,CAAC,CAAC,MAAM,oBAAoB,EAAE,CAAC,EAAE,CAAC;gBACpC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC9B,OAAO;oBACL,KAAK,EAAE,GAAG,KAAK,kHAAkH;iBAClI,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,+BAA+B,CAAC;oBACnD,UAAU;oBACV,QAAQ,EAAE,IAAI;oBACd,KAAK,EACH,YAAY,KAAK,gBAAgB;wBAC/B,CAAC,CAAC,kCAAkC;wBACpC,CAAC,CAAC,SAAS;oBACf,QAAQ,EAAE,QAAQ,IAAI,SAAS;oBAC/B,YAAY,EAAE,aAAa;iBAC5B,CAAC,CAAC;gBACH,OAAO,EAAE,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YACxD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAI,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvD,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBAC1C,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAC9B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;gBAC5B,CAAC;gBACD,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC9B,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,0BAA0B,OAAO,EAAE,EAAE,CAAC;YAChE,CAAC;QACH,CAAC;QAED,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;YACpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC9B,OAAO;oBACL,KAAK,EACH,wHAAwH;iBAC3H,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,iBAAiB,CAAC;gBAC7B,KAAK;gBACL,QAAQ,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,UAAU;oBACjB,MAAM,EAAE,OAAO;iBAChB;gBACD,UAAU;gBACV,IAAI;gBACJ,QAAQ;gBACR,YAAY,EAAE,aAAa;gBAC3B,WAAW,EAAE,YAAY;gBACzB,iBAAiB,EAAE,WAAW;aAC/B,CAAC,CAAC;QACL,CAAC;QAED,uEAAuE;QAEvE,sEAAsE;QACtE,yEAAyE;QACzE,mEAAmE;QACnE,IAAI,YAAY,KAAK,QAAQ,IAAI,CAAC,MAAM,oBAAoB,EAAE,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,+BAA+B,CAAC;oBACnD,UAAU;oBACV,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,kCAAkC;oBACzC,QAAQ,EAAE,QAAQ,IAAI,SAAS;oBAC/B,YAAY,EAAE,aAAa;iBAC5B,CAAC,CAAC;gBACH,OAAO,EAAE,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YACxD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAI,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvD,kEAAkE;gBAClE,6BAA6B;gBAC7B,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBAC1C,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAC9B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;gBAC5B,CAAC;gBACD,YAAY,GAAG,OAAO,CAAC;YACzB,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,mEAAmE;QACnE,gCAAgC;QAChC,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;YACxD,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC;wBACtC,UAAU;wBACV,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,SAAS;wBACjB,QAAQ,EAAE,QAAQ,IAAI,SAAS;wBAC/B,YAAY,EAAE,aAAa;wBAC3B,iBAAiB,EAAE,WAAW;qBAC/B,CAAC,CAAC;oBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;oBACxC,IAAI,OAAO,EAAE,CAAC;wBACZ,OAAO,CAAC,GAAG,CAAC,+BAA+B,OAAO,CAAC,MAAM,QAAQ,CAAC,CAAC;wBACnE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oBAC3B,CAAC;oBACD,OAAO,CAAC,IAAI,CACV,kFAAkF,CACnF,CAAC;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CACV,yDAAyD,EACxD,GAAa,EAAE,OAAO,IAAI,GAAG,CAC/B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,8DAA8D;QAE9D,sEAAsE;QACtE,sEAAsE;QAEtE,IAAI,QAAQ,GAKD,IAAI,CAAC;QAEhB,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;YACpD,IAAI,OAAO,EAAE,CAAC;gBACZ,QAAQ,GAAG;oBACT,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,UAAU;oBACjB,MAAM,EAAE,OAAO;iBAChB,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;YACxD,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,GAAG;oBACT,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,WAAW;oBACrB,KAAK,EAAE,YAAY;oBACnB,MAAM,EAAE,SAAS;iBAClB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,iBAAiB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACnD,OAAO;gBACL,KAAK,EAAE,YAAY;oBACjB,CAAC,CAAC,iCAAiC,YAAY,6GAA6G;oBAC5J,CAAC,CAAC,8IAA8I;aACnJ,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,iBAAiB,CAAC;YAC7B,KAAK;YACL,QAAQ;YACR,UAAU;YACV,IAAI;YACJ,QAAQ;YACR,YAAY,EAAE,aAAa;YAC3B,WAAW,EAAE,YAAY;YACzB,iBAAiB,EAAE,WAAW;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,iBAAiB,CAAC,EAC/B,KAAK,EACL,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,iBAAiB,GAelB;IACC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,kBAAkB,GAAG,EAAE,CAAC;IAEzC,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CACT,MAAM,EACN,IAAI,IAAI,CAAC,CAAC,UAAsB,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAClD,QAAQ,CACT,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,QAAQ;QAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,YAAY;QAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEtD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,CAAC,MAAM,EAAE,EAAE;YACvD,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACzD,OAAO;gBACL,KAAK,EACH,GAAG,CAAC,MAAM,KAAK,GAAG;oBAChB,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,0DAA0D;oBAC5E,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,wBAAwB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;aAClF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsB,CAAC;QACrD,OAAO;YACL,IAAI,EAAE,6BAA6B,CACjC,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EACxB,WAAW,CACZ,CAAC,IAAI,EAAE;SACT,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EACF,GAAa,EAAE,IAAI,KAAK,YAAY;gBACnC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,4CAA4C;gBAC9D,CAAC,CAAC,mBAAmB,QAAQ,CAAC,IAAI,KAAM,GAAa,EAAE,OAAO,IAAI,GAAG,EAAE;SAC5E,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,EACnC,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,GAWlB;IACC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE,CACrC,6BAA6B,CAAC,KAAK,IAAI,QAAQ,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvE,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC1C,CAAC;IAED,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;QACpE,IAAI,CAAC,CAAC,MAAM,oBAAoB,EAAE,CAAC,EAAE,CAAC;YACpC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EACH,oIAAoI;aACvI,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,CAC5C,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC,CACxE,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,8BAA+B,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;aAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EACH,kEAAkE;aACrE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC;gBACtC,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,iBAAiB;aAClB,CAAC,CAAC;YACH,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,0BAA2B,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;aAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;QACzD,MAAM,OAAO,GACX,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,GAAG,YAAY,4BAA4B,OAAO,qBAAqB;aAC/E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC;gBAC5C,QAAQ,EAAE,YAAY;gBACtB,IAAI,EAAE,QAAQ;gBACd,MAAM;gBACN,YAAY;gBACZ,iBAAiB;aAClB,CAAC,CAAC;YACH,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,GAAG,YAAY,oBAAqB,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;aACnF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,MAAM,oBAAoB,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,CAC5C,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC,CACxE,CAAC;YACF,IAAI,OAAO;gBAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACxD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC;gBACtC,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,iBAAiB;aAClB,CAAC,CAAC;YACH,IAAI,OAAO;gBAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;IACpD,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC;gBAC5C,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,OAAO;gBACf,YAAY;gBACZ,iBAAiB;aAClB,CAAC,CAAC;YACH,IAAI,OAAO;gBAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACxD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC;gBAC5C,QAAQ,EAAE,QAAQ;gBAClB,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,iBAAiB;aAClB,CAAC,CAAC;YACH,IAAI,OAAO;gBAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,iBAAiB,GAKlB;IACC,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5D,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,aAAiC,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC;YACtC,KAAK,EAAE,kCAAkC;YACzC,YAAY,EAAE,wBAAwB,CAAC,YAAY,CAAC;YACpD,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;iBAChE;aACF;YACD,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;YAClE,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/D,WAAW,EAAE,CAAC;SACf,CAAC,EAAE,CAAC;YACH,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;gBAAE,YAAY,IAAI,KAAK,CAAC,IAAI,CAAC;YAC5D,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACvC,SAAS,GAAG,KAAK,CAAC,KAAK;qBACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;qBACtC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;qBACxB,IAAI,CAAC,EAAE,CAAC;qBACR,IAAI,EAAE,CAAC;YACZ,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBACtD,aAAa,GAAG,KAAK,CAAC,KAAK,IAAI,mCAAmC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,OAAO,uBAAuB,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,EAC/B,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,iBAAiB,GAMlB;IACC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE;oBACR;wBACE,KAAK,EAAE;4BACL,EAAE,IAAI,EAAE,wBAAwB,CAAC,YAAY,CAAC,EAAE;4BAChD,EAAE,IAAI,EAAE,sBAAsB,CAAC,IAAI,CAAC,EAAE;yBACvC;qBACF;iBACF;gBACD,gBAAgB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;aACrC,CAAC;YACF,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK;YAClD,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;aACzB,IAAI,CAAC,EAAE,CAAC;aACR,IAAI,EAAE,CAAC;QACV,OAAO,uBAAuB,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,EACrC,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,iBAAiB,GAOlB;IACC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC;IACzE,MAAM,KAAK,GACT,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,MAAM,EAAE;gBACjC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK;gBACL,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,wBAAwB,CAAC,YAAY,CAAC,EAAE;oBACnE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,CAAC,IAAI,CAAC,EAAE;iBACxD;gBACD,WAAW,EAAE,CAAC;aACf,CAAC;YACF,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;QACF,OAAO,uBAAuB,CAC5B,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAClD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,OAAO,CAAC,MAAM,IAAI,oBAAoB;QAAE,OAAO,OAAO,CAAC;IAC3D,sEAAsE;IACtE,0EAA0E;IAC1E,uEAAuE;IACvE,kDAAkD;IAClD,OAAO,CAAC,IAAI,CACV,4CAA4C,OAAO,CAAC,MAAM,kBAAkB,oBAAoB,MAAM,CACvG,CAAC;IACF,MAAM,MAAM,GAAG,oCAAoC,CAAC;IACpD,MAAM,SAAS,GAAG,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACxC,OAAO,CACL,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;QAC3B,MAAM;QACN,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAC1C,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,YAAqB;IACrD,MAAM,MAAM,GAAG,YAAY;QACzB,CAAC,CAAC,4CAA4C,YAAY,EAAE;QAC5D,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;;;;;;;4CAOmC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY;IAC1C,OAAO,6EAA6E,IAAI,iBAAiB,CAAC;AAC5G,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAa;IAC5C,OAAO,KAAK;SACT,IAAI,EAAE;SACN,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;SAChC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC;SAChC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,8BAA8B,CAAC,EACtC,QAAQ,EACR,YAAY,GAIb;IACC,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,kDAAkD,QAAQ,IAAI;QAChE,CAAC,CAAC,sCAAsC,CAAC;IAC3C,MAAM,MAAM,GAAG,YAAY;QACzB,CAAC,CAAC,gEAAgE,YAAY,wIAAwI;QACtN,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,GAAG,IAAI,4EAA4E,MAAM,EAAE,CAAC;AACrG,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,oBAAoB,CAAC,EAClC,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,iBAAiB,GAQlB;IACC,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,8BAA8B,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;IAE1E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE;oBACR;wBACE,KAAK,EAAE;4BACL,EAAE,IAAI,EAAE,MAAM,EAAE;4BAChB;gCACE,UAAU,EAAE;oCACV,QAAQ,EAAE,2BAA2B,CAAC,QAAQ,CAAC;oCAC/C,IAAI,EAAE,MAAM;iCACb;6BACF;yBACF;qBACF;iBACF;gBACD,8DAA8D;gBAC9D,6BAA6B;gBAC7B,gBAAgB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;aACrC,CAAC;YACF,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK;YAC/C,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;aACzB,IAAI,CAAC,EAAE,CAAC;aACR,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAY;IAC/C,sEAAsE;IACtE,2DAA2D;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAiB;IAC3C,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IACD,kEAAkE;IAClE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,KAAK,GAAG,MAAM,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,MAAM,CAAC,YAAY,CAC3B,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CACxD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC","sourcesContent":["/**\n * POST /_agent-native/transcribe-voice\n *\n * Receives an audio blob from the agent sidebar composer and forwards it to\n * the configured transcription provider. Returns `{ text }` on success,\n * `{ error }` on failure.\n *\n * Key resolution order for BYOK providers:\n * 1. Request-scoped encrypted secret (`app_secrets`: user, org, workspace).\n * 2. Env var fallback only outside authenticated request contexts.\n *\n * If no server provider is configured, returns 400 with an error the\n * composer UI can surface (the client falls back to Web Speech when possible).\n *\n * This is a framework route rather than a `defineAction` because multipart\n * audio bodies aren't a clean fit for the action contract (actions are\n * typed JSON-in / JSON-out).\n */\n\nimport {\n defineEventHandler,\n getMethod,\n getRequestHeader,\n readMultipartFormData,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport { createBuilderEngine } from \"../agent/engine/builder-engine.js\";\nimport { appStateGet } from \"../application-state/store.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { transcribeWithBuilder } from \"../transcription/builder-transcription.js\";\nimport {\n applyVoiceContextReplacements,\n buildVoiceGuidanceBlock,\n parseVoiceContextPack,\n voiceContextTermsOnly,\n type VoiceContextPack,\n} from \"../voice/index.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n resolveHasBuilderPrivateKey,\n resolveSecret,\n} from \"./credential-provider.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nconst WHISPER_URL = \"https://api.openai.com/v1/audio/transcriptions\";\nconst GROQ_URL = \"https://api.groq.com/openai/v1/audio/transcriptions\";\nconst GROQ_CHAT_URL = \"https://api.groq.com/openai/v1/chat/completions\";\nconst GROQ_MODEL = \"whisper-large-v3-turbo\";\nconst GROQ_CLEANUP_MODEL = \"llama-3.3-70b-versatile\";\nconst OPENAI_MODEL = \"whisper-1\";\nconst OPENAI_CHAT_URL = \"https://api.openai.com/v1/chat/completions\";\nconst OPENAI_CLEANUP_MODEL = \"gpt-5.4-mini\";\nconst MAX_AUDIO_BYTES = 25 * 1024 * 1024; // Whisper hard limit.\n// Hard cap for the dictation-cleanup text path (`sanitizeTranscriptText`\n// below). This endpoint has no `task` field β it's always the Hold-Fn\n// dictation cleanup pass β but a long session (many minutes across\n// multiple pause-triggered final segments) can still exceed a tight cap.\n// 150k gives real headroom for a long dictation session while still\n// bounding worst-case request size; truncation (when it does happen) keeps\n// both ends of the text instead of silently dropping the tail.\nconst MAX_TRANSCRIPT_CHARS = 150_000;\n// Public Builder transcription model id. The Builder gateway maps this to\n// Gemini 3.1 Flash-Lite.\nconst BUILDER_GEMINI_TRANSCRIPTION_MODEL = \"gemini-3-1-flash-lite\";\n\n// Gemini Flash Lite BYOK path when GEMINI_API_KEY is configured.\n// Gemini accepts inline audio; we just give it the bytes and a \"transcribe\n// this\" prompt and it replies with text. 2.5x faster TTFT than 2.5 Flash\n// per Google's release notes, and noticeably snappier than the Whisper\n// round-trip even on a fast connection.\n// Keep the direct Google AI path on a stable public model id; Builder's\n// managed provider above handles the newer Gemini 3.1 Flash-Lite preview.\nconst GEMINI_MODEL = \"gemini-2.0-flash-lite\";\nconst GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent`;\n\n/**\n * Reject cross-site POSTs. Cookies are `SameSite=None; Secure` over HTTPS so\n * the browser would otherwise attach the session to a forged form submission\n * from evil.com, causing us to spend OpenAI credits on the user's behalf.\n * Same-origin browsers always send `Origin` on POST; if it's missing we fall\n * back to `Sec-Fetch-Site` so Safari's fetch-spec behavior still works.\n */\nfunction isSameOriginRequest(event: H3Event): boolean {\n const host = getRequestHeader(event, \"host\");\n const origin = getRequestHeader(event, \"origin\");\n if (origin && host) {\n try {\n const parsed = new URL(origin);\n if (parsed.host === host) return true;\n // Tauri desktop dev serves the tray WebView from localhost:1420 while\n // the app server lives on the template dev port. Production Tauri\n // WebViews can also send a tauri://localhost origin. Treat only those\n // desktop origins as trusted cross-origin callers; arbitrary websites\n // still fail the CSRF check.\n if (parsed.protocol === \"tauri:\" && parsed.hostname === \"localhost\") {\n return true;\n }\n if (\n (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") &&\n parsed.hostname === \"tauri.localhost\" &&\n (host.startsWith(\"localhost:\") || host.startsWith(\"127.0.0.1:\"))\n ) {\n return true;\n }\n if (\n parsed.protocol === \"http:\" &&\n (parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\") &&\n parsed.port === \"1420\" &&\n (host.startsWith(\"localhost:\") || host.startsWith(\"127.0.0.1:\"))\n ) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n }\n const fetchSite = getRequestHeader(event, \"sec-fetch-site\");\n if (fetchSite) return fetchSite === \"same-origin\" || fetchSite === \"none\";\n // No Origin and no Sec-Fetch-Site: likely a non-browser client (curl,\n // server-side) β safe to allow, CSRF requires a browser with ambient cookies.\n return true;\n}\n\n/**\n * Derive an AbortSignal that fires when the client disconnects mid-request\n * (e.g. the desktop client's own 8s ceiling firing before a provider call's\n * longer timeout). Without this, an abandoned client connection leaves the\n * server-side provider fetch running for its full timeout, burning provider\n * quota/cost on a response nobody will read. `req.on(\"close\", ...)` fires on\n * abnormal/early disconnect in Node's http server; a stray fire after normal\n * completion is a harmless no-op since the response has already been sent.\n * Returns undefined if the underlying Node request isn't available (e.g. a\n * non-Node adapter), so callers fall back to their existing timeout-only\n * signal.\n */\nfunction clientDisconnectSignal(event: H3Event): AbortSignal | undefined {\n const req = event.node?.req as\n | (NodeJS.EventEmitter & { on?: (...args: any[]) => void })\n | undefined;\n if (!req?.on) return undefined;\n const controller = new AbortController();\n req.on(\"close\", () => controller.abort());\n return controller.signal;\n}\n\n/** Combine a provider call's own timeout signal with the request's optional\n * client-disconnect signal so either one aborts the upstream fetch. */\nfunction withClientAbort(\n timeoutSignal: AbortSignal,\n clientAbortSignal?: AbortSignal,\n): AbortSignal {\n return clientAbortSignal\n ? AbortSignal.any([timeoutSignal, clientAbortSignal])\n : timeoutSignal;\n}\n\nexport function createTranscribeVoiceHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n if (!isSameOriginRequest(event)) {\n setResponseStatus(event, 403);\n return { error: \"Cross-origin request rejected\" };\n }\n\n // One client-disconnect signal per request, threaded into every\n // provider-fetch AbortController below via AbortSignal.any so a client\n // giving up early aborts the same upstream fetch instead of leaving it\n // running for its full timeout.\n const clientAbort = clientDisconnectSignal(event);\n\n const parts = await readMultipartFormData(event).catch(() => null);\n const audio = parts?.find((p) => p.name === \"audio\");\n const textPart = parts?.find((p) => p.name === \"text\");\n const transcriptText = textPart?.data\n ? sanitizeTranscriptText(Buffer.from(textPart.data).toString(\"utf8\"))\n : undefined;\n if (!audio?.data?.length && !transcriptText) {\n setResponseStatus(event, 400);\n return { error: \"Missing audio or transcript payload\" };\n }\n if (audio?.data?.length && audio.data.length > MAX_AUDIO_BYTES) {\n setResponseStatus(event, 413);\n return { error: \"Audio too large (max 25 MB)\" };\n }\n\n const languagePart = parts?.find((p) => p.name === \"language\");\n const language = languagePart?.data\n ? Buffer.from(languagePart.data).toString(\"utf8\").trim().slice(0, 8)\n : undefined;\n const instructionsPart = parts?.find((p) => p.name === \"instructions\");\n const instructions = instructionsPart?.data\n ? sanitizeInstructions(\n Buffer.from(instructionsPart.data).toString(\"utf8\"),\n )\n : undefined;\n const voiceContextPart = parts?.find(\n (p) => p.name === \"voiceContext\" || p.name === \"contextPack\",\n );\n const voiceContext = voiceContextPart?.data\n ? parseVoiceContextPack(\n Buffer.from(voiceContextPart.data).toString(\"utf8\"),\n )\n : undefined;\n const voiceGuidance = buildVoiceGuidanceBlock({\n instructions,\n contextPack: voiceContextTermsOnly(voiceContext),\n });\n const applyVoiceContext = (value: string) =>\n applyVoiceContextReplacements(value, voiceContext).trim();\n\n // Resolve provider preference. Per-request \"provider\" form field takes\n // precedence (the desktop client sends it on every dictation press),\n // falling back to the user's stored `voice-transcription-prefs` app\n // state for the agent sidebar composer / web clients that don't send\n // it explicitly.\n const session = await getSession(event).catch(() => null);\n if (!session?.email && process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n const orgCtx = session?.email\n ? await getOrgContext(event).catch(() => null)\n : null;\n const requestContext = {\n userEmail: session?.email,\n orgId: orgCtx?.orgId ?? undefined,\n };\n const withRequestContext = async <T>(fn: () => Promise<T>): Promise<T> =>\n requestContext.userEmail\n ? runWithRequestContext(requestContext, fn)\n : fn();\n const hasBuilderPrivateKey = async () =>\n withRequestContext(() => resolveHasBuilderPrivateKey());\n const transcribeWithBuilderForRequest = (\n opts: Parameters<typeof transcribeWithBuilder>[0],\n ) => withRequestContext(() => transcribeWithBuilder(opts));\n const sessionId = session?.email ?? \"local\";\n let providerPref: string | undefined;\n // CRITICAL: presence of the \"provider\" form field is the explicit\n // signal that the client is making a per-request choice. Even if\n // the value is \"auto\" (β undefined providerPref β fallback chain),\n // we must NOT fall back to app-state's stored preference β the\n // client just told us what it wants. Without this gate, a stale\n // `voice-transcription-prefs.provider = \"browser\"` in app-state\n // (from earlier testing) would override the client's \"auto\" and\n // 400 with \"Voice provider is set to browser\".\n const providerPart = parts?.find((p) => p.name === \"provider\");\n let providerExplicit = false;\n if (providerPart?.data) {\n const v = Buffer.from(providerPart.data)\n .toString(\"utf8\")\n .trim()\n .toLowerCase();\n if (\n v === \"auto\" ||\n v === \"browser\" ||\n v === \"builder\" ||\n v === \"builder-gemini\" ||\n v === \"gemini\" ||\n v === \"openai\" ||\n v === \"groq\"\n ) {\n providerExplicit = true;\n providerPref = v === \"auto\" ? undefined : v;\n }\n }\n if (!providerExplicit) {\n try {\n const prefs = await appStateGet(sessionId, \"voice-transcription-prefs\");\n providerPref = (\n prefs as { provider?: string; value?: { provider?: string } } | null\n )?.provider;\n providerPref ??= (prefs as { value?: { provider?: string } } | null)\n ?.value?.provider;\n } catch {\n /* fall through β default to fallback chain */\n }\n }\n\n // Respect explicit \"browser\" preference β user chose Web Speech API and\n // does not want audio uploaded to any external provider. The client\n // shouldn't hit this endpoint when \"browser\" is selected; this is a\n // defense-in-depth refusal.\n if (providerPref === \"browser\" && !transcriptText) {\n setResponseStatus(event, 400);\n return {\n error:\n 'Voice provider is set to \"browser\" (Web Speech API only). Change the preference in Settings β Voice Transcription to use a server-side provider.',\n };\n }\n\n // Per-user-or-fallback API key resolution. Hoisted up so the Gemini\n // path below can use it without duplicating logic.\n async function resolveApiKey(key: string): Promise<string | undefined> {\n return (await withRequestContext(() => resolveSecret(key))) ?? undefined;\n }\n\n if (transcriptText) {\n return await cleanupTranscriptText({\n event,\n text: transcriptText,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n providerPref,\n hasBuilderPrivateKey,\n withRequestContext,\n resolveApiKey,\n clientAbortSignal: clientAbort,\n });\n }\n\n if (!audio?.data?.length) {\n setResponseStatus(event, 400);\n return { error: \"Missing audio payload\" };\n }\n\n const mime = audio.type || \"audio/webm\";\n const audioBytes = new Uint8Array(\n audio.data.buffer,\n audio.data.byteOffset,\n audio.data.byteLength,\n );\n\n let builderError: string | null = null;\n\n // ββ Strict per-provider preferences βββββββββββββββββββββββββββββββββ\n // When the user explicitly picks a single provider (gemini / builder /\n // groq), we only try that provider and surface its error rather than\n // silently falling through. \"auto\" / undefined keeps the existing\n // fallback chain below. \"openai\" is handled by the chain (it skips\n // earlier providers and lands on the Whisper path).\n\n if (providerPref === \"gemini\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (!geminiKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Gemini is selected but GEMINI_API_KEY is not configured. Add it in Settings β API Keys, or change the provider preference.\",\n };\n }\n try {\n const text = await transcribeWithGemini({\n audioBytes,\n mimeType: mime,\n apiKey: geminiKey,\n language: language || undefined,\n instructions: voiceGuidance,\n clientAbortSignal: clientAbort,\n });\n const trimmed = applyVoiceContext(text);\n if (!trimmed) {\n setResponseStatus(event, 502);\n return { error: \"Gemini returned an empty transcript.\" };\n }\n return { text: trimmed };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Gemini transcription failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"builder\" || providerPref === \"builder-gemini\") {\n const label =\n providerPref === \"builder-gemini\"\n ? \"Builder Gemini Flash-Lite\"\n : \"Builder\";\n if (!(await hasBuilderPrivateKey())) {\n setResponseStatus(event, 400);\n return {\n error: `${label} is selected but Builder.io is not connected. Connect Builder.io in Settings, or change the provider preference.`,\n };\n }\n try {\n const result = await transcribeWithBuilderForRequest({\n audioBytes,\n mimeType: mime,\n model:\n providerPref === \"builder-gemini\"\n ? BUILDER_GEMINI_TRANSCRIPTION_MODEL\n : undefined,\n language: language || undefined,\n instructions: voiceGuidance,\n });\n return { text: applyVoiceContext(result.text ?? \"\") };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n if (message.includes(\"credits exhausted\")) {\n setResponseStatus(event, 402);\n return { error: message };\n }\n setResponseStatus(event, 502);\n return { error: `${label} transcription failed: ${message}` };\n }\n }\n\n if (providerPref === \"groq\") {\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (!groqKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Groq is selected but GROQ_API_KEY is not configured. Add it in Settings β API Keys, or change the provider preference.\",\n };\n }\n return await callWhisperCompat({\n event,\n provider: {\n name: \"groq\",\n endpoint: GROQ_URL,\n model: GROQ_MODEL,\n apiKey: groqKey,\n },\n audioBytes,\n mime,\n language,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n clientAbortSignal: clientAbort,\n });\n }\n\n // ββ Auto / undefined / openai fallback chain ββββββββββββββββββββββββ\n\n // ββ Builder Gemini Flash-Lite path βββββββββββββββββββββββββββββββββ\n // First-priority in auto mode when Builder is connected. This lets users\n // try Gemini 3.1 Flash-Lite without bringing their own Google key.\n if (providerPref !== \"openai\" && (await hasBuilderPrivateKey())) {\n try {\n const result = await transcribeWithBuilderForRequest({\n audioBytes,\n mimeType: mime,\n model: BUILDER_GEMINI_TRANSCRIPTION_MODEL,\n language: language || undefined,\n instructions: voiceGuidance,\n });\n return { text: applyVoiceContext(result.text ?? \"\") };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // Surface 402 (credits exhausted) as a 402 so the client can show\n // a specific upgrade prompt.\n if (message.includes(\"credits exhausted\")) {\n setResponseStatus(event, 402);\n return { error: message };\n }\n builderError = message;\n }\n }\n\n // ββ Gemini Flash Lite BYOK path ββββββββββββββββββββββββββββββββββββ\n // If Builder is unavailable, try a user-provided Gemini key before\n // Whisper-compatible providers.\n if (providerPref !== \"openai\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (geminiKey) {\n try {\n const text = await transcribeWithGemini({\n audioBytes,\n mimeType: mime,\n apiKey: geminiKey,\n language: language || undefined,\n instructions: voiceGuidance,\n clientAbortSignal: clientAbort,\n });\n const trimmed = applyVoiceContext(text);\n if (trimmed) {\n console.log(`[transcribe-voice] Gemini β ${trimmed.length} chars`);\n return { text: trimmed };\n }\n console.warn(\n \"[transcribe-voice] Gemini returned empty text β falling through to next provider\",\n );\n } catch (err) {\n console.warn(\n \"[transcribe-voice] Gemini path failed, falling through:\",\n (err as Error)?.message ?? err,\n );\n }\n }\n }\n\n // If Builder is unavailable, fall through to BYOK providers rather than\n // hard-failing. This mirrors Clips' batch transcription path.\n\n // ββ Groq / OpenAI Whisper-compatible path ββββββββββββββββββββββββββ\n // (resolveApiKey is hoisted above so the Gemini path can use it too.)\n\n let provider: {\n name: \"groq\" | \"openai\";\n endpoint: string;\n model: string;\n apiKey: string;\n } | null = null;\n\n if (providerPref !== \"openai\") {\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (groqKey) {\n provider = {\n name: \"groq\",\n endpoint: GROQ_URL,\n model: GROQ_MODEL,\n apiKey: groqKey,\n };\n }\n }\n if (!provider) {\n const openaiKey = await resolveApiKey(\"OPENAI_API_KEY\");\n if (openaiKey) {\n provider = {\n name: \"openai\",\n endpoint: WHISPER_URL,\n model: OPENAI_MODEL,\n apiKey: openaiKey,\n };\n }\n }\n\n if (!provider) {\n setResponseStatus(event, builderError ? 502 : 400);\n return {\n error: builderError\n ? `Builder transcription failed: ${builderError}. Add GEMINI_API_KEY, GROQ_API_KEY, or OPENAI_API_KEY in Settings β API Keys to enable a fallback provider.`\n : \"No voice transcription provider configured. Connect Builder.io or add GEMINI_API_KEY / GROQ_API_KEY / OPENAI_API_KEY in Settings β API Keys.\",\n };\n }\n\n return await callWhisperCompat({\n event,\n provider,\n audioBytes,\n mime,\n language,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n clientAbortSignal: clientAbort,\n });\n });\n}\n\n/**\n * Posts the audio to a Whisper-compatible OpenAI-style endpoint (Groq or\n * OpenAI itself) and returns `{ text }` / `{ error }` shaped like the\n * other branches in `createTranscribeVoiceHandler`. Hoisted so the\n * strict-Groq preference path and the auto fallback chain share one\n * implementation.\n */\nasync function callWhisperCompat({\n event,\n provider,\n audioBytes,\n mime,\n language,\n instructions,\n contextPack,\n clientAbortSignal,\n}: {\n event: H3Event;\n provider: {\n name: \"groq\" | \"openai\";\n endpoint: string;\n model: string;\n apiKey: string;\n };\n audioBytes: Uint8Array;\n mime: string;\n language?: string;\n instructions?: string;\n contextPack?: VoiceContextPack;\n clientAbortSignal?: AbortSignal;\n}): Promise<{ text: string } | { error: string }> {\n const ext = pickExtension(mime);\n const filename = `composer-voice.${ext}`;\n\n const form = new FormData();\n form.append(\n \"file\",\n new Blob([audioBytes as BlobPart], { type: mime }),\n filename,\n );\n form.append(\"model\", provider.model);\n form.append(\"response_format\", \"json\");\n if (language) form.append(\"language\", language);\n if (instructions) form.append(\"prompt\", instructions);\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 45_000);\n try {\n const res = await fetch(provider.endpoint, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${provider.apiKey}` },\n body: form,\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n setResponseStatus(event, res.status === 401 ? 401 : 502);\n return {\n error:\n res.status === 401\n ? `${provider.name} rejected the API key. Update it in Settings β API Keys.`\n : `${provider.name} transcription error ${res.status}: ${text.slice(0, 300)}`,\n };\n }\n const data = (await res.json()) as { text?: string };\n return {\n text: applyVoiceContextReplacements(\n (data.text ?? \"\").trim(),\n contextPack,\n ).trim(),\n };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error:\n (err as Error)?.name === \"AbortError\"\n ? `${provider.name} transcription timed out after 45 seconds.`\n : `Could not reach ${provider.name}: ${(err as Error)?.message ?? err}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function cleanupTranscriptText({\n event,\n text,\n instructions,\n contextPack,\n providerPref,\n hasBuilderPrivateKey,\n withRequestContext,\n resolveApiKey,\n clientAbortSignal,\n}: {\n event: H3Event;\n text: string;\n instructions?: string;\n contextPack?: VoiceContextPack;\n providerPref?: string;\n hasBuilderPrivateKey: () => Promise<boolean>;\n withRequestContext: <T>(fn: () => Promise<T>) => Promise<T>;\n resolveApiKey: (key: string) => Promise<string | undefined>;\n clientAbortSignal?: AbortSignal;\n}): Promise<{ text: string } | { error: string }> {\n const original = text.trim();\n if (!original) return { text: \"\" };\n const finalizeText = (value: string) =>\n applyVoiceContextReplacements(value || original, contextPack).trim();\n\n if (providerPref === \"browser\") {\n return { text: finalizeText(original) };\n }\n\n if (providerPref === \"builder\" || providerPref === \"builder-gemini\") {\n if (!(await hasBuilderPrivateKey())) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Builder.io cleanup is selected but Builder.io is not connected. Connect Builder.io in Settings, or change the provider preference.\",\n };\n }\n try {\n const cleaned = await withRequestContext(() =>\n cleanupWithBuilder({ text: original, instructions, clientAbortSignal }),\n );\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Builder.io cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"gemini\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (!geminiKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Gemini cleanup is selected but GEMINI_API_KEY is not configured.\",\n };\n }\n try {\n const cleaned = await cleanupWithGemini({\n text: original,\n apiKey: geminiKey,\n instructions,\n clientAbortSignal,\n });\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Gemini cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"openai\" || providerPref === \"groq\") {\n const keyName =\n providerPref === \"openai\" ? \"OPENAI_API_KEY\" : \"GROQ_API_KEY\";\n const apiKey = await resolveApiKey(keyName);\n if (!apiKey) {\n setResponseStatus(event, 400);\n return {\n error: `${providerPref} cleanup is selected but ${keyName} is not configured.`,\n };\n }\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: providerPref,\n text: original,\n apiKey,\n instructions,\n clientAbortSignal,\n });\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `${providerPref} cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (await hasBuilderPrivateKey()) {\n try {\n const cleaned = await withRequestContext(() =>\n cleanupWithBuilder({ text: original, instructions, clientAbortSignal }),\n );\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through to BYOK providers, then raw text.\n }\n }\n\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (geminiKey) {\n try {\n const cleaned = await cleanupWithGemini({\n text: original,\n apiKey: geminiKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (groqKey) {\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: \"groq\",\n text: original,\n apiKey: groqKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n const openaiKey = await resolveApiKey(\"OPENAI_API_KEY\");\n if (openaiKey) {\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: \"openai\",\n text: original,\n apiKey: openaiKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n return { text: finalizeText(original) };\n}\n\nasync function cleanupWithBuilder({\n text,\n instructions,\n clientAbortSignal,\n}: {\n text: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const engine = createBuilderEngine();\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n let streamedText = \"\";\n let finalText = \"\";\n let terminalError: string | undefined;\n try {\n for await (const event of engine.stream({\n model: BUILDER_GEMINI_TRANSCRIPTION_MODEL,\n systemPrompt: buildCleanupSystemPrompt(instructions),\n messages: [\n {\n role: \"user\",\n content: [{ type: \"text\", text: buildCleanupUserPrompt(text) }],\n },\n ],\n tools: [],\n abortSignal: withClientAbort(controller.signal, clientAbortSignal),\n maxOutputTokens: Math.min(4096, Math.max(512, text.length * 2)),\n temperature: 0,\n })) {\n if (event.type === \"text-delta\") streamedText += event.text;\n if (event.type === \"assistant-content\") {\n finalText = event.parts\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n .trim();\n }\n if (event.type === \"stop\" && event.reason === \"error\") {\n terminalError = event.error ?? \"Builder gateway returned an error\";\n }\n }\n } finally {\n clearTimeout(timeout);\n }\n if (terminalError) throw new Error(terminalError);\n return stripTranscriptEnvelope(finalText || streamedText);\n}\n\nasync function cleanupWithGemini({\n text,\n apiKey,\n instructions,\n clientAbortSignal,\n}: {\n text: string;\n apiKey: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n try {\n const res = await fetch(GEMINI_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n { text: buildCleanupSystemPrompt(instructions) },\n { text: buildCleanupUserPrompt(text) },\n ],\n },\n ],\n generationConfig: { temperature: 0 },\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Gemini ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n }>;\n };\n const cleaned = data.candidates?.[0]?.content?.parts\n ?.map((p) => p.text ?? \"\")\n .join(\"\")\n .trim();\n return stripTranscriptEnvelope(cleaned ?? \"\");\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function cleanupWithChatProvider({\n provider,\n text,\n apiKey,\n instructions,\n clientAbortSignal,\n}: {\n provider: \"openai\" | \"groq\";\n text: string;\n apiKey: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n const endpoint = provider === \"openai\" ? OPENAI_CHAT_URL : GROQ_CHAT_URL;\n const model =\n provider === \"openai\" ? OPENAI_CLEANUP_MODEL : GROQ_CLEANUP_MODEL;\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: buildCleanupSystemPrompt(instructions) },\n { role: \"user\", content: buildCleanupUserPrompt(text) },\n ],\n temperature: 0,\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`${provider} ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n return stripTranscriptEnvelope(\n data.choices?.[0]?.message?.content?.trim() ?? \"\",\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction pickExtension(mime: string): string {\n const lower = mime.toLowerCase();\n if (lower.includes(\"mp4\") || lower.includes(\"m4a\")) return \"mp4\";\n if (lower.includes(\"mpeg\") || lower.includes(\"mp3\")) return \"mp3\";\n if (lower.includes(\"ogg\")) return \"ogg\";\n if (lower.includes(\"wav\")) return \"wav\";\n return \"webm\";\n}\n\nfunction sanitizeInstructions(value: string): string | undefined {\n const trimmed = value.replace(/\\0/g, \"\").trim();\n if (!trimmed) return undefined;\n return trimmed.slice(0, 3000);\n}\n\nfunction sanitizeTranscriptText(value: string): string | undefined {\n const trimmed = value.replace(/\\0/g, \"\").trim();\n if (!trimmed) return undefined;\n if (trimmed.length <= MAX_TRANSCRIPT_CHARS) return trimmed;\n // Truncate the middle rather than the tail β losing the end of a long\n // dictation silently (previous behavior) is worse than losing the middle,\n // since users notice a cut-off ending immediately but rarely proofread\n // the entire cleaned output against the original.\n console.warn(\n `[transcribe-voice] transcript truncated: ${trimmed.length} chars exceeds ${MAX_TRANSCRIPT_CHARS} cap`,\n );\n const marker = \"\\n[... transcript truncated ...]\\n\";\n const keepChars = MAX_TRANSCRIPT_CHARS - marker.length;\n const headChars = Math.floor((keepChars * 2) / 3);\n const tailChars = keepChars - headChars;\n return (\n trimmed.slice(0, headChars) +\n marker +\n trimmed.slice(trimmed.length - tailChars)\n );\n}\n\nfunction buildCleanupSystemPrompt(instructions?: string): string {\n const custom = instructions\n ? `\\n\\nUser's custom cleanup instructions:\\n${instructions}`\n : \"\";\n return `You clean up live speech-recognition transcripts before paste.\n\nRules:\n- Preserve the speaker's meaning and voice.\n- Fix obvious recognition mistakes, punctuation, capitalization, spacing, and casing.\n- Remove false starts and filler only when they are clearly not intentional.\n- Do not add facts, explanations, headings, bullets, quotes, or markdown.\n- Output only the cleaned transcript text.${custom}`;\n}\n\nfunction buildCleanupUserPrompt(text: string): string {\n return `Clean up this transcript and return only the final text:\\n\\n<transcript>\\n${text}\\n</transcript>`;\n}\n\nfunction stripTranscriptEnvelope(value: string): string {\n return value\n .trim()\n .replace(/^```(?:text)?\\s*/i, \"\")\n .replace(/\\s*```$/i, \"\")\n .replace(/^[\"β](.*)[\"β]$/s, \"$1\")\n .trim();\n}\n\nfunction buildGeminiTranscriptionPrompt({\n language,\n instructions,\n}: {\n language?: string;\n instructions?: string;\n}): string {\n const base = language\n ? `Transcribe the speech in this audio (language: ${language}).`\n : \"Transcribe the speech in this audio.\";\n const custom = instructions\n ? `\\n\\nAdditional user instructions for transcription cleanup:\\n${instructions}\\n\\nApply these only to formatting, casing, punctuation, vocabulary, and cleanup. Do not add content that is not present in the audio.`\n : \"\";\n return `${base} Output only the transcript text β no preamble, no quotes, no formatting.${custom}`;\n}\n\n/**\n * Transcribe audio via Gemini Flash Lite.\n *\n * Gemini accepts the audio inline as base64 alongside a text prompt; we\n * ask for just the transcript with no preamble. 30s timeout β Gemini is\n * fast and we'd rather fall through to Whisper than wait longer.\n *\n * Gemini's documented audio formats are WAV / MP3 / AIFF / AAC / OGG /\n * FLAC β webm/opus is not officially supported but in practice it\n * accepts webm too. If Gemini rejects it the caller falls through.\n */\nasync function transcribeWithGemini({\n audioBytes,\n mimeType,\n apiKey,\n language,\n instructions,\n clientAbortSignal,\n}: {\n audioBytes: Uint8Array;\n mimeType: string;\n apiKey: string;\n language?: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const base64 = uint8ArrayToBase64(audioBytes);\n const prompt = buildGeminiTranscriptionPrompt({ language, instructions });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n try {\n const res = await fetch(GEMINI_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n { text: prompt },\n {\n inlineData: {\n mimeType: normalizeAudioMimeForGemini(mimeType),\n data: base64,\n },\n },\n ],\n },\n ],\n // Keep generation tight β we want the transcript verbatim, no\n // creative reinterpretation.\n generationConfig: { temperature: 0 },\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Gemini ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n }>;\n };\n const text = data.candidates?.[0]?.content?.parts\n ?.map((p) => p.text ?? \"\")\n .join(\"\")\n .trim();\n return text ?? \"\";\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction normalizeAudioMimeForGemini(mime: string): string {\n // Strip codec parameters β Gemini doesn't need them and some variants\n // (e.g. \"audio/webm;codecs=opus\") are rejected as unknown.\n const lower = mime.toLowerCase().split(\";\")[0].trim();\n if (!lower) return \"audio/webm\";\n return lower;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n // Fallback for non-Node runtimes β chunk to avoid stack overflow.\n let binary = \"\";\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(\n ...bytes.subarray(i, Math.min(i + chunk, bytes.length)),\n );\n }\n return btoa(binary);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transcribe-voice.js","sourceRoot":"","sources":["../../src/server/transcribe-voice.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * POST /_agent-native/transcribe-voice\n *\n * Receives an audio blob from the agent sidebar composer and forwards it to\n * the configured transcription provider. Returns `{ text }` on success,\n * `{ error }` on failure.\n *\n * Key resolution order for BYOK providers:\n * 1. Request-scoped encrypted secret (`app_secrets`: user, org, workspace).\n * 2. Env var fallback only outside authenticated request contexts.\n *\n * If no server provider is configured, returns 400 with an error the\n * composer UI can surface (the client falls back to Web Speech when possible).\n *\n * This is a framework route rather than a `defineAction` because multipart\n * audio bodies aren't a clean fit for the action contract (actions are\n * typed JSON-in / JSON-out).\n */\n\nimport {\n defineEventHandler,\n getMethod,\n getRequestHeader,\n readMultipartFormData,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport { createBuilderEngine } from \"../agent/engine/builder-engine.js\";\nimport { appStateGet } from \"../application-state/store.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { transcribeWithBuilder } from \"../transcription/builder-transcription.js\";\nimport {\n applyVoiceContextReplacements,\n buildVoiceGuidanceBlock,\n parseVoiceContextPack,\n voiceContextTermsOnly,\n type VoiceContextPack,\n} from \"../voice/index.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n resolveHasBuilderPrivateKey,\n resolveSecret,\n} from \"./credential-provider.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nconst WHISPER_URL = \"https://api.openai.com/v1/audio/transcriptions\";\nconst GROQ_URL = \"https://api.groq.com/openai/v1/audio/transcriptions\";\nconst GROQ_CHAT_URL = \"https://api.groq.com/openai/v1/chat/completions\";\nconst GROQ_MODEL = \"whisper-large-v3-turbo\";\nconst GROQ_CLEANUP_MODEL = \"llama-3.3-70b-versatile\";\nconst OPENAI_MODEL = \"whisper-1\";\nconst OPENAI_CHAT_URL = \"https://api.openai.com/v1/chat/completions\";\nconst OPENAI_CLEANUP_MODEL = \"gpt-5.6-luna\";\nconst MAX_AUDIO_BYTES = 25 * 1024 * 1024; // Whisper hard limit.\n// Hard cap for the dictation-cleanup text path (`sanitizeTranscriptText`\n// below). This endpoint has no `task` field β it's always the Hold-Fn\n// dictation cleanup pass β but a long session (many minutes across\n// multiple pause-triggered final segments) can still exceed a tight cap.\n// 150k gives real headroom for a long dictation session while still\n// bounding worst-case request size; truncation (when it does happen) keeps\n// both ends of the text instead of silently dropping the tail.\nconst MAX_TRANSCRIPT_CHARS = 150_000;\n// Public Builder transcription model id. The Builder gateway maps this to\n// Gemini 3.1 Flash-Lite.\nconst BUILDER_GEMINI_TRANSCRIPTION_MODEL = \"gemini-3-1-flash-lite\";\n\n// Gemini Flash Lite BYOK path when GEMINI_API_KEY is configured.\n// Gemini accepts inline audio; we just give it the bytes and a \"transcribe\n// this\" prompt and it replies with text. 2.5x faster TTFT than 2.5 Flash\n// per Google's release notes, and noticeably snappier than the Whisper\n// round-trip even on a fast connection.\n// Keep the direct Google AI path on a stable public model id; Builder's\n// managed provider above handles the newer Gemini 3.1 Flash-Lite preview.\nconst GEMINI_MODEL = \"gemini-2.0-flash-lite\";\nconst GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent`;\n\n/**\n * Reject cross-site POSTs. Cookies are `SameSite=None; Secure` over HTTPS so\n * the browser would otherwise attach the session to a forged form submission\n * from evil.com, causing us to spend OpenAI credits on the user's behalf.\n * Same-origin browsers always send `Origin` on POST; if it's missing we fall\n * back to `Sec-Fetch-Site` so Safari's fetch-spec behavior still works.\n */\nfunction isSameOriginRequest(event: H3Event): boolean {\n const host = getRequestHeader(event, \"host\");\n const origin = getRequestHeader(event, \"origin\");\n if (origin && host) {\n try {\n const parsed = new URL(origin);\n if (parsed.host === host) return true;\n // Tauri desktop dev serves the tray WebView from localhost:1420 while\n // the app server lives on the template dev port. Production Tauri\n // WebViews can also send a tauri://localhost origin. Treat only those\n // desktop origins as trusted cross-origin callers; arbitrary websites\n // still fail the CSRF check.\n if (parsed.protocol === \"tauri:\" && parsed.hostname === \"localhost\") {\n return true;\n }\n if (\n (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") &&\n parsed.hostname === \"tauri.localhost\" &&\n (host.startsWith(\"localhost:\") || host.startsWith(\"127.0.0.1:\"))\n ) {\n return true;\n }\n if (\n parsed.protocol === \"http:\" &&\n (parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\") &&\n parsed.port === \"1420\" &&\n (host.startsWith(\"localhost:\") || host.startsWith(\"127.0.0.1:\"))\n ) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n }\n const fetchSite = getRequestHeader(event, \"sec-fetch-site\");\n if (fetchSite) return fetchSite === \"same-origin\" || fetchSite === \"none\";\n // No Origin and no Sec-Fetch-Site: likely a non-browser client (curl,\n // server-side) β safe to allow, CSRF requires a browser with ambient cookies.\n return true;\n}\n\n/**\n * Derive an AbortSignal that fires when the client disconnects mid-request\n * (e.g. the desktop client's own 8s ceiling firing before a provider call's\n * longer timeout). Without this, an abandoned client connection leaves the\n * server-side provider fetch running for its full timeout, burning provider\n * quota/cost on a response nobody will read. `req.on(\"close\", ...)` fires on\n * abnormal/early disconnect in Node's http server; a stray fire after normal\n * completion is a harmless no-op since the response has already been sent.\n * Returns undefined if the underlying Node request isn't available (e.g. a\n * non-Node adapter), so callers fall back to their existing timeout-only\n * signal.\n */\nfunction clientDisconnectSignal(event: H3Event): AbortSignal | undefined {\n const req = event.node?.req as\n | (NodeJS.EventEmitter & { on?: (...args: any[]) => void })\n | undefined;\n if (!req?.on) return undefined;\n const controller = new AbortController();\n req.on(\"close\", () => controller.abort());\n return controller.signal;\n}\n\n/** Combine a provider call's own timeout signal with the request's optional\n * client-disconnect signal so either one aborts the upstream fetch. */\nfunction withClientAbort(\n timeoutSignal: AbortSignal,\n clientAbortSignal?: AbortSignal,\n): AbortSignal {\n return clientAbortSignal\n ? AbortSignal.any([timeoutSignal, clientAbortSignal])\n : timeoutSignal;\n}\n\nexport function createTranscribeVoiceHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n if (!isSameOriginRequest(event)) {\n setResponseStatus(event, 403);\n return { error: \"Cross-origin request rejected\" };\n }\n\n // One client-disconnect signal per request, threaded into every\n // provider-fetch AbortController below via AbortSignal.any so a client\n // giving up early aborts the same upstream fetch instead of leaving it\n // running for its full timeout.\n const clientAbort = clientDisconnectSignal(event);\n\n const parts = await readMultipartFormData(event).catch(() => null);\n const audio = parts?.find((p) => p.name === \"audio\");\n const textPart = parts?.find((p) => p.name === \"text\");\n const transcriptText = textPart?.data\n ? sanitizeTranscriptText(Buffer.from(textPart.data).toString(\"utf8\"))\n : undefined;\n if (!audio?.data?.length && !transcriptText) {\n setResponseStatus(event, 400);\n return { error: \"Missing audio or transcript payload\" };\n }\n if (audio?.data?.length && audio.data.length > MAX_AUDIO_BYTES) {\n setResponseStatus(event, 413);\n return { error: \"Audio too large (max 25 MB)\" };\n }\n\n const languagePart = parts?.find((p) => p.name === \"language\");\n const language = languagePart?.data\n ? Buffer.from(languagePart.data).toString(\"utf8\").trim().slice(0, 8)\n : undefined;\n const instructionsPart = parts?.find((p) => p.name === \"instructions\");\n const instructions = instructionsPart?.data\n ? sanitizeInstructions(\n Buffer.from(instructionsPart.data).toString(\"utf8\"),\n )\n : undefined;\n const voiceContextPart = parts?.find(\n (p) => p.name === \"voiceContext\" || p.name === \"contextPack\",\n );\n const voiceContext = voiceContextPart?.data\n ? parseVoiceContextPack(\n Buffer.from(voiceContextPart.data).toString(\"utf8\"),\n )\n : undefined;\n const voiceGuidance = buildVoiceGuidanceBlock({\n instructions,\n contextPack: voiceContextTermsOnly(voiceContext),\n });\n const applyVoiceContext = (value: string) =>\n applyVoiceContextReplacements(value, voiceContext).trim();\n\n // Resolve provider preference. Per-request \"provider\" form field takes\n // precedence (the desktop client sends it on every dictation press),\n // falling back to the user's stored `voice-transcription-prefs` app\n // state for the agent sidebar composer / web clients that don't send\n // it explicitly.\n const session = await getSession(event).catch(() => null);\n if (!session?.email && process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n const orgCtx = session?.email\n ? await getOrgContext(event).catch(() => null)\n : null;\n const requestContext = {\n userEmail: session?.email,\n orgId: orgCtx?.orgId ?? undefined,\n };\n const withRequestContext = async <T>(fn: () => Promise<T>): Promise<T> =>\n requestContext.userEmail\n ? runWithRequestContext(requestContext, fn)\n : fn();\n const hasBuilderPrivateKey = async () =>\n withRequestContext(() => resolveHasBuilderPrivateKey());\n const transcribeWithBuilderForRequest = (\n opts: Parameters<typeof transcribeWithBuilder>[0],\n ) => withRequestContext(() => transcribeWithBuilder(opts));\n const sessionId = session?.email ?? \"local\";\n let providerPref: string | undefined;\n // CRITICAL: presence of the \"provider\" form field is the explicit\n // signal that the client is making a per-request choice. Even if\n // the value is \"auto\" (β undefined providerPref β fallback chain),\n // we must NOT fall back to app-state's stored preference β the\n // client just told us what it wants. Without this gate, a stale\n // `voice-transcription-prefs.provider = \"browser\"` in app-state\n // (from earlier testing) would override the client's \"auto\" and\n // 400 with \"Voice provider is set to browser\".\n const providerPart = parts?.find((p) => p.name === \"provider\");\n let providerExplicit = false;\n if (providerPart?.data) {\n const v = Buffer.from(providerPart.data)\n .toString(\"utf8\")\n .trim()\n .toLowerCase();\n if (\n v === \"auto\" ||\n v === \"browser\" ||\n v === \"builder\" ||\n v === \"builder-gemini\" ||\n v === \"gemini\" ||\n v === \"openai\" ||\n v === \"groq\"\n ) {\n providerExplicit = true;\n providerPref = v === \"auto\" ? undefined : v;\n }\n }\n if (!providerExplicit) {\n try {\n const prefs = await appStateGet(sessionId, \"voice-transcription-prefs\");\n providerPref = (\n prefs as { provider?: string; value?: { provider?: string } } | null\n )?.provider;\n providerPref ??= (prefs as { value?: { provider?: string } } | null)\n ?.value?.provider;\n } catch {\n /* fall through β default to fallback chain */\n }\n }\n\n // Respect explicit \"browser\" preference β user chose Web Speech API and\n // does not want audio uploaded to any external provider. The client\n // shouldn't hit this endpoint when \"browser\" is selected; this is a\n // defense-in-depth refusal.\n if (providerPref === \"browser\" && !transcriptText) {\n setResponseStatus(event, 400);\n return {\n error:\n 'Voice provider is set to \"browser\" (Web Speech API only). Change the preference in Settings β Voice Transcription to use a server-side provider.',\n };\n }\n\n // Per-user-or-fallback API key resolution. Hoisted up so the Gemini\n // path below can use it without duplicating logic.\n async function resolveApiKey(key: string): Promise<string | undefined> {\n return (await withRequestContext(() => resolveSecret(key))) ?? undefined;\n }\n\n if (transcriptText) {\n return await cleanupTranscriptText({\n event,\n text: transcriptText,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n providerPref,\n hasBuilderPrivateKey,\n withRequestContext,\n resolveApiKey,\n clientAbortSignal: clientAbort,\n });\n }\n\n if (!audio?.data?.length) {\n setResponseStatus(event, 400);\n return { error: \"Missing audio payload\" };\n }\n\n const mime = audio.type || \"audio/webm\";\n const audioBytes = new Uint8Array(\n audio.data.buffer,\n audio.data.byteOffset,\n audio.data.byteLength,\n );\n\n let builderError: string | null = null;\n\n // ββ Strict per-provider preferences βββββββββββββββββββββββββββββββββ\n // When the user explicitly picks a single provider (gemini / builder /\n // groq), we only try that provider and surface its error rather than\n // silently falling through. \"auto\" / undefined keeps the existing\n // fallback chain below. \"openai\" is handled by the chain (it skips\n // earlier providers and lands on the Whisper path).\n\n if (providerPref === \"gemini\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (!geminiKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Gemini is selected but GEMINI_API_KEY is not configured. Add it in Settings β API Keys, or change the provider preference.\",\n };\n }\n try {\n const text = await transcribeWithGemini({\n audioBytes,\n mimeType: mime,\n apiKey: geminiKey,\n language: language || undefined,\n instructions: voiceGuidance,\n clientAbortSignal: clientAbort,\n });\n const trimmed = applyVoiceContext(text);\n if (!trimmed) {\n setResponseStatus(event, 502);\n return { error: \"Gemini returned an empty transcript.\" };\n }\n return { text: trimmed };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Gemini transcription failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"builder\" || providerPref === \"builder-gemini\") {\n const label =\n providerPref === \"builder-gemini\"\n ? \"Builder Gemini Flash-Lite\"\n : \"Builder\";\n if (!(await hasBuilderPrivateKey())) {\n setResponseStatus(event, 400);\n return {\n error: `${label} is selected but Builder.io is not connected. Connect Builder.io in Settings, or change the provider preference.`,\n };\n }\n try {\n const result = await transcribeWithBuilderForRequest({\n audioBytes,\n mimeType: mime,\n model:\n providerPref === \"builder-gemini\"\n ? BUILDER_GEMINI_TRANSCRIPTION_MODEL\n : undefined,\n language: language || undefined,\n instructions: voiceGuidance,\n });\n return { text: applyVoiceContext(result.text ?? \"\") };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n if (message.includes(\"credits exhausted\")) {\n setResponseStatus(event, 402);\n return { error: message };\n }\n setResponseStatus(event, 502);\n return { error: `${label} transcription failed: ${message}` };\n }\n }\n\n if (providerPref === \"groq\") {\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (!groqKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Groq is selected but GROQ_API_KEY is not configured. Add it in Settings β API Keys, or change the provider preference.\",\n };\n }\n return await callWhisperCompat({\n event,\n provider: {\n name: \"groq\",\n endpoint: GROQ_URL,\n model: GROQ_MODEL,\n apiKey: groqKey,\n },\n audioBytes,\n mime,\n language,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n clientAbortSignal: clientAbort,\n });\n }\n\n // ββ Auto / undefined / openai fallback chain ββββββββββββββββββββββββ\n\n // ββ Builder Gemini Flash-Lite path βββββββββββββββββββββββββββββββββ\n // First-priority in auto mode when Builder is connected. This lets users\n // try Gemini 3.1 Flash-Lite without bringing their own Google key.\n if (providerPref !== \"openai\" && (await hasBuilderPrivateKey())) {\n try {\n const result = await transcribeWithBuilderForRequest({\n audioBytes,\n mimeType: mime,\n model: BUILDER_GEMINI_TRANSCRIPTION_MODEL,\n language: language || undefined,\n instructions: voiceGuidance,\n });\n return { text: applyVoiceContext(result.text ?? \"\") };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // Surface 402 (credits exhausted) as a 402 so the client can show\n // a specific upgrade prompt.\n if (message.includes(\"credits exhausted\")) {\n setResponseStatus(event, 402);\n return { error: message };\n }\n builderError = message;\n }\n }\n\n // ββ Gemini Flash Lite BYOK path ββββββββββββββββββββββββββββββββββββ\n // If Builder is unavailable, try a user-provided Gemini key before\n // Whisper-compatible providers.\n if (providerPref !== \"openai\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (geminiKey) {\n try {\n const text = await transcribeWithGemini({\n audioBytes,\n mimeType: mime,\n apiKey: geminiKey,\n language: language || undefined,\n instructions: voiceGuidance,\n clientAbortSignal: clientAbort,\n });\n const trimmed = applyVoiceContext(text);\n if (trimmed) {\n console.log(`[transcribe-voice] Gemini β ${trimmed.length} chars`);\n return { text: trimmed };\n }\n console.warn(\n \"[transcribe-voice] Gemini returned empty text β falling through to next provider\",\n );\n } catch (err) {\n console.warn(\n \"[transcribe-voice] Gemini path failed, falling through:\",\n (err as Error)?.message ?? err,\n );\n }\n }\n }\n\n // If Builder is unavailable, fall through to BYOK providers rather than\n // hard-failing. This mirrors Clips' batch transcription path.\n\n // ββ Groq / OpenAI Whisper-compatible path ββββββββββββββββββββββββββ\n // (resolveApiKey is hoisted above so the Gemini path can use it too.)\n\n let provider: {\n name: \"groq\" | \"openai\";\n endpoint: string;\n model: string;\n apiKey: string;\n } | null = null;\n\n if (providerPref !== \"openai\") {\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (groqKey) {\n provider = {\n name: \"groq\",\n endpoint: GROQ_URL,\n model: GROQ_MODEL,\n apiKey: groqKey,\n };\n }\n }\n if (!provider) {\n const openaiKey = await resolveApiKey(\"OPENAI_API_KEY\");\n if (openaiKey) {\n provider = {\n name: \"openai\",\n endpoint: WHISPER_URL,\n model: OPENAI_MODEL,\n apiKey: openaiKey,\n };\n }\n }\n\n if (!provider) {\n setResponseStatus(event, builderError ? 502 : 400);\n return {\n error: builderError\n ? `Builder transcription failed: ${builderError}. Add GEMINI_API_KEY, GROQ_API_KEY, or OPENAI_API_KEY in Settings β API Keys to enable a fallback provider.`\n : \"No voice transcription provider configured. Connect Builder.io or add GEMINI_API_KEY / GROQ_API_KEY / OPENAI_API_KEY in Settings β API Keys.\",\n };\n }\n\n return await callWhisperCompat({\n event,\n provider,\n audioBytes,\n mime,\n language,\n instructions: voiceGuidance,\n contextPack: voiceContext,\n clientAbortSignal: clientAbort,\n });\n });\n}\n\n/**\n * Posts the audio to a Whisper-compatible OpenAI-style endpoint (Groq or\n * OpenAI itself) and returns `{ text }` / `{ error }` shaped like the\n * other branches in `createTranscribeVoiceHandler`. Hoisted so the\n * strict-Groq preference path and the auto fallback chain share one\n * implementation.\n */\nasync function callWhisperCompat({\n event,\n provider,\n audioBytes,\n mime,\n language,\n instructions,\n contextPack,\n clientAbortSignal,\n}: {\n event: H3Event;\n provider: {\n name: \"groq\" | \"openai\";\n endpoint: string;\n model: string;\n apiKey: string;\n };\n audioBytes: Uint8Array;\n mime: string;\n language?: string;\n instructions?: string;\n contextPack?: VoiceContextPack;\n clientAbortSignal?: AbortSignal;\n}): Promise<{ text: string } | { error: string }> {\n const ext = pickExtension(mime);\n const filename = `composer-voice.${ext}`;\n\n const form = new FormData();\n form.append(\n \"file\",\n new Blob([audioBytes as BlobPart], { type: mime }),\n filename,\n );\n form.append(\"model\", provider.model);\n form.append(\"response_format\", \"json\");\n if (language) form.append(\"language\", language);\n if (instructions) form.append(\"prompt\", instructions);\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 45_000);\n try {\n const res = await fetch(provider.endpoint, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${provider.apiKey}` },\n body: form,\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n setResponseStatus(event, res.status === 401 ? 401 : 502);\n return {\n error:\n res.status === 401\n ? `${provider.name} rejected the API key. Update it in Settings β API Keys.`\n : `${provider.name} transcription error ${res.status}: ${text.slice(0, 300)}`,\n };\n }\n const data = (await res.json()) as { text?: string };\n return {\n text: applyVoiceContextReplacements(\n (data.text ?? \"\").trim(),\n contextPack,\n ).trim(),\n };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error:\n (err as Error)?.name === \"AbortError\"\n ? `${provider.name} transcription timed out after 45 seconds.`\n : `Could not reach ${provider.name}: ${(err as Error)?.message ?? err}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function cleanupTranscriptText({\n event,\n text,\n instructions,\n contextPack,\n providerPref,\n hasBuilderPrivateKey,\n withRequestContext,\n resolveApiKey,\n clientAbortSignal,\n}: {\n event: H3Event;\n text: string;\n instructions?: string;\n contextPack?: VoiceContextPack;\n providerPref?: string;\n hasBuilderPrivateKey: () => Promise<boolean>;\n withRequestContext: <T>(fn: () => Promise<T>) => Promise<T>;\n resolveApiKey: (key: string) => Promise<string | undefined>;\n clientAbortSignal?: AbortSignal;\n}): Promise<{ text: string } | { error: string }> {\n const original = text.trim();\n if (!original) return { text: \"\" };\n const finalizeText = (value: string) =>\n applyVoiceContextReplacements(value || original, contextPack).trim();\n\n if (providerPref === \"browser\") {\n return { text: finalizeText(original) };\n }\n\n if (providerPref === \"builder\" || providerPref === \"builder-gemini\") {\n if (!(await hasBuilderPrivateKey())) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Builder.io cleanup is selected but Builder.io is not connected. Connect Builder.io in Settings, or change the provider preference.\",\n };\n }\n try {\n const cleaned = await withRequestContext(() =>\n cleanupWithBuilder({ text: original, instructions, clientAbortSignal }),\n );\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Builder.io cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"gemini\") {\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (!geminiKey) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Gemini cleanup is selected but GEMINI_API_KEY is not configured.\",\n };\n }\n try {\n const cleaned = await cleanupWithGemini({\n text: original,\n apiKey: geminiKey,\n instructions,\n clientAbortSignal,\n });\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `Gemini cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (providerPref === \"openai\" || providerPref === \"groq\") {\n const keyName =\n providerPref === \"openai\" ? \"OPENAI_API_KEY\" : \"GROQ_API_KEY\";\n const apiKey = await resolveApiKey(keyName);\n if (!apiKey) {\n setResponseStatus(event, 400);\n return {\n error: `${providerPref} cleanup is selected but ${keyName} is not configured.`,\n };\n }\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: providerPref,\n text: original,\n apiKey,\n instructions,\n clientAbortSignal,\n });\n return { text: finalizeText(cleaned || original) };\n } catch (err) {\n setResponseStatus(event, 502);\n return {\n error: `${providerPref} cleanup failed: ${(err as Error)?.message ?? String(err)}`,\n };\n }\n }\n\n if (await hasBuilderPrivateKey()) {\n try {\n const cleaned = await withRequestContext(() =>\n cleanupWithBuilder({ text: original, instructions, clientAbortSignal }),\n );\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through to BYOK providers, then raw text.\n }\n }\n\n const geminiKey = await resolveApiKey(\"GEMINI_API_KEY\");\n if (geminiKey) {\n try {\n const cleaned = await cleanupWithGemini({\n text: original,\n apiKey: geminiKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n const groqKey = await resolveApiKey(\"GROQ_API_KEY\");\n if (groqKey) {\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: \"groq\",\n text: original,\n apiKey: groqKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n const openaiKey = await resolveApiKey(\"OPENAI_API_KEY\");\n if (openaiKey) {\n try {\n const cleaned = await cleanupWithChatProvider({\n provider: \"openai\",\n text: original,\n apiKey: openaiKey,\n instructions,\n clientAbortSignal,\n });\n if (cleaned) return { text: finalizeText(cleaned) };\n } catch {\n // Fall through.\n }\n }\n\n return { text: finalizeText(original) };\n}\n\nasync function cleanupWithBuilder({\n text,\n instructions,\n clientAbortSignal,\n}: {\n text: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const engine = createBuilderEngine();\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n let streamedText = \"\";\n let finalText = \"\";\n let terminalError: string | undefined;\n try {\n for await (const event of engine.stream({\n model: BUILDER_GEMINI_TRANSCRIPTION_MODEL,\n systemPrompt: buildCleanupSystemPrompt(instructions),\n messages: [\n {\n role: \"user\",\n content: [{ type: \"text\", text: buildCleanupUserPrompt(text) }],\n },\n ],\n tools: [],\n abortSignal: withClientAbort(controller.signal, clientAbortSignal),\n maxOutputTokens: Math.min(4096, Math.max(512, text.length * 2)),\n temperature: 0,\n })) {\n if (event.type === \"text-delta\") streamedText += event.text;\n if (event.type === \"assistant-content\") {\n finalText = event.parts\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n .trim();\n }\n if (event.type === \"stop\" && event.reason === \"error\") {\n terminalError = event.error ?? \"Builder gateway returned an error\";\n }\n }\n } finally {\n clearTimeout(timeout);\n }\n if (terminalError) throw new Error(terminalError);\n return stripTranscriptEnvelope(finalText || streamedText);\n}\n\nasync function cleanupWithGemini({\n text,\n apiKey,\n instructions,\n clientAbortSignal,\n}: {\n text: string;\n apiKey: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n try {\n const res = await fetch(GEMINI_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n { text: buildCleanupSystemPrompt(instructions) },\n { text: buildCleanupUserPrompt(text) },\n ],\n },\n ],\n generationConfig: { temperature: 0 },\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Gemini ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n }>;\n };\n const cleaned = data.candidates?.[0]?.content?.parts\n ?.map((p) => p.text ?? \"\")\n .join(\"\")\n .trim();\n return stripTranscriptEnvelope(cleaned ?? \"\");\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function cleanupWithChatProvider({\n provider,\n text,\n apiKey,\n instructions,\n clientAbortSignal,\n}: {\n provider: \"openai\" | \"groq\";\n text: string;\n apiKey: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8_000);\n const endpoint = provider === \"openai\" ? OPENAI_CHAT_URL : GROQ_CHAT_URL;\n const model =\n provider === \"openai\" ? OPENAI_CLEANUP_MODEL : GROQ_CLEANUP_MODEL;\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: buildCleanupSystemPrompt(instructions) },\n { role: \"user\", content: buildCleanupUserPrompt(text) },\n ],\n temperature: 0,\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`${provider} ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n return stripTranscriptEnvelope(\n data.choices?.[0]?.message?.content?.trim() ?? \"\",\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction pickExtension(mime: string): string {\n const lower = mime.toLowerCase();\n if (lower.includes(\"mp4\") || lower.includes(\"m4a\")) return \"mp4\";\n if (lower.includes(\"mpeg\") || lower.includes(\"mp3\")) return \"mp3\";\n if (lower.includes(\"ogg\")) return \"ogg\";\n if (lower.includes(\"wav\")) return \"wav\";\n return \"webm\";\n}\n\nfunction sanitizeInstructions(value: string): string | undefined {\n const trimmed = value.replace(/\\0/g, \"\").trim();\n if (!trimmed) return undefined;\n return trimmed.slice(0, 3000);\n}\n\nfunction sanitizeTranscriptText(value: string): string | undefined {\n const trimmed = value.replace(/\\0/g, \"\").trim();\n if (!trimmed) return undefined;\n if (trimmed.length <= MAX_TRANSCRIPT_CHARS) return trimmed;\n // Truncate the middle rather than the tail β losing the end of a long\n // dictation silently (previous behavior) is worse than losing the middle,\n // since users notice a cut-off ending immediately but rarely proofread\n // the entire cleaned output against the original.\n console.warn(\n `[transcribe-voice] transcript truncated: ${trimmed.length} chars exceeds ${MAX_TRANSCRIPT_CHARS} cap`,\n );\n const marker = \"\\n[... transcript truncated ...]\\n\";\n const keepChars = MAX_TRANSCRIPT_CHARS - marker.length;\n const headChars = Math.floor((keepChars * 2) / 3);\n const tailChars = keepChars - headChars;\n return (\n trimmed.slice(0, headChars) +\n marker +\n trimmed.slice(trimmed.length - tailChars)\n );\n}\n\nfunction buildCleanupSystemPrompt(instructions?: string): string {\n const custom = instructions\n ? `\\n\\nUser's custom cleanup instructions:\\n${instructions}`\n : \"\";\n return `You clean up live speech-recognition transcripts before paste.\n\nRules:\n- Preserve the speaker's meaning and voice.\n- Fix obvious recognition mistakes, punctuation, capitalization, spacing, and casing.\n- Remove false starts and filler only when they are clearly not intentional.\n- Do not add facts, explanations, headings, bullets, quotes, or markdown.\n- Output only the cleaned transcript text.${custom}`;\n}\n\nfunction buildCleanupUserPrompt(text: string): string {\n return `Clean up this transcript and return only the final text:\\n\\n<transcript>\\n${text}\\n</transcript>`;\n}\n\nfunction stripTranscriptEnvelope(value: string): string {\n return value\n .trim()\n .replace(/^```(?:text)?\\s*/i, \"\")\n .replace(/\\s*```$/i, \"\")\n .replace(/^[\"β](.*)[\"β]$/s, \"$1\")\n .trim();\n}\n\nfunction buildGeminiTranscriptionPrompt({\n language,\n instructions,\n}: {\n language?: string;\n instructions?: string;\n}): string {\n const base = language\n ? `Transcribe the speech in this audio (language: ${language}).`\n : \"Transcribe the speech in this audio.\";\n const custom = instructions\n ? `\\n\\nAdditional user instructions for transcription cleanup:\\n${instructions}\\n\\nApply these only to formatting, casing, punctuation, vocabulary, and cleanup. Do not add content that is not present in the audio.`\n : \"\";\n return `${base} Output only the transcript text β no preamble, no quotes, no formatting.${custom}`;\n}\n\n/**\n * Transcribe audio via Gemini Flash Lite.\n *\n * Gemini accepts the audio inline as base64 alongside a text prompt; we\n * ask for just the transcript with no preamble. 30s timeout β Gemini is\n * fast and we'd rather fall through to Whisper than wait longer.\n *\n * Gemini's documented audio formats are WAV / MP3 / AIFF / AAC / OGG /\n * FLAC β webm/opus is not officially supported but in practice it\n * accepts webm too. If Gemini rejects it the caller falls through.\n */\nasync function transcribeWithGemini({\n audioBytes,\n mimeType,\n apiKey,\n language,\n instructions,\n clientAbortSignal,\n}: {\n audioBytes: Uint8Array;\n mimeType: string;\n apiKey: string;\n language?: string;\n instructions?: string;\n clientAbortSignal?: AbortSignal;\n}): Promise<string> {\n const base64 = uint8ArrayToBase64(audioBytes);\n const prompt = buildGeminiTranscriptionPrompt({ language, instructions });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n try {\n const res = await fetch(GEMINI_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n { text: prompt },\n {\n inlineData: {\n mimeType: normalizeAudioMimeForGemini(mimeType),\n data: base64,\n },\n },\n ],\n },\n ],\n // Keep generation tight β we want the transcript verbatim, no\n // creative reinterpretation.\n generationConfig: { temperature: 0 },\n }),\n signal: withClientAbort(controller.signal, clientAbortSignal),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Gemini ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n }>;\n };\n const text = data.candidates?.[0]?.content?.parts\n ?.map((p) => p.text ?? \"\")\n .join(\"\")\n .trim();\n return text ?? \"\";\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction normalizeAudioMimeForGemini(mime: string): string {\n // Strip codec parameters β Gemini doesn't need them and some variants\n // (e.g. \"audio/webm;codecs=opus\") are rejected as unknown.\n const lower = mime.toLowerCase().split(\";\")[0].trim();\n if (!lower) return \"audio/webm\";\n return lower;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n // Fallback for non-Node runtimes β chunk to avoid stack overflow.\n let binary = \"\";\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(\n ...bytes.subarray(i, Math.min(i + chunk, bytes.length)),\n );\n }\n return btoa(binary);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/usage/store.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAC3D,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,iBAAiB,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,yBAAyB,GAAG,uBAAuB,CAAC;IAC5D,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,EAAE,gBAK/B,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,gBAO1C,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC,gBAAgB,CAIlB;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjE;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/usage/store.ts"],"names":[],"mappings":"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"}
|
package/dist/usage/store.js
CHANGED
|
@@ -63,13 +63,22 @@ const PRICING = [
|
|
|
63
63
|
pricing: { input: 100, output: 500, cacheRead: 10, cacheWrite: 125 },
|
|
64
64
|
},
|
|
65
65
|
// ββ OpenAI / Codex ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
66
|
-
// Published rates as of 2026-
|
|
67
|
-
// and has no separate cache-write token charge, so cacheWrite is 0.
|
|
68
|
-
//
|
|
66
|
+
// Published rates as of 2026-07; OpenAI bills cached input at a discount
|
|
67
|
+
// and has no separate cache-write token charge, so cacheWrite is 0. Sol and
|
|
68
|
+
// Terra have higher large-context rates after 272K tokens; this table tracks
|
|
69
|
+
// the standard rate because usage rows do not preserve request context size.
|
|
69
70
|
{
|
|
70
|
-
match: /gpt-5
|
|
71
|
+
match: /gpt-5[.-]6-sol/i,
|
|
71
72
|
pricing: { input: 500, output: 3000, cacheRead: 50, cacheWrite: 0 },
|
|
72
73
|
},
|
|
74
|
+
{
|
|
75
|
+
match: /gpt-5[.-]6-terra/i,
|
|
76
|
+
pricing: { input: 250, output: 1500, cacheRead: 25, cacheWrite: 0 },
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
match: /gpt-5[.-]6-luna/i,
|
|
80
|
+
pricing: { input: 100, output: 600, cacheRead: 10, cacheWrite: 0 },
|
|
81
|
+
},
|
|
73
82
|
{
|
|
74
83
|
match: /gpt-5/i,
|
|
75
84
|
pricing: { input: 125, output: 1000, cacheRead: 12.5, cacheWrite: 0 },
|
package/dist/usage/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/usage/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAcjE,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAahD,MAAM,CAAC,MAAM,iBAAiB,GAAqB;IACjD,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,iBAAiB;IACxB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,yBAAyB;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAqB;IAC5D,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,yBAAyB;IAChC,UAAU,EAAE,SAAS;IACrB,MAAM,EAAE,uBAAuB;IAC/B,wBAAwB,EAAE,sCAAsC;IAChE,aAAa,EAAE,6BAA6B;CAC7C,CAAC;AAEF,MAAM,UAAU,qBAAqB,CACnC,UAAqC;IAErC,OAAO,UAAU,KAAK,SAAS;QAC7B,CAAC,CAAC,4BAA4B;QAC9B,CAAC,CAAC,iBAAiB,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,GAAG,GAAG,CAAC;IAC5B,MAAM,OAAO,GACX,OAAO;QACP,sCAAsC;QACtC,6BAA6B,CAAC;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAC1C,CAAC;AAED,MAAM,OAAO,GAAoD;IAC/D,8EAA8E;IAC9E,uEAAuE;IACvE;QACE,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;KACzE;IACD,4EAA4E;IAC5E,0EAA0E;IAC1E;QACE,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;KACtE;IACD,oDAAoD;IACpD;QACE,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;KACzE;IACD;QACE,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;KACrE;IACD,+EAA+E;IAC/E,yEAAyE;IACzE,oEAAoE;IACpE,2EAA2E;IAC3E;QACE,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;KACpE;IACD;QACE,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE;KACtE;IACD,+EAA+E;IAC/E,+EAA+E;IAC/E;QACE,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;KACpE;IACD,oDAAoD;IACpD;QACE,KAAK,EAAE,2BAA2B;QAClC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAChE;IACD,iDAAiD;IACjD;QACE,KAAK,EAAE,kBAAkB;QACzB,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;KACpE;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAChE;IACD,+EAA+E;IAC/E,2CAA2C;IAC3C;QACE,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAChE;IACD,kDAAkD;IAClD;QACE,KAAK,EAAE,0BAA0B;QACjC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAC9D;IACD,+EAA+E;IAC/E,iCAAiC;IACjC;QACE,KAAK,EAAE,gBAAgB;QACvB,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAClE;IACD,4CAA4C;IAC5C;QACE,KAAK,EAAE,+BAA+B;QACtC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;KAChE;IACD,6CAA6C;IAC7C;QACE,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;KACtE;CACF,CAAC;AAEF,SAAS,UAAU,CAAC,KAAa;IAC/B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACpD,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,OAAO,CAAC;AAC9C,CAAC;AA2BD,IAAI,YAAuC,CAAC;AAE5C,KAAK,UAAU,gBAAgB;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,CAAC,KAAK,IAAI,EAAE;YACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG;;eAET,OAAO,EAAE;;yBAEC,OAAO,EAAE;0BACR,OAAO,EAAE;8BACL,OAAO,EAAE;+BACR,OAAO,EAAE;4BACZ,OAAO,EAAE;;;;;uBAKd,OAAO,EAAE;;OAEzB,CAAC;YAEF,+EAA+E;YAC/E,MAAM,SAAS,GAA4B;gBACzC,CAAC,mBAAmB,EAAE,GAAG,OAAO,EAAE,qBAAqB,CAAC;gBACxD,CAAC,oBAAoB,EAAE,GAAG,OAAO,EAAE,qBAAqB,CAAC;gBACzD,CAAC,OAAO,EAAE,8BAA8B,CAAC;gBACzC,CAAC,KAAK,EAAE,0BAA0B,CAAC;gBACnC,CAAC,QAAQ,EAAE,0BAA0B,CAAC;aACvC,CAAC;YAEF,IAAI,UAAU,EAAE,EAAE,CAAC;gBACjB,uEAAuE;gBACvE,uEAAuE;gBACvE,uEAAuE;gBACvE,oEAAoE;gBACpE,wEAAwE;gBACxE,yEAAyE;gBACzE,yEAAyE;gBACzE,uEAAuE;gBACvE,oEAAoE;gBACpE,UAAU;gBACV,MAAM,iBAAiB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBAClD,sEAAsE;gBACtE,qDAAqD;gBACrD,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;oBACnC,MAAM,kBAAkB,CACtB,aAAa,EACb,GAAG,EACH,oDAAoD,GAAG,IAAI,GAAG,EAAE,CACjE,CAAC;gBACJ,CAAC;gBACD,0EAA0E;gBAC1E,0EAA0E;gBAC1E,6DAA6D;gBAC7D,MAAM,uBAAuB,CAAC,aAAa,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC7D,qEAAqE;gBACrE,2CAA2C;gBAC3C,MAAM,iBAAiB,CACrB,+BAA+B,EAC/B,mGAAmG,CACpG,CAAC;gBACF,OAAO;YACT,CAAC;YAED,qEAAqE;YACrE,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChC,iEAAiE;YACjE,mEAAmE;YACnE,kEAAkE;YAClE,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,OAAO,CAClB,sCAAsC,GAAG,IAAI,GAAG,EAAE,CACnD,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,iCAAiC;gBACnC,CAAC;YACH,CAAC;YACD,0EAA0E;YAC1E,0EAA0E;YAC1E,6DAA6D;YAC7D,MAAM,uBAAuB,CAAC,aAAa,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,CAClB,mGAAmG,CACpG,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACjB,sDAAsD;YACtD,YAAY,GAAG,SAAS,CAAC;YACzB,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAmB,EACnB,YAAoB,EACpB,KAAa,EACb,eAAe,GAAG,CAAC,EACnB,gBAAgB,GAAG,CAAC;IAEpB,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,aAAa,GACjB,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG;QACzC,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,GAAG;QAC3C,CAAC,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,GAAG,GAAG;QACjD,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC;IACtD,OAAO,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,aAAmC,EACnC,WAAoB,EACpB,YAAqB,EACrB,KAAc;IAEd,MAAM,MAAM,GACV,OAAO,aAAa,KAAK,QAAQ;QAC/B,CAAC,CAAC;YACE,UAAU,EAAE,aAAa;YACzB,WAAW,EAAE,WAAW,IAAI,CAAC;YAC7B,YAAY,EAAE,YAAY,IAAI,CAAC;YAC/B,KAAK,EAAE,KAAK,IAAI,EAAE;SACnB;QACH,CAAC,CAAC,aAAa,CAAC;IAEpB,MAAM,EACJ,UAAU,EACV,WAAW,EAAE,KAAK,EAClB,YAAY,EAAE,MAAM,EACpB,eAAe,GAAG,CAAC,EACnB,gBAAgB,GAAG,CAAC,EACpB,KAAK,EAAE,SAAS,EAChB,KAAK,EACL,GAAG,EACH,KAAK,EACL,aAAa,GACd,GAAG,MAAM,CAAC;IAEX,qEAAqE;IACrE,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,IAAI,CAAC,gBAAgB;QAAE,OAAO;IAEvE,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,WAAW,GACf,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC7D,MAAM,aAAa,GAAG,KAAK,IAAI,MAAM,CAAC;IACtC,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE,CAAC;IAEhC,2EAA2E;IAC3E,yEAAyE;IACzE,yEAAyE;IACzE,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,CAAC,OAAO,CAAC;YACnB,GAAG,EAAE,wDAAwD;YAC7D,IAAI,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;IAED,8EAA8E;IAC9E,yDAAyD;IACzD,MAAM,QAAQ,GACZ,aAAa;QACb,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;IAC7E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAChE,MAAM,MAAM,CAAC,OAAO,CAAC;QACnB,GAAG,EAAE;;kDAEyC;QAC9C,IAAI,EAAE;YACJ,EAAE;YACF,UAAU;YACV,KAAK;YACL,MAAM;YACN,eAAe;YACf,gBAAgB;YAChB,QAAQ;YACR,SAAS;YACT,aAAa;YACb,WAAW;YACX,WAAW;YACX,IAAI,CAAC,GAAG,EAAE;SACX;KACF,CAAC,CAAC;AACL,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACpC,GAAG,EAAE,0FAA0F;QAC/F,IAAI,EAAE,CAAC,UAAU,CAAC;KACnB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,CAAE,IAAI,CAAC,CAAC,CAAwB,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IAClE,OAAO,KAAK,GAAG,GAAG,CAAC;AACrB,CAAC;AAwDD,MAAM,MAAM,GAAG,UAAU,CAAC;AAE1B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA4B;IAE5B,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAE5D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACpC,GAAG,EAAE;;;;;;;iEAOwD;QAC7D,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC;KACpC,CAAC,CAAC;IACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAkC,CAAC;IAEpE,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC;QAClC,GAAG,EAAE,UAAU,GAAG;;;;;;;;;iBASL,GAAG;0BACM;QACtB,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,CAAC,IAAe,EAAiB,EAAE,CACpD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACb,MAAM,GAAG,GAAG,CAA2C,CAAC;QACxD,OAAO;YACL,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACxB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG;YACnC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;YAC7B,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;YACpC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YACtC,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;YACxC,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;SAC1C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACrD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KACjC,CAAC,CAAC;IAEH,yEAAyE;IACzE,uEAAuE;IACvE,sEAAsE;IACtE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACnC,GAAG,EAAE;gDACuC;QAC5C,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC;KACpC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4C,CAAC;IACnE,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAqC,EAAE,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,KAAK,GAAkB,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SAC/C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnB,IAAI;QACJ,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,GAAG;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACtC,GAAG,EAAE;;;;;;eAMM;QACX,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;KAC3B,CAAC,CAAC;IACH,MAAM,MAAM,GACV,UAAU,CAAC,IACZ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;QACjC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC;QAClC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9B,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC;QAC1C,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,CAAC;QAC5C,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,CAAC;QACnD,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,CAAC;QACrD,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,GAAG;KAC9C,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,OAAO,EAAE,iBAAiB;QAC1B,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG;QACtC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAChC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;QACvC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;QACzC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;QAC3C,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;QAC5C,OAAO;QACP,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9B,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Token usage tracking and cost monitoring.\n *\n * Every LLM call made by the framework records a row here so users can\n * see where their spend is going β chat vs automations vs background jobs\n * vs whatever else a template labels its prompts as.\n *\n * Cost is stored as \"centicents\" (1/100th of a cent) for integer precision.\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\n\n/**\n * Per-million-token pricing in cents. Cache read is typically ~10% of\n * input; cache write (5m TTL) is ~125%. Pricing is best-effort β keep\n * this table in sync with Anthropic's published prices.\n */\ninterface ModelPricing {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n}\n\nexport const BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER = 1.25;\nexport const BUILDER_AGENT_CREDITS_PER_USD = 20;\n\nexport type UsageBillingUnit = \"usd\" | \"builder-credits\";\n\nexport interface UsageBillingMode {\n unit: UsageBillingUnit;\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\nexport const USD_USAGE_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nexport const BUILDER_CREDIT_USAGE_BILLING: UsageBillingMode = {\n unit: \"builder-credits\",\n label: \"Builder.io credit spend\",\n shortLabel: \"Credits\",\n source: \"builder-agent-credits\",\n hardCostMarginMultiplier: BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER,\n creditsPerUsd: BUILDER_AGENT_CREDITS_PER_USD,\n};\n\nexport function usageBillingForEngine(\n engineName: string | null | undefined,\n): UsageBillingMode {\n return engineName === \"builder\"\n ? BUILDER_CREDIT_USAGE_BILLING\n : USD_USAGE_BILLING;\n}\n\nexport function builderCreditsFromCostCents(cents: number): number {\n if (!Number.isFinite(cents) || cents <= 0) return 0;\n const dollars = cents / 100;\n const credits =\n dollars *\n BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER *\n BUILDER_AGENT_CREDITS_PER_USD;\n return Math.ceil(credits * 1000) / 1000;\n}\n\nconst PRICING: Array<{ match: RegExp; pricing: ModelPricing }> = [\n // ββ Anthropic ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // claude-fable-5: $10/$50 per MTok (Mythos-class, launched 2026-06-09)\n {\n match: /fable-5/i,\n pricing: { input: 1000, output: 5000, cacheRead: 100, cacheWrite: 1250 },\n },\n // claude-opus-4-8: $5/$25 standard mode (fast mode same as fable-5 $10/$50)\n // Use standard-mode pricing as default; fast-mode is a separate model id.\n {\n match: /opus-4-8/i,\n pricing: { input: 500, output: 2500, cacheRead: 50, cacheWrite: 625 },\n },\n // claude-opus-4-7 and older opus: ~$15/$75 per MTok\n {\n match: /opus/i,\n pricing: { input: 1500, output: 7500, cacheRead: 150, cacheWrite: 1875 },\n },\n {\n match: /haiku/i,\n pricing: { input: 100, output: 500, cacheRead: 10, cacheWrite: 125 },\n },\n // ββ OpenAI / Codex ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Published rates as of 2026-06; OpenAI bills cached input at a discount\n // and has no separate cache-write token charge, so cacheWrite is 0.\n // /gpt-5\\.5/ must precede /gpt-5/ since the latter also matches \"gpt-5.5\".\n {\n match: /gpt-5\\.5/i,\n pricing: { input: 500, output: 3000, cacheRead: 50, cacheWrite: 0 },\n },\n {\n match: /gpt-5/i,\n pricing: { input: 125, output: 1000, cacheRead: 12.5, cacheWrite: 0 },\n },\n // ββ Google Gemini βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Gemini 3 Pro / 3.1 Pro: ~$1.25/$10 per MTok (approximate; verify on billing)\n {\n match: /gemini-3[.-]1-pro/i,\n pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },\n },\n // Gemini 3.5 Flash / 3 Flash: ~$0.15/$0.60 per MTok\n {\n match: /gemini-3[.-][0-9]+-flash/i,\n pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },\n },\n // Gemini 2.5 Pro/Flash (catch-all for older 2.5)\n {\n match: /gemini-2\\.5-pro/i,\n pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },\n },\n {\n match: /gemini-2\\.5-flash/i,\n pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },\n },\n // ββ Groq ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Groq Llama 3.3 70B: $0.59/$0.79 per MTok\n {\n match: /llama-3\\.3-70b/i,\n pricing: { input: 59, output: 79, cacheRead: 0, cacheWrite: 0 },\n },\n // Groq Llama 3.1 8B instant: $0.05/$0.08 per MTok\n {\n match: /llama-3\\.1-8b|llama3-8b/i,\n pricing: { input: 5, output: 8, cacheRead: 0, cacheWrite: 0 },\n },\n // ββ Mistral βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Mistral Large: ~$2/$6 per MTok\n {\n match: /mistral-large/i,\n pricing: { input: 200, output: 600, cacheRead: 0, cacheWrite: 0 },\n },\n // Mistral Small/Medium: ~$0.2/$0.6 per MTok\n {\n match: /mistral-small|mistral-medium/i,\n pricing: { input: 20, output: 60, cacheRead: 0, cacheWrite: 0 },\n },\n // default β sonnet pricing ($3/$15 per MTok)\n {\n match: /.*/,\n pricing: { input: 300, output: 1500, cacheRead: 30, cacheWrite: 375 },\n },\n];\n\nfunction pricingFor(model: string): ModelPricing {\n for (const entry of PRICING) {\n if (entry.match.test(model)) return entry.pricing;\n }\n return PRICING[PRICING.length - 1]!.pricing;\n}\n\nexport interface UsageRecord {\n ownerEmail: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n model: string;\n /** Category for this call β e.g. \"chat\", \"automation\", \"job\", \"custom-agent\". */\n label?: string;\n /** Optional template/app name (e.g. \"mail\"). Falls back to AGENT_APP / APP_NAME env. */\n app?: string;\n /**\n * Stable id of the thing this usage belongs to (e.g. a recap plan id). When\n * set, any prior row(s) with the same (label, refId) are deleted before\n * insert, so re-recording the same run overwrites instead of double-counting.\n */\n refId?: string;\n /**\n * Precomputed cost in centicents (1/100Β’). When provided, it is stored\n * verbatim instead of being derived from tokens β e.g. to mirror a\n * provider-reported dollar cost so two surfaces agree exactly.\n */\n costCentsX100?: number;\n}\n\nlet _initPromise: Promise<void> | undefined;\n\nasync function ensureUsageTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS token_usage (\n id ${intType()} PRIMARY KEY,\n owner_email TEXT NOT NULL,\n input_tokens ${intType()} NOT NULL DEFAULT 0,\n output_tokens ${intType()} NOT NULL DEFAULT 0,\n cache_read_tokens ${intType()} NOT NULL DEFAULT 0,\n cache_write_tokens ${intType()} NOT NULL DEFAULT 0,\n cost_cents_x100 ${intType()} NOT NULL DEFAULT 0,\n model TEXT NOT NULL DEFAULT '',\n label TEXT NOT NULL DEFAULT 'chat',\n app TEXT NOT NULL DEFAULT '',\n ref_id TEXT NOT NULL DEFAULT '',\n created_at ${intType()} NOT NULL\n )\n `;\n\n // Additive columns for older deployments that pre-date the label/cache fields.\n const additions: Array<[string, string]> = [\n [\"cache_read_tokens\", `${intType()} NOT NULL DEFAULT 0`],\n [\"cache_write_tokens\", `${intType()} NOT NULL DEFAULT 0`],\n [\"label\", `TEXT NOT NULL DEFAULT 'chat'`],\n [\"app\", `TEXT NOT NULL DEFAULT ''`],\n [\"ref_id\", `TEXT NOT NULL DEFAULT ''`],\n ];\n\n if (isPostgres()) {\n // Hot path: the `token_usage` table and its index are virtually always\n // already present in production. Issuing `CREATE TABLE`/`ALTER TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely. The ensure* wrappers probe `information_schema`/\n // `pg_indexes` first (plain reads, no lock) and run DDL ONLY for what is\n // actually missing, bounded by a transaction-scoped `lock_timeout`. If a\n // swallowed lock-timeout leaves the schema still missing they RE-PROBE\n // and THROW rather than letting init memoize success against absent\n // schema.\n await ensureTableExists(\"token_usage\", createSql);\n // Add columns on older deployments β guarded so the hot path (columns\n // already present) skips the ACCESS EXCLUSIVE ALTER.\n for (const [col, def] of additions) {\n await ensureColumnExists(\n \"token_usage\",\n col,\n `ALTER TABLE token_usage ADD COLUMN IF NOT EXISTS ${col} ${def}`,\n );\n }\n // Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written per run by recordUsage() overflows int4. Widen\n // it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"token_usage\", [\"created_at\"]);\n // Probe pg_indexes first (no lock) and skip the SHARE-locking CREATE\n // INDEX when the index is already present.\n await ensureIndexExists(\n \"idx_token_usage_owner_created\",\n `CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem β keep the original behaviour.\n await client.execute(createSql);\n // Add columns on older deployments that pre-date the label/cache\n // fields. Each ALTER is wrapped so a dialect without IF NOT EXISTS\n // (SQLite) still makes progress if only some columns are missing.\n for (const [col, def] of additions) {\n try {\n await client.execute(\n `ALTER TABLE token_usage ADD COLUMN ${col} ${def}`,\n );\n } catch {\n // Column already exists β ignore\n }\n }\n // Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written per run by recordUsage() overflows int4. Widen\n // it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"token_usage\", [\"created_at\"]);\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,\n );\n } catch {}\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n/**\n * Calculate cost in centicents (1/100th of a cent).\n * Accepts cache tokens so callers that use prompt caching are priced\n * correctly. Non-cache-aware callers can pass 0 for the cache fields.\n */\nexport function calculateCost(\n inputTokens: number,\n outputTokens: number,\n model: string,\n cacheReadTokens = 0,\n cacheWriteTokens = 0,\n): number {\n const p = pricingFor(model);\n const rawCenticents =\n (inputTokens / 1_000_000) * p.input * 100 +\n (outputTokens / 1_000_000) * p.output * 100 +\n (cacheReadTokens / 1_000_000) * p.cacheRead * 100 +\n (cacheWriteTokens / 1_000_000) * p.cacheWrite * 100;\n return rawCenticents > 0 ? Math.max(1, Math.round(rawCenticents)) : 0;\n}\n\n/**\n * Record token usage from an LLM call.\n *\n * Accepts an object with the full set of fields. A positional overload\n * remains for backward compatibility with the older 4-arg signature.\n */\nexport async function recordUsage(record: UsageRecord): Promise<void>;\nexport async function recordUsage(\n ownerEmail: string,\n inputTokens: number,\n outputTokens: number,\n model: string,\n): Promise<void>;\nexport async function recordUsage(\n recordOrOwner: UsageRecord | string,\n inputTokens?: number,\n outputTokens?: number,\n model?: string,\n): Promise<void> {\n const record: UsageRecord =\n typeof recordOrOwner === \"string\"\n ? {\n ownerEmail: recordOrOwner,\n inputTokens: inputTokens ?? 0,\n outputTokens: outputTokens ?? 0,\n model: model ?? \"\",\n }\n : recordOrOwner;\n\n const {\n ownerEmail,\n inputTokens: inTok,\n outputTokens: outTok,\n cacheReadTokens = 0,\n cacheWriteTokens = 0,\n model: modelName,\n label,\n app,\n refId,\n costCentsX100,\n } = record;\n\n // Skip no-op writes (e.g. a stream aborted before any tokens flowed)\n if (!inTok && !outTok && !cacheReadTokens && !cacheWriteTokens) return;\n\n await ensureUsageTable();\n const client = getDbExec();\n const resolvedApp =\n app ?? process.env.AGENT_APP ?? process.env.APP_NAME ?? \"\";\n const resolvedLabel = label ?? \"chat\";\n const resolvedRef = refId ?? \"\";\n\n // Replace any prior usage for this (label, refId) so re-recording the same\n // run β e.g. a recap regenerated on a PR re-push β overwrites instead of\n // double-counting. No-op when refId is unset (the common per-call path).\n if (resolvedRef) {\n await client.execute({\n sql: `DELETE FROM token_usage WHERE label = ? AND ref_id = ?`,\n args: [resolvedLabel, resolvedRef],\n });\n }\n\n // Prefer an explicit precomputed cost (e.g. a provider-reported dollar cost);\n // otherwise derive it from tokens via the pricing table.\n const costX100 =\n costCentsX100 ??\n calculateCost(inTok, outTok, modelName, cacheReadTokens, cacheWriteTokens);\n const id = Date.now() * 1000 + Math.floor(Math.random() * 1000);\n await client.execute({\n sql: `INSERT INTO token_usage\n (id, owner_email, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, model, label, app, ref_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n ownerEmail,\n inTok,\n outTok,\n cacheReadTokens,\n cacheWriteTokens,\n costX100,\n modelName,\n resolvedLabel,\n resolvedApp,\n resolvedRef,\n Date.now(),\n ],\n });\n}\n\n/** Total cost (in cents) charged against a user, across all time. */\nexport async function getUserUsageCents(ownerEmail: string): Promise<number> {\n await ensureUsageTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT COALESCE(SUM(cost_cents_x100), 0) as total FROM token_usage WHERE owner_email = ?`,\n args: [ownerEmail],\n });\n const total = Number((rows[0] as { total?: number })?.total ?? 0);\n return total / 100;\n}\n\n// βββ Admin / UI queries βββββββββββββββββββββββββββββββββββββββββββββββββ\n\nexport interface UsageSummaryOptions {\n ownerEmail: string;\n /** Inclusive lower bound (ms since epoch). Defaults to 30 days ago. */\n sinceMs?: number;\n}\n\nexport interface UsageBucket {\n key: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n calls: number;\n}\n\nexport interface DailyBucket {\n /** YYYY-MM-DD (UTC) */\n date: string;\n cents: number;\n calls: number;\n}\n\nexport interface UsageRecentEntry {\n id: number;\n createdAt: number;\n label: string;\n app: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n}\n\nexport interface UsageSummary {\n billing?: UsageBillingMode;\n totalCents: number;\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheWriteTokens: number;\n sinceMs: number;\n byLabel: UsageBucket[];\n byModel: UsageBucket[];\n byApp: UsageBucket[];\n byDay: DailyBucket[];\n recent: UsageRecentEntry[];\n}\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Produce an aggregated spend view for the Usage admin panel.\n * Scoped to the passed owner email; the UI always passes the session user.\n */\nexport async function getUsageSummary(\n options: UsageSummaryOptions,\n): Promise<UsageSummary> {\n await ensureUsageTable();\n const client = getDbExec();\n const sinceMs = options.sinceMs ?? Date.now() - 30 * DAY_MS;\n\n const totalRow = await client.execute({\n sql: `SELECT\n COALESCE(SUM(cost_cents_x100), 0) AS cents,\n COUNT(*) AS calls,\n COALESCE(SUM(input_tokens), 0) AS in_tok,\n COALESCE(SUM(output_tokens), 0) AS out_tok,\n COALESCE(SUM(cache_read_tokens), 0) AS cr_tok,\n COALESCE(SUM(cache_write_tokens), 0) AS cw_tok\n FROM token_usage WHERE owner_email = ? AND created_at >= ?`,\n args: [options.ownerEmail, sinceMs],\n });\n const t = (totalRow.rows[0] ?? {}) as Record<string, number | null>;\n\n const bucketSql = (col: string) => ({\n sql: `SELECT ${col} AS k,\n COALESCE(SUM(cost_cents_x100), 0) AS cents,\n COUNT(*) AS calls,\n COALESCE(SUM(input_tokens), 0) AS in_tok,\n COALESCE(SUM(output_tokens), 0) AS out_tok,\n COALESCE(SUM(cache_read_tokens), 0) AS cr_tok,\n COALESCE(SUM(cache_write_tokens), 0) AS cw_tok\n FROM token_usage\n WHERE owner_email = ? AND created_at >= ?\n GROUP BY ${col}\n ORDER BY cents DESC`,\n args: [options.ownerEmail, sinceMs],\n });\n\n const mapBuckets = (rows: unknown[]): UsageBucket[] =>\n rows.map((r) => {\n const row = r as Record<string, number | string | null>;\n return {\n key: String(row.k ?? \"\"),\n cents: Number(row.cents ?? 0) / 100,\n calls: Number(row.calls ?? 0),\n inputTokens: Number(row.in_tok ?? 0),\n outputTokens: Number(row.out_tok ?? 0),\n cacheReadTokens: Number(row.cr_tok ?? 0),\n cacheWriteTokens: Number(row.cw_tok ?? 0),\n };\n });\n\n const [byLabelR, byModelR, byAppR] = await Promise.all([\n client.execute(bucketSql(\"label\")),\n client.execute(bucketSql(\"model\")),\n client.execute(bucketSql(\"app\")),\n ]);\n\n // By-day aggregation β done in JS so we don't depend on dialect-specific\n // date functions (SQLite `strftime`, Postgres `to_char`). Cheap enough\n // for a 30-day window; if this grows, swap for a dialect-aware query.\n const dayRows = await client.execute({\n sql: `SELECT created_at, cost_cents_x100 FROM token_usage\n WHERE owner_email = ? AND created_at >= ?`,\n args: [options.ownerEmail, sinceMs],\n });\n const dayMap = new Map<string, { cents: number; calls: number }>();\n for (const row of dayRows.rows as Array<Record<string, number>>) {\n const date = new Date(Number(row.created_at)).toISOString().slice(0, 10);\n const prev = dayMap.get(date) ?? { cents: 0, calls: 0 };\n prev.cents += Number(row.cost_cents_x100 ?? 0);\n prev.calls += 1;\n dayMap.set(date, prev);\n }\n const byDay: DailyBucket[] = [...dayMap.entries()]\n .map(([date, v]) => ({\n date,\n cents: v.cents / 100,\n calls: v.calls,\n }))\n .sort((a, b) => a.date.localeCompare(b.date));\n\n const recentRows = await client.execute({\n sql: `SELECT id, created_at, label, app, model,\n input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,\n cost_cents_x100\n FROM token_usage\n WHERE owner_email = ?\n ORDER BY created_at DESC\n LIMIT 50`,\n args: [options.ownerEmail],\n });\n const recent: UsageRecentEntry[] = (\n recentRows.rows as Array<Record<string, number | string | null>>\n ).map((row) => ({\n id: Number(row.id),\n createdAt: Number(row.created_at),\n label: String(row.label ?? \"chat\"),\n app: String(row.app ?? \"\"),\n model: String(row.model ?? \"\"),\n inputTokens: Number(row.input_tokens ?? 0),\n outputTokens: Number(row.output_tokens ?? 0),\n cacheReadTokens: Number(row.cache_read_tokens ?? 0),\n cacheWriteTokens: Number(row.cache_write_tokens ?? 0),\n cents: Number(row.cost_cents_x100 ?? 0) / 100,\n }));\n\n return {\n billing: USD_USAGE_BILLING,\n totalCents: Number(t.cents ?? 0) / 100,\n totalCalls: Number(t.calls ?? 0),\n totalInputTokens: Number(t.in_tok ?? 0),\n totalOutputTokens: Number(t.out_tok ?? 0),\n totalCacheReadTokens: Number(t.cr_tok ?? 0),\n totalCacheWriteTokens: Number(t.cw_tok ?? 0),\n sinceMs,\n byLabel: mapBuckets(byLabelR.rows),\n byModel: mapBuckets(byModelR.rows),\n byApp: mapBuckets(byAppR.rows),\n byDay,\n recent,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/usage/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Token usage tracking and cost monitoring.\n *\n * Every LLM call made by the framework records a row here so users can\n * see where their spend is going β chat vs automations vs background jobs\n * vs whatever else a template labels its prompts as.\n *\n * Cost is stored as \"centicents\" (1/100th of a cent) for integer precision.\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\n\n/**\n * Per-million-token pricing in cents. Cache read is typically ~10% of\n * input; cache write (5m TTL) is ~125%. Pricing is best-effort β keep\n * this table in sync with Anthropic's published prices.\n */\ninterface ModelPricing {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n}\n\nexport const BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER = 1.25;\nexport const BUILDER_AGENT_CREDITS_PER_USD = 20;\n\nexport type UsageBillingUnit = \"usd\" | \"builder-credits\";\n\nexport interface UsageBillingMode {\n unit: UsageBillingUnit;\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\nexport const USD_USAGE_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nexport const BUILDER_CREDIT_USAGE_BILLING: UsageBillingMode = {\n unit: \"builder-credits\",\n label: \"Builder.io credit spend\",\n shortLabel: \"Credits\",\n source: \"builder-agent-credits\",\n hardCostMarginMultiplier: BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER,\n creditsPerUsd: BUILDER_AGENT_CREDITS_PER_USD,\n};\n\nexport function usageBillingForEngine(\n engineName: string | null | undefined,\n): UsageBillingMode {\n return engineName === \"builder\"\n ? BUILDER_CREDIT_USAGE_BILLING\n : USD_USAGE_BILLING;\n}\n\nexport function builderCreditsFromCostCents(cents: number): number {\n if (!Number.isFinite(cents) || cents <= 0) return 0;\n const dollars = cents / 100;\n const credits =\n dollars *\n BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER *\n BUILDER_AGENT_CREDITS_PER_USD;\n return Math.ceil(credits * 1000) / 1000;\n}\n\nconst PRICING: Array<{ match: RegExp; pricing: ModelPricing }> = [\n // ββ Anthropic ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // claude-fable-5: $10/$50 per MTok (Mythos-class, launched 2026-06-09)\n {\n match: /fable-5/i,\n pricing: { input: 1000, output: 5000, cacheRead: 100, cacheWrite: 1250 },\n },\n // claude-opus-4-8: $5/$25 standard mode (fast mode same as fable-5 $10/$50)\n // Use standard-mode pricing as default; fast-mode is a separate model id.\n {\n match: /opus-4-8/i,\n pricing: { input: 500, output: 2500, cacheRead: 50, cacheWrite: 625 },\n },\n // claude-opus-4-7 and older opus: ~$15/$75 per MTok\n {\n match: /opus/i,\n pricing: { input: 1500, output: 7500, cacheRead: 150, cacheWrite: 1875 },\n },\n {\n match: /haiku/i,\n pricing: { input: 100, output: 500, cacheRead: 10, cacheWrite: 125 },\n },\n // ββ OpenAI / Codex ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Published rates as of 2026-07; OpenAI bills cached input at a discount\n // and has no separate cache-write token charge, so cacheWrite is 0. Sol and\n // Terra have higher large-context rates after 272K tokens; this table tracks\n // the standard rate because usage rows do not preserve request context size.\n {\n match: /gpt-5[.-]6-sol/i,\n pricing: { input: 500, output: 3000, cacheRead: 50, cacheWrite: 0 },\n },\n {\n match: /gpt-5[.-]6-terra/i,\n pricing: { input: 250, output: 1500, cacheRead: 25, cacheWrite: 0 },\n },\n {\n match: /gpt-5[.-]6-luna/i,\n pricing: { input: 100, output: 600, cacheRead: 10, cacheWrite: 0 },\n },\n {\n match: /gpt-5/i,\n pricing: { input: 125, output: 1000, cacheRead: 12.5, cacheWrite: 0 },\n },\n // ββ Google Gemini βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Gemini 3 Pro / 3.1 Pro: ~$1.25/$10 per MTok (approximate; verify on billing)\n {\n match: /gemini-3[.-]1-pro/i,\n pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },\n },\n // Gemini 3.5 Flash / 3 Flash: ~$0.15/$0.60 per MTok\n {\n match: /gemini-3[.-][0-9]+-flash/i,\n pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },\n },\n // Gemini 2.5 Pro/Flash (catch-all for older 2.5)\n {\n match: /gemini-2\\.5-pro/i,\n pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },\n },\n {\n match: /gemini-2\\.5-flash/i,\n pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },\n },\n // ββ Groq ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Groq Llama 3.3 70B: $0.59/$0.79 per MTok\n {\n match: /llama-3\\.3-70b/i,\n pricing: { input: 59, output: 79, cacheRead: 0, cacheWrite: 0 },\n },\n // Groq Llama 3.1 8B instant: $0.05/$0.08 per MTok\n {\n match: /llama-3\\.1-8b|llama3-8b/i,\n pricing: { input: 5, output: 8, cacheRead: 0, cacheWrite: 0 },\n },\n // ββ Mistral βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n // Mistral Large: ~$2/$6 per MTok\n {\n match: /mistral-large/i,\n pricing: { input: 200, output: 600, cacheRead: 0, cacheWrite: 0 },\n },\n // Mistral Small/Medium: ~$0.2/$0.6 per MTok\n {\n match: /mistral-small|mistral-medium/i,\n pricing: { input: 20, output: 60, cacheRead: 0, cacheWrite: 0 },\n },\n // default β sonnet pricing ($3/$15 per MTok)\n {\n match: /.*/,\n pricing: { input: 300, output: 1500, cacheRead: 30, cacheWrite: 375 },\n },\n];\n\nfunction pricingFor(model: string): ModelPricing {\n for (const entry of PRICING) {\n if (entry.match.test(model)) return entry.pricing;\n }\n return PRICING[PRICING.length - 1]!.pricing;\n}\n\nexport interface UsageRecord {\n ownerEmail: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n model: string;\n /** Category for this call β e.g. \"chat\", \"automation\", \"job\", \"custom-agent\". */\n label?: string;\n /** Optional template/app name (e.g. \"mail\"). Falls back to AGENT_APP / APP_NAME env. */\n app?: string;\n /**\n * Stable id of the thing this usage belongs to (e.g. a recap plan id). When\n * set, any prior row(s) with the same (label, refId) are deleted before\n * insert, so re-recording the same run overwrites instead of double-counting.\n */\n refId?: string;\n /**\n * Precomputed cost in centicents (1/100Β’). When provided, it is stored\n * verbatim instead of being derived from tokens β e.g. to mirror a\n * provider-reported dollar cost so two surfaces agree exactly.\n */\n costCentsX100?: number;\n}\n\nlet _initPromise: Promise<void> | undefined;\n\nasync function ensureUsageTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS token_usage (\n id ${intType()} PRIMARY KEY,\n owner_email TEXT NOT NULL,\n input_tokens ${intType()} NOT NULL DEFAULT 0,\n output_tokens ${intType()} NOT NULL DEFAULT 0,\n cache_read_tokens ${intType()} NOT NULL DEFAULT 0,\n cache_write_tokens ${intType()} NOT NULL DEFAULT 0,\n cost_cents_x100 ${intType()} NOT NULL DEFAULT 0,\n model TEXT NOT NULL DEFAULT '',\n label TEXT NOT NULL DEFAULT 'chat',\n app TEXT NOT NULL DEFAULT '',\n ref_id TEXT NOT NULL DEFAULT '',\n created_at ${intType()} NOT NULL\n )\n `;\n\n // Additive columns for older deployments that pre-date the label/cache fields.\n const additions: Array<[string, string]> = [\n [\"cache_read_tokens\", `${intType()} NOT NULL DEFAULT 0`],\n [\"cache_write_tokens\", `${intType()} NOT NULL DEFAULT 0`],\n [\"label\", `TEXT NOT NULL DEFAULT 'chat'`],\n [\"app\", `TEXT NOT NULL DEFAULT ''`],\n [\"ref_id\", `TEXT NOT NULL DEFAULT ''`],\n ];\n\n if (isPostgres()) {\n // Hot path: the `token_usage` table and its index are virtually always\n // already present in production. Issuing `CREATE TABLE`/`ALTER TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely. The ensure* wrappers probe `information_schema`/\n // `pg_indexes` first (plain reads, no lock) and run DDL ONLY for what is\n // actually missing, bounded by a transaction-scoped `lock_timeout`. If a\n // swallowed lock-timeout leaves the schema still missing they RE-PROBE\n // and THROW rather than letting init memoize success against absent\n // schema.\n await ensureTableExists(\"token_usage\", createSql);\n // Add columns on older deployments β guarded so the hot path (columns\n // already present) skips the ACCESS EXCLUSIVE ALTER.\n for (const [col, def] of additions) {\n await ensureColumnExists(\n \"token_usage\",\n col,\n `ALTER TABLE token_usage ADD COLUMN IF NOT EXISTS ${col} ${def}`,\n );\n }\n // Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written per run by recordUsage() overflows int4. Widen\n // it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"token_usage\", [\"created_at\"]);\n // Probe pg_indexes first (no lock) and skip the SHARE-locking CREATE\n // INDEX when the index is already present.\n await ensureIndexExists(\n \"idx_token_usage_owner_created\",\n `CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem β keep the original behaviour.\n await client.execute(createSql);\n // Add columns on older deployments that pre-date the label/cache\n // fields. Each ALTER is wrapped so a dialect without IF NOT EXISTS\n // (SQLite) still makes progress if only some columns are missing.\n for (const [col, def] of additions) {\n try {\n await client.execute(\n `ALTER TABLE token_usage ADD COLUMN ${col} ${def}`,\n );\n } catch {\n // Column already exists β ignore\n }\n }\n // Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres\n // the `Date.now()` written per run by recordUsage() overflows int4. Widen\n // it in place (no-op once done / on fresh BIGINT databases).\n await widenIntColumnsToBigInt(\"token_usage\", [\"created_at\"]);\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,\n );\n } catch {}\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n/**\n * Calculate cost in centicents (1/100th of a cent).\n * Accepts cache tokens so callers that use prompt caching are priced\n * correctly. Non-cache-aware callers can pass 0 for the cache fields.\n */\nexport function calculateCost(\n inputTokens: number,\n outputTokens: number,\n model: string,\n cacheReadTokens = 0,\n cacheWriteTokens = 0,\n): number {\n const p = pricingFor(model);\n const rawCenticents =\n (inputTokens / 1_000_000) * p.input * 100 +\n (outputTokens / 1_000_000) * p.output * 100 +\n (cacheReadTokens / 1_000_000) * p.cacheRead * 100 +\n (cacheWriteTokens / 1_000_000) * p.cacheWrite * 100;\n return rawCenticents > 0 ? Math.max(1, Math.round(rawCenticents)) : 0;\n}\n\n/**\n * Record token usage from an LLM call.\n *\n * Accepts an object with the full set of fields. A positional overload\n * remains for backward compatibility with the older 4-arg signature.\n */\nexport async function recordUsage(record: UsageRecord): Promise<void>;\nexport async function recordUsage(\n ownerEmail: string,\n inputTokens: number,\n outputTokens: number,\n model: string,\n): Promise<void>;\nexport async function recordUsage(\n recordOrOwner: UsageRecord | string,\n inputTokens?: number,\n outputTokens?: number,\n model?: string,\n): Promise<void> {\n const record: UsageRecord =\n typeof recordOrOwner === \"string\"\n ? {\n ownerEmail: recordOrOwner,\n inputTokens: inputTokens ?? 0,\n outputTokens: outputTokens ?? 0,\n model: model ?? \"\",\n }\n : recordOrOwner;\n\n const {\n ownerEmail,\n inputTokens: inTok,\n outputTokens: outTok,\n cacheReadTokens = 0,\n cacheWriteTokens = 0,\n model: modelName,\n label,\n app,\n refId,\n costCentsX100,\n } = record;\n\n // Skip no-op writes (e.g. a stream aborted before any tokens flowed)\n if (!inTok && !outTok && !cacheReadTokens && !cacheWriteTokens) return;\n\n await ensureUsageTable();\n const client = getDbExec();\n const resolvedApp =\n app ?? process.env.AGENT_APP ?? process.env.APP_NAME ?? \"\";\n const resolvedLabel = label ?? \"chat\";\n const resolvedRef = refId ?? \"\";\n\n // Replace any prior usage for this (label, refId) so re-recording the same\n // run β e.g. a recap regenerated on a PR re-push β overwrites instead of\n // double-counting. No-op when refId is unset (the common per-call path).\n if (resolvedRef) {\n await client.execute({\n sql: `DELETE FROM token_usage WHERE label = ? AND ref_id = ?`,\n args: [resolvedLabel, resolvedRef],\n });\n }\n\n // Prefer an explicit precomputed cost (e.g. a provider-reported dollar cost);\n // otherwise derive it from tokens via the pricing table.\n const costX100 =\n costCentsX100 ??\n calculateCost(inTok, outTok, modelName, cacheReadTokens, cacheWriteTokens);\n const id = Date.now() * 1000 + Math.floor(Math.random() * 1000);\n await client.execute({\n sql: `INSERT INTO token_usage\n (id, owner_email, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, model, label, app, ref_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n ownerEmail,\n inTok,\n outTok,\n cacheReadTokens,\n cacheWriteTokens,\n costX100,\n modelName,\n resolvedLabel,\n resolvedApp,\n resolvedRef,\n Date.now(),\n ],\n });\n}\n\n/** Total cost (in cents) charged against a user, across all time. */\nexport async function getUserUsageCents(ownerEmail: string): Promise<number> {\n await ensureUsageTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT COALESCE(SUM(cost_cents_x100), 0) as total FROM token_usage WHERE owner_email = ?`,\n args: [ownerEmail],\n });\n const total = Number((rows[0] as { total?: number })?.total ?? 0);\n return total / 100;\n}\n\n// βββ Admin / UI queries βββββββββββββββββββββββββββββββββββββββββββββββββ\n\nexport interface UsageSummaryOptions {\n ownerEmail: string;\n /** Inclusive lower bound (ms since epoch). Defaults to 30 days ago. */\n sinceMs?: number;\n}\n\nexport interface UsageBucket {\n key: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n calls: number;\n}\n\nexport interface DailyBucket {\n /** YYYY-MM-DD (UTC) */\n date: string;\n cents: number;\n calls: number;\n}\n\nexport interface UsageRecentEntry {\n id: number;\n createdAt: number;\n label: string;\n app: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n}\n\nexport interface UsageSummary {\n billing?: UsageBillingMode;\n totalCents: number;\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheWriteTokens: number;\n sinceMs: number;\n byLabel: UsageBucket[];\n byModel: UsageBucket[];\n byApp: UsageBucket[];\n byDay: DailyBucket[];\n recent: UsageRecentEntry[];\n}\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Produce an aggregated spend view for the Usage admin panel.\n * Scoped to the passed owner email; the UI always passes the session user.\n */\nexport async function getUsageSummary(\n options: UsageSummaryOptions,\n): Promise<UsageSummary> {\n await ensureUsageTable();\n const client = getDbExec();\n const sinceMs = options.sinceMs ?? Date.now() - 30 * DAY_MS;\n\n const totalRow = await client.execute({\n sql: `SELECT\n COALESCE(SUM(cost_cents_x100), 0) AS cents,\n COUNT(*) AS calls,\n COALESCE(SUM(input_tokens), 0) AS in_tok,\n COALESCE(SUM(output_tokens), 0) AS out_tok,\n COALESCE(SUM(cache_read_tokens), 0) AS cr_tok,\n COALESCE(SUM(cache_write_tokens), 0) AS cw_tok\n FROM token_usage WHERE owner_email = ? AND created_at >= ?`,\n args: [options.ownerEmail, sinceMs],\n });\n const t = (totalRow.rows[0] ?? {}) as Record<string, number | null>;\n\n const bucketSql = (col: string) => ({\n sql: `SELECT ${col} AS k,\n COALESCE(SUM(cost_cents_x100), 0) AS cents,\n COUNT(*) AS calls,\n COALESCE(SUM(input_tokens), 0) AS in_tok,\n COALESCE(SUM(output_tokens), 0) AS out_tok,\n COALESCE(SUM(cache_read_tokens), 0) AS cr_tok,\n COALESCE(SUM(cache_write_tokens), 0) AS cw_tok\n FROM token_usage\n WHERE owner_email = ? AND created_at >= ?\n GROUP BY ${col}\n ORDER BY cents DESC`,\n args: [options.ownerEmail, sinceMs],\n });\n\n const mapBuckets = (rows: unknown[]): UsageBucket[] =>\n rows.map((r) => {\n const row = r as Record<string, number | string | null>;\n return {\n key: String(row.k ?? \"\"),\n cents: Number(row.cents ?? 0) / 100,\n calls: Number(row.calls ?? 0),\n inputTokens: Number(row.in_tok ?? 0),\n outputTokens: Number(row.out_tok ?? 0),\n cacheReadTokens: Number(row.cr_tok ?? 0),\n cacheWriteTokens: Number(row.cw_tok ?? 0),\n };\n });\n\n const [byLabelR, byModelR, byAppR] = await Promise.all([\n client.execute(bucketSql(\"label\")),\n client.execute(bucketSql(\"model\")),\n client.execute(bucketSql(\"app\")),\n ]);\n\n // By-day aggregation β done in JS so we don't depend on dialect-specific\n // date functions (SQLite `strftime`, Postgres `to_char`). Cheap enough\n // for a 30-day window; if this grows, swap for a dialect-aware query.\n const dayRows = await client.execute({\n sql: `SELECT created_at, cost_cents_x100 FROM token_usage\n WHERE owner_email = ? AND created_at >= ?`,\n args: [options.ownerEmail, sinceMs],\n });\n const dayMap = new Map<string, { cents: number; calls: number }>();\n for (const row of dayRows.rows as Array<Record<string, number>>) {\n const date = new Date(Number(row.created_at)).toISOString().slice(0, 10);\n const prev = dayMap.get(date) ?? { cents: 0, calls: 0 };\n prev.cents += Number(row.cost_cents_x100 ?? 0);\n prev.calls += 1;\n dayMap.set(date, prev);\n }\n const byDay: DailyBucket[] = [...dayMap.entries()]\n .map(([date, v]) => ({\n date,\n cents: v.cents / 100,\n calls: v.calls,\n }))\n .sort((a, b) => a.date.localeCompare(b.date));\n\n const recentRows = await client.execute({\n sql: `SELECT id, created_at, label, app, model,\n input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,\n cost_cents_x100\n FROM token_usage\n WHERE owner_email = ?\n ORDER BY created_at DESC\n LIMIT 50`,\n args: [options.ownerEmail],\n });\n const recent: UsageRecentEntry[] = (\n recentRows.rows as Array<Record<string, number | string | null>>\n ).map((row) => ({\n id: Number(row.id),\n createdAt: Number(row.created_at),\n label: String(row.label ?? \"chat\"),\n app: String(row.app ?? \"\"),\n model: String(row.model ?? \"\"),\n inputTokens: Number(row.input_tokens ?? 0),\n outputTokens: Number(row.output_tokens ?? 0),\n cacheReadTokens: Number(row.cache_read_tokens ?? 0),\n cacheWriteTokens: Number(row.cache_write_tokens ?? 0),\n cents: Number(row.cost_cents_x100 ?? 0) / 100,\n }));\n\n return {\n billing: USD_USAGE_BILLING,\n totalCents: Number(t.cents ?? 0) / 100,\n totalCalls: Number(t.calls ?? 0),\n totalInputTokens: Number(t.in_tok ?? 0),\n totalOutputTokens: Number(t.out_tok ?? 0),\n totalCacheReadTokens: Number(t.cr_tok ?? 0),\n totalCacheWriteTokens: Number(t.cw_tok ?? 0),\n sinceMs,\n byLabel: mapBuckets(byLabelR.rows),\n byModel: mapBuckets(byModelR.rows),\n byApp: mapBuckets(byAppR.rows),\n byDay,\n recent,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAa,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAqB1D,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,kCAAkC,CAAC;AAud1C;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgE9C;AAED;;;;;;GAMG;AACH,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCvD;AAOD;;;;;GAKG;AACH,iBAAS,qBAAqB,CAC5B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9C;AAoDD,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"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"}
|