@agent-native/core 0.95.1 → 0.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +64 -0
- package/corpus/core/docs/content/audit-log.mdx +2 -1
- package/corpus/core/docs/content/automations.mdx +7 -7
- package/corpus/core/docs/content/creating-templates.mdx +1 -1
- package/corpus/core/docs/content/internationalization.mdx +2 -1
- package/corpus/core/docs/content/locales/ar-SA/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/ar-SA/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/ar-SA/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/ar-SA/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
- package/corpus/core/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/ar-SA/security.mdx +8 -0
- package/corpus/core/docs/content/locales/de-DE/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/de-DE/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/de-DE/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/de-DE/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
- package/corpus/core/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/de-DE/security.mdx +8 -0
- package/corpus/core/docs/content/locales/es-ES/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/es-ES/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/es-ES/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/es-ES/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
- package/corpus/core/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/es-ES/security.mdx +8 -0
- package/corpus/core/docs/content/locales/fr-FR/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/fr-FR/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/fr-FR/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/fr-FR/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
- package/corpus/core/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
- package/corpus/core/docs/content/locales/fr-FR/security.mdx +8 -0
- package/corpus/core/docs/content/locales/hi-IN/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/hi-IN/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/hi-IN/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/hi-IN/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
- package/corpus/core/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/hi-IN/security.mdx +8 -0
- package/corpus/core/docs/content/locales/ja-JP/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/ja-JP/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/ja-JP/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/ja-JP/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
- package/corpus/core/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
- package/corpus/core/docs/content/locales/ja-JP/security.mdx +8 -0
- package/corpus/core/docs/content/locales/ko-KR/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/ko-KR/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/ko-KR/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/ko-KR/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
- package/corpus/core/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
- package/corpus/core/docs/content/locales/ko-KR/security.mdx +8 -0
- package/corpus/core/docs/content/locales/pt-BR/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/pt-BR/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/pt-BR/getting-started.mdx +7 -1
- package/corpus/core/docs/content/locales/pt-BR/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
- package/corpus/core/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/pt-BR/security.mdx +8 -0
- package/corpus/core/docs/content/locales/zh-CN/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/zh-CN/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/zh-CN/getting-started.mdx +6 -4
- package/corpus/core/docs/content/locales/zh-CN/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
- package/corpus/core/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
- package/corpus/core/docs/content/locales/zh-CN/security.mdx +8 -0
- package/corpus/core/docs/content/locales/zh-TW/audit-log.mdx +2 -1
- package/corpus/core/docs/content/locales/zh-TW/automations.mdx +7 -7
- package/corpus/core/docs/content/locales/zh-TW/getting-started.mdx +6 -4
- package/corpus/core/docs/content/locales/zh-TW/internationalization.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
- package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
- package/corpus/core/docs/content/locales/zh-TW/security.mdx +8 -0
- package/corpus/core/docs/content/package-lifecycle.mdx +51 -0
- package/corpus/core/docs/content/sandbox-adapters.mdx +16 -5
- package/corpus/core/package.json +11 -2
- package/corpus/core/src/a2a/auth-policy.ts +33 -0
- package/corpus/core/src/a2a/client.ts +11 -1
- package/corpus/core/src/agent/durable-background.ts +15 -7
- package/corpus/core/src/agent/production-agent.ts +87 -27
- package/corpus/core/src/agent/run-store.ts +13 -4
- package/corpus/core/src/agent/thread-data-builder.ts +7 -5
- package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
- package/corpus/core/src/audit/store.ts +8 -3
- package/corpus/core/src/audit/types.ts +3 -0
- package/corpus/core/src/chat-threads/store.ts +20 -1
- package/corpus/core/src/cli/code-agent-executor.ts +1 -0
- package/corpus/core/src/cli/code-agent-runs.ts +14 -0
- package/corpus/core/src/cli/doctor.ts +396 -0
- package/corpus/core/src/cli/index.ts +56 -0
- package/corpus/core/src/cli/info.ts +3 -3
- package/corpus/core/src/cli/package-lifecycle.ts +821 -0
- package/corpus/core/src/client/AgentPanel.tsx +32 -25
- package/corpus/core/src/client/AssistantChat.tsx +36 -20
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +141 -90
- package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
- package/corpus/core/src/client/chat/ChatHistoryList.tsx +404 -0
- package/corpus/core/src/client/chat/index.ts +6 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +37 -3
- package/corpus/core/src/client/code-agent-chat-adapter.ts +72 -4
- package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +52 -11
- package/corpus/core/src/client/composer/TiptapComposer.tsx +157 -20
- package/corpus/core/src/client/composer/VoiceButton.tsx +28 -0
- package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +5 -0
- package/corpus/core/src/client/conversation/code-agent-transcript.ts +4 -5
- package/corpus/core/src/client/guided-questions.tsx +2 -1
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/client/use-chat-threads.ts +10 -1
- package/corpus/core/src/client/voice-provider-status.ts +44 -0
- package/corpus/core/src/code-agents/transcript-normalizer.ts +76 -0
- package/corpus/core/src/deploy/build.ts +12 -11
- package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
- package/corpus/core/src/guards/index.ts +23 -0
- package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
- package/corpus/core/src/guards/no-env-credentials.ts +229 -0
- package/corpus/core/src/guards/no-env-mutation.ts +114 -0
- package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
- package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
- package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
- package/corpus/core/src/guards/scan-utils.ts +105 -0
- package/corpus/core/src/guards/types.ts +30 -0
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +35 -5
- package/corpus/core/src/integrations/adapters/slack.ts +74 -21
- package/corpus/core/src/integrations/webhook-handler.ts +14 -0
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
- package/corpus/core/src/observability/routes.ts +17 -0
- package/corpus/core/src/observability/store.ts +4 -1
- package/corpus/core/src/observability/traces.ts +41 -2
- package/corpus/core/src/org/accept-pending.ts +9 -1
- package/corpus/core/src/org/migrations.ts +41 -0
- package/corpus/core/src/package-lifecycle/index.ts +1 -0
- package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
- package/corpus/core/src/provider-api/custom-registry.ts +56 -0
- package/corpus/core/src/provider-api/index.ts +2 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +19 -1
- package/corpus/core/src/scripts/call-agent.ts +53 -3
- package/corpus/core/src/scripts/chat/search-chats.ts +11 -8
- package/corpus/core/src/secrets/register-framework-secrets.ts +1 -1
- package/corpus/core/src/secrets/storage.ts +47 -27
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +95 -18
- package/corpus/core/src/server/core-routes-plugin.ts +45 -14
- package/corpus/core/src/server/csrf.ts +24 -5
- package/corpus/core/src/server/framework-request-handler.ts +34 -0
- package/corpus/core/src/server/google-realtime-session.ts +1 -36
- package/corpus/core/src/server/poll.ts +24 -2
- package/corpus/core/src/server/realtime-voice.ts +80 -24
- package/corpus/core/src/server/request-origin.ts +63 -0
- package/corpus/core/src/server/transcribe-voice.ts +1 -50
- package/corpus/core/src/server/voice-providers-status.ts +4 -3
- package/corpus/core/src/shared/cache-control.ts +2 -8
- package/corpus/core/src/styles/agent-native.css +1 -0
- package/corpus/core/src/styles/chat-history-list.css +313 -0
- package/corpus/core/src/templates/default/package.json +2 -2
- package/corpus/core/src/templates/headless/package.json +0 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/corpus/core/src/templates/workspace-core/package.json +0 -1
- package/corpus/core/src/templates/workspace-root/package.json +0 -1
- package/corpus/core/src/triggers/actions.ts +11 -3
- package/corpus/core/src/triggers/types.ts +7 -1
- package/corpus/core/src/vite/client.ts +1 -0
- package/corpus/templates/analytics/AGENTS.md +7 -0
- package/corpus/templates/analytics/actions/bigquery.ts +26 -2
- package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
- package/corpus/templates/analytics/actions/data-source-status.ts +18 -0
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
- package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
- package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -4
- package/corpus/templates/analytics/app/global.css +10 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +25 -2
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-answers-simple-time-bounded-metrics-without-unnece.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-chat-reliably-uses-connected-data-sources-across-s.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-chat-threads-now-stay-clear-of-top-actions-and-fade-smoothly.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-context-chips-can-now-be-selected-and-removed-one-at-a-time-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-composer-no-longer-carries-dashboard-or-panel-contex.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-section-stays-highlighted-while-its-chat-history-is-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
- package/corpus/templates/analytics/package.json +1 -2
- package/corpus/templates/analytics/server/lib/bigquery.ts +91 -14
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +82 -7
- package/corpus/templates/assets/package.json +1 -2
- package/corpus/templates/brain/package.json +1 -2
- package/corpus/templates/calendar/package.json +1 -2
- package/corpus/templates/chat/package.json +1 -2
- package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +3 -2
- package/corpus/templates/clips/desktop/package.json +6 -4
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
- package/corpus/templates/clips/package.json +1 -2
- package/corpus/templates/clips/server/db/schema.ts +29 -17
- package/corpus/templates/clips/server/plugins/db.ts +8 -0
- package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
- package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
- package/corpus/templates/content/AGENTS.md +72 -62
- package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
- package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
- package/corpus/templates/content/actions/_position-utils.ts +76 -0
- package/corpus/templates/content/actions/_property-utils.ts +31 -20
- package/corpus/templates/content/actions/add-database-item.ts +52 -39
- package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
- package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
- package/corpus/templates/content/actions/configure-document-property.ts +36 -27
- package/corpus/templates/content/actions/create-content-database.ts +40 -30
- package/corpus/templates/content/actions/create-document.ts +39 -32
- package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
- package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
- package/corpus/templates/content/actions/move-document.ts +64 -48
- package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
- package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
- package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
- package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
- package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/content/app/i18n-data.ts +40 -0
- package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
- package/corpus/templates/content/package.json +1 -2
- package/corpus/templates/content/parity/matrix.md +25 -25
- package/corpus/templates/content/parity/matrix.ts +1 -0
- package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
- package/corpus/templates/content/shared/api.ts +16 -1
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
- package/corpus/templates/design/AGENTS.md +12 -2
- package/corpus/templates/design/DEVELOPING.md +10 -6
- package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
- package/corpus/templates/design/actions/duplicate-design.ts +31 -25
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
- package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
- package/corpus/templates/design/package.json +1 -1
- package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
- package/corpus/templates/dispatch/package.json +1 -2
- package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
- package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
- package/corpus/templates/forms/package.json +1 -2
- package/corpus/templates/macros/package.json +1 -2
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
- package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
- package/corpus/templates/mail/package.json +1 -2
- package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
- package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
- package/corpus/templates/plan/package.json +1 -2
- package/corpus/templates/plan/server/plans.ts +9 -2
- package/corpus/templates/slides/actions/list-decks.ts +28 -0
- package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
- package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
- package/corpus/templates/slides/app/pages/Index.tsx +2 -3
- package/corpus/templates/slides/app/root.tsx +0 -5
- package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
- package/corpus/templates/slides/package.json +1 -2
- package/dist/a2a/auth-policy.d.ts +19 -0
- package/dist/a2a/auth-policy.d.ts.map +1 -1
- package/dist/a2a/auth-policy.js +32 -0
- package/dist/a2a/auth-policy.js.map +1 -1
- package/dist/a2a/client.d.ts +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +2 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/agent/durable-background.d.ts +8 -5
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +15 -8
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts +6 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +63 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +9 -4
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +1 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +6 -5
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/audit/actions/export-audit-events.d.ts +27 -0
- package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
- package/dist/audit/actions/export-audit-events.js +144 -0
- package/dist/audit/actions/export-audit-events.js.map +1 -0
- package/dist/audit/store.d.ts +1 -0
- package/dist/audit/store.d.ts.map +1 -1
- package/dist/audit/store.js +8 -3
- package/dist/audit/store.js.map +1 -1
- package/dist/audit/types.d.ts +3 -0
- package/dist/audit/types.d.ts.map +1 -1
- package/dist/audit/types.js.map +1 -1
- package/dist/chat-threads/store.d.ts +10 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +6 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +1 -0
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/code-agent-runs.d.ts +12 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -1
- package/dist/cli/code-agent-runs.js +1 -0
- package/dist/cli/code-agent-runs.js.map +1 -1
- package/dist/cli/doctor.d.ts +83 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +277 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/index.js +50 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/info.js +3 -3
- package/dist/cli/info.js.map +1 -1
- package/dist/cli/package-lifecycle.d.ts +50 -0
- package/dist/cli/package-lifecycle.d.ts.map +1 -0
- package/dist/cli/package-lifecycle.js +560 -0
- package/dist/cli/package-lifecycle.js.map +1 -0
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +11 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +7 -4
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +83 -10
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.js +7 -3
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/ChatHistoryList.d.ts +88 -0
- package/dist/client/chat/ChatHistoryList.d.ts.map +1 -0
- package/dist/client/chat/ChatHistoryList.js +83 -0
- package/dist/client/chat/ChatHistoryList.js.map +1 -0
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +13 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +10 -2
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/code-agent-chat-adapter.d.ts +17 -1
- package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +47 -3
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts +11 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.js +5 -3
- package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +25 -2
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +96 -5
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +21 -1
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.js +5 -0
- package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/client/conversation/code-agent-transcript.d.ts +2 -0
- package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -1
- package/dist/client/conversation/code-agent-transcript.js +3 -5
- package/dist/client/conversation/code-agent-transcript.js.map +1 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +2 -1
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +9 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/voice-provider-status.d.ts +10 -0
- package/dist/client/voice-provider-status.d.ts.map +1 -0
- package/dist/client/voice-provider-status.js +32 -0
- package/dist/client/voice-provider-status.js.map +1 -0
- package/dist/code-agents/transcript-normalizer.d.ts +29 -0
- package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +55 -0
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +13 -11
- package/dist/deploy/build.js.map +1 -1
- package/dist/guards/db-tool-scoping.d.ts +38 -0
- package/dist/guards/db-tool-scoping.d.ts.map +1 -0
- package/dist/guards/db-tool-scoping.js +114 -0
- package/dist/guards/db-tool-scoping.js.map +1 -0
- package/dist/guards/index.d.ts +23 -0
- package/dist/guards/index.d.ts.map +1 -0
- package/dist/guards/index.js +19 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/guards/no-drizzle-push.d.ts +14 -0
- package/dist/guards/no-drizzle-push.d.ts.map +1 -0
- package/dist/guards/no-drizzle-push.js +97 -0
- package/dist/guards/no-drizzle-push.js.map +1 -0
- package/dist/guards/no-env-credentials.d.ts +36 -0
- package/dist/guards/no-env-credentials.d.ts.map +1 -0
- package/dist/guards/no-env-credentials.js +204 -0
- package/dist/guards/no-env-credentials.js.map +1 -0
- package/dist/guards/no-env-mutation.d.ts +23 -0
- package/dist/guards/no-env-mutation.d.ts.map +1 -0
- package/dist/guards/no-env-mutation.js +90 -0
- package/dist/guards/no-env-mutation.js.map +1 -0
- package/dist/guards/no-localhost-fallback.d.ts +30 -0
- package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
- package/dist/guards/no-localhost-fallback.js +105 -0
- package/dist/guards/no-localhost-fallback.js.map +1 -0
- package/dist/guards/no-unscoped-credentials.d.ts +28 -0
- package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
- package/dist/guards/no-unscoped-credentials.js +199 -0
- package/dist/guards/no-unscoped-credentials.js.map +1 -0
- package/dist/guards/no-unscoped-queries.d.ts +32 -0
- package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
- package/dist/guards/no-unscoped-queries.js +720 -0
- package/dist/guards/no-unscoped-queries.js.map +1 -0
- package/dist/guards/scan-utils.d.ts +28 -0
- package/dist/guards/scan-utils.d.ts.map +1 -0
- package/dist/guards/scan-utils.js +92 -0
- package/dist/guards/scan-utils.js.map +1 -0
- package/dist/guards/types.d.ts +28 -0
- package/dist/guards/types.d.ts.map +1 -0
- package/dist/guards/types.js +11 -0
- package/dist/guards/types.js.map +1 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +25 -5
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +55 -21
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +11 -0
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +5 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/hosted-model-experiment.d.ts +39 -0
- package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
- package/dist/observability/hosted-model-experiment.js +90 -0
- package/dist/observability/hosted-model-experiment.js.map +1 -0
- package/dist/observability/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts.map +1 -1
- package/dist/observability/routes.js +16 -0
- package/dist/observability/routes.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +4 -1
- package/dist/observability/store.js.map +1 -1
- package/dist/observability/traces.d.ts +6 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +28 -2
- package/dist/observability/traces.js.map +1 -1
- package/dist/org/accept-pending.d.ts.map +1 -1
- package/dist/org/accept-pending.js +9 -1
- package/dist/org/accept-pending.js.map +1 -1
- package/dist/org/migrations.d.ts +7 -2
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +41 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/package-lifecycle/index.d.ts +2 -0
- package/dist/package-lifecycle/index.d.ts.map +1 -0
- package/dist/package-lifecycle/index.js +2 -0
- package/dist/package-lifecycle/index.js.map +1 -0
- package/dist/package-lifecycle/manifest.d.ts +24 -0
- package/dist/package-lifecycle/manifest.d.ts.map +1 -0
- package/dist/package-lifecycle/manifest.js +81 -0
- package/dist/package-lifecycle/manifest.js.map +1 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/custom-registry.d.ts +32 -1
- package/dist/provider-api/custom-registry.d.ts.map +1 -1
- package/dist/provider-api/custom-registry.js +41 -1
- package/dist/provider-api/custom-registry.js.map +1 -1
- package/dist/provider-api/index.d.ts +1 -1
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +1 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +19 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +43 -3
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/chat/search-chats.d.ts +1 -1
- package/dist/scripts/chat/search-chats.d.ts.map +1 -1
- package/dist/scripts/chat/search-chats.js +11 -8
- package/dist/scripts/chat/search-chats.js.map +1 -1
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +45 -27
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +11 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +74 -19
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +3 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +36 -12
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +18 -5
- package/dist/server/csrf.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +34 -0
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-realtime-session.d.ts.map +1 -1
- package/dist/server/google-realtime-session.js +2 -34
- package/dist/server/google-realtime-session.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +24 -2
- package/dist/server/poll.js.map +1 -1
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +64 -21
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/server/request-origin.d.ts +10 -0
- package/dist/server/request-origin.d.ts.map +1 -0
- package/dist/server/request-origin.js +60 -0
- package/dist/server/request-origin.js.map +1 -0
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +2 -48
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +2 -3
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/shared/cache-control.d.ts +4 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +2 -7
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/chat-history-list.css +313 -0
- package/dist/templates/default/package.json +2 -2
- package/dist/templates/headless/package.json +0 -1
- package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
- package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/dist/templates/workspace-core/package.json +0 -1
- package/dist/templates/workspace-root/package.json +0 -1
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +8 -3
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/types.d.ts +7 -1
- package/dist/triggers/types.d.ts.map +1 -1
- package/dist/triggers/types.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/audit-log.mdx +2 -1
- package/docs/content/automations.mdx +7 -7
- package/docs/content/creating-templates.mdx +1 -1
- package/docs/content/internationalization.mdx +2 -1
- package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
- package/docs/content/locales/ar-SA/automations.mdx +7 -7
- package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
- package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
- package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
- package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/ar-SA/security.mdx +8 -0
- package/docs/content/locales/de-DE/audit-log.mdx +2 -1
- package/docs/content/locales/de-DE/automations.mdx +7 -7
- package/docs/content/locales/de-DE/getting-started.mdx +7 -1
- package/docs/content/locales/de-DE/internationalization.mdx +1 -1
- package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
- package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/de-DE/security.mdx +8 -0
- package/docs/content/locales/es-ES/audit-log.mdx +2 -1
- package/docs/content/locales/es-ES/automations.mdx +7 -7
- package/docs/content/locales/es-ES/getting-started.mdx +7 -1
- package/docs/content/locales/es-ES/internationalization.mdx +1 -1
- package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
- package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/es-ES/security.mdx +8 -0
- package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
- package/docs/content/locales/fr-FR/automations.mdx +7 -7
- package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
- package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
- package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
- package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
- package/docs/content/locales/fr-FR/security.mdx +8 -0
- package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
- package/docs/content/locales/hi-IN/automations.mdx +7 -7
- package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
- package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
- package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
- package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/hi-IN/security.mdx +8 -0
- package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
- package/docs/content/locales/ja-JP/automations.mdx +7 -7
- package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
- package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
- package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
- package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
- package/docs/content/locales/ja-JP/security.mdx +8 -0
- package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
- package/docs/content/locales/ko-KR/automations.mdx +7 -7
- package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
- package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
- package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
- package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
- package/docs/content/locales/ko-KR/security.mdx +8 -0
- package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
- package/docs/content/locales/pt-BR/automations.mdx +7 -7
- package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
- package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
- package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
- package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/pt-BR/security.mdx +8 -0
- package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
- package/docs/content/locales/zh-CN/automations.mdx +7 -7
- package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
- package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
- package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
- package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
- package/docs/content/locales/zh-CN/security.mdx +8 -0
- package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
- package/docs/content/locales/zh-TW/automations.mdx +7 -7
- package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
- package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
- package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
- package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
- package/docs/content/locales/zh-TW/security.mdx +8 -0
- package/docs/content/package-lifecycle.mdx +51 -0
- package/docs/content/sandbox-adapters.mdx +16 -5
- package/package.json +12 -3
- package/src/templates/default/package.json +2 -2
- package/src/templates/headless/package.json +0 -1
- package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
- package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/src/templates/workspace-core/package.json +0 -1
- package/src/templates/workspace-root/package.json +0 -1
- package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
- package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
- package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared file-walking / offset helpers used by every guard in this
|
|
3
|
+
* directory. Ported (behavior-for-behavior) from the identical helpers
|
|
4
|
+
* duplicated across `scripts/guard-*.mjs` — see each guard file for the
|
|
5
|
+
* specific `scripts/guard-<name>.mjs` it was derived from.
|
|
6
|
+
*
|
|
7
|
+
* The original scripts walk directories with `fs/promises` async
|
|
8
|
+
* generators. Guard functions here are synchronous pure functions (per the
|
|
9
|
+
* plan's `scan<Name>(options): GuardResult` contract), so this module uses
|
|
10
|
+
* `fs.readdirSync` instead — same skip-dir semantics, no behavior change.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
|
|
16
|
+
/** Directories skipped by every guard's repo/app walk. */
|
|
17
|
+
export const DEFAULT_SKIP_DIRS = new Set([
|
|
18
|
+
"node_modules",
|
|
19
|
+
".git",
|
|
20
|
+
"dist",
|
|
21
|
+
"build",
|
|
22
|
+
".next",
|
|
23
|
+
".nuxt",
|
|
24
|
+
".output",
|
|
25
|
+
".cache",
|
|
26
|
+
".turbo",
|
|
27
|
+
".netlify",
|
|
28
|
+
".vercel",
|
|
29
|
+
".wrangler",
|
|
30
|
+
".react-router",
|
|
31
|
+
".generated",
|
|
32
|
+
".claude",
|
|
33
|
+
"out",
|
|
34
|
+
"coverage",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
/** Recursively walk `dir`, yielding absolute file paths. Skips any
|
|
38
|
+
* directory whose basename is in `skipDirs`. */
|
|
39
|
+
export function* walk(
|
|
40
|
+
dir: string,
|
|
41
|
+
skipDirs: Set<string> = DEFAULT_SKIP_DIRS,
|
|
42
|
+
): Generator<string> {
|
|
43
|
+
let entries: fs.Dirent[];
|
|
44
|
+
try {
|
|
45
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
46
|
+
} catch {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const full = path.join(dir, entry.name);
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
if (skipDirs.has(entry.name)) continue;
|
|
53
|
+
yield* walk(full, skipDirs);
|
|
54
|
+
} else if (entry.isFile()) {
|
|
55
|
+
yield full;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function lineColForOffset(
|
|
61
|
+
contents: string,
|
|
62
|
+
offset: number,
|
|
63
|
+
): { line: number; col: number } {
|
|
64
|
+
let line = 1;
|
|
65
|
+
let lineStart = 0;
|
|
66
|
+
for (let i = 0; i < offset; i++) {
|
|
67
|
+
if (contents.charCodeAt(i) === 10) {
|
|
68
|
+
line++;
|
|
69
|
+
lineStart = i + 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { line, col: offset - lineStart + 1 };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isCommentLine(lineText: string): boolean {
|
|
76
|
+
const trimmed = lineText.trimStart();
|
|
77
|
+
return (
|
|
78
|
+
trimmed.startsWith("*") ||
|
|
79
|
+
trimmed.startsWith("//") ||
|
|
80
|
+
trimmed.startsWith("/*")
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function relPosix(root: string, file: string): string {
|
|
85
|
+
return path.relative(root, file).replaceAll("\\", "/");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function readFileSafe(file: string): string | null {
|
|
89
|
+
try {
|
|
90
|
+
return fs.readFileSync(file, "utf8");
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** True if `rel` matches an exact-path entry in `extraExemptPaths`
|
|
97
|
+
* (posix-relative, exact string match — the same shape the exempt-path
|
|
98
|
+
* sets used in the original monorepo guards). */
|
|
99
|
+
export function isExtraExempt(
|
|
100
|
+
rel: string,
|
|
101
|
+
extraExemptPaths: string[] | undefined,
|
|
102
|
+
): boolean {
|
|
103
|
+
if (!extraExemptPaths || extraExemptPaths.length === 0) return false;
|
|
104
|
+
return extraExemptPaths.includes(rel);
|
|
105
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for `agent-native doctor`'s guard functions.
|
|
3
|
+
*
|
|
4
|
+
* Each guard is a pure function `scan<Name>(options): GuardResult` that
|
|
5
|
+
* scans a single app root and returns a flat list of findings. Guards do
|
|
6
|
+
* not print, exit, or read `agent-native.json` themselves — that
|
|
7
|
+
* orchestration lives in `../cli/doctor.ts` so the functions stay pure and
|
|
8
|
+
* independently testable/importable (see the `./guards` package export).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface GuardFinding {
|
|
12
|
+
/** Path to the offending file, relative to the scanned root. */
|
|
13
|
+
file: string;
|
|
14
|
+
/** 1-based line number of the offending line. */
|
|
15
|
+
line: number;
|
|
16
|
+
/** Human-readable explanation of the finding. */
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface GuardResult {
|
|
21
|
+
/** Stable guard identifier, e.g. "no-drizzle-push". Matches the name used
|
|
22
|
+
* by `--only` and `agent-native.json`'s `doctor.disabledGuards`. */
|
|
23
|
+
name: string;
|
|
24
|
+
findings: GuardFinding[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface GuardScanOptions {
|
|
28
|
+
/** Absolute path to the app root to scan. */
|
|
29
|
+
root: string;
|
|
30
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { Task } from "../a2a/types.js";
|
|
|
4
4
|
import {
|
|
5
5
|
formatLlmCredentialErrorMessage,
|
|
6
6
|
isLlmCredentialError,
|
|
7
|
+
LLM_MISSING_CREDENTIALS_ERROR_CODE,
|
|
7
8
|
} from "../agent/engine/credential-errors.js";
|
|
8
9
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
9
10
|
import { FRAMEWORK_ROUTE_PREFIX } from "../server/core-routes-plugin.js";
|
|
@@ -457,15 +458,44 @@ function formatContinuationFailureMessage(
|
|
|
457
458
|
continuation: A2AContinuation,
|
|
458
459
|
reason: string,
|
|
459
460
|
): string {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
461
|
+
const explicitCode = extractFailureCode(reason);
|
|
462
|
+
const diagnostics = formatContinuationFailureDiagnostics(
|
|
463
|
+
continuation,
|
|
464
|
+
reason,
|
|
465
|
+
);
|
|
466
|
+
if (isLlmCredentialError(reason, explicitCode)) {
|
|
467
|
+
return (
|
|
468
|
+
formatLlmCredentialErrorMessage({
|
|
469
|
+
agentName: continuation.agentName,
|
|
470
|
+
}) + diagnostics
|
|
471
|
+
);
|
|
464
472
|
}
|
|
465
473
|
|
|
466
474
|
return `The ${continuation.agentName} agent could not finish this request: ${sanitizeFailureReason(
|
|
467
475
|
reason,
|
|
468
|
-
)}`;
|
|
476
|
+
)}${diagnostics}`;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function formatContinuationFailureDiagnostics(
|
|
480
|
+
continuation: A2AContinuation,
|
|
481
|
+
reason: string,
|
|
482
|
+
): string {
|
|
483
|
+
return `\n\nError code: \`${continuationFailureCode(reason)}\`\nRequest ID: \`${continuation.integrationTaskId}\`\nContinuation ID: \`${continuation.id}\`\nDownstream task ID: \`${continuation.a2aTaskId}\``;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function continuationFailureCode(reason: string): string {
|
|
487
|
+
const explicitCode = extractFailureCode(reason);
|
|
488
|
+
if (explicitCode) return explicitCode;
|
|
489
|
+
if (isLlmCredentialError(reason, explicitCode)) {
|
|
490
|
+
return LLM_MISSING_CREDENTIALS_ERROR_CODE;
|
|
491
|
+
}
|
|
492
|
+
if (/\btimed out polling\b/i.test(reason)) return "a2a_remote_timeout";
|
|
493
|
+
return "a2a_downstream_error";
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function extractFailureCode(reason: string): string | null {
|
|
497
|
+
const match = /\bcode\s*[:=]\s*[`"']?([a-z][a-z0-9_]{0,79})\b/i.exec(reason);
|
|
498
|
+
return match?.[1]?.toLowerCase() ?? null;
|
|
469
499
|
}
|
|
470
500
|
|
|
471
501
|
function isRemoteWorkExpired(continuation: A2AContinuation): boolean {
|
|
@@ -37,6 +37,7 @@ const SLACK_API_TIMEOUT_MS = 10_000;
|
|
|
37
37
|
const SLACK_PERMALINK_TIMEOUT_MS = 1_000;
|
|
38
38
|
const SLACK_CONTEXT_MESSAGE_LIMIT = 15;
|
|
39
39
|
const SLACK_CONTEXT_TEXT_LIMIT = 2_000;
|
|
40
|
+
const SLACK_CALM_PROGRESS_THRESHOLD_SECONDS = 30;
|
|
40
41
|
|
|
41
42
|
export interface SlackAdapterOptions {
|
|
42
43
|
/** Resolve the bot token for the exact Slack installation. */
|
|
@@ -323,12 +324,10 @@ export function slackAdapter(
|
|
|
323
324
|
async postProcessingPlaceholder(
|
|
324
325
|
incoming: IncomingMessage,
|
|
325
326
|
): Promise<{ placeholderRef: string } | null> {
|
|
326
|
-
// No placeholder reply in the thread — Slack's native assistant
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
// We just set the native status and return null so sendResponse posts
|
|
331
|
-
// the final reply as a fresh message.
|
|
327
|
+
// No placeholder reply in the thread — Slack's native assistant status
|
|
328
|
+
// bar and the task stream are the loading affordance. Keep the status
|
|
329
|
+
// specific about intent instead of presenting the generic thinking
|
|
330
|
+
// state while the native plan is opening.
|
|
332
331
|
const token = await resolveBotToken(incoming);
|
|
333
332
|
if (!token) return null;
|
|
334
333
|
|
|
@@ -336,11 +335,16 @@ export function slackAdapter(
|
|
|
336
335
|
const threadTs = incoming.platformContext.threadTs as string;
|
|
337
336
|
if (!channelId || !threadTs) return null;
|
|
338
337
|
|
|
339
|
-
// Best-effort: flip the native Agent
|
|
338
|
+
// Best-effort: flip the native Agent status bar in the
|
|
340
339
|
// channel input area. Slack accepts chat:write for this method. The
|
|
341
340
|
// canonical manifest separately requests assistant:write for Agent View
|
|
342
341
|
// and app_context_changed events.
|
|
343
|
-
setSlackAssistantStatus(
|
|
342
|
+
setSlackAssistantStatus(
|
|
343
|
+
token,
|
|
344
|
+
channelId,
|
|
345
|
+
threadTs,
|
|
346
|
+
"I’m looking into this now…",
|
|
347
|
+
);
|
|
344
348
|
return null;
|
|
345
349
|
},
|
|
346
350
|
|
|
@@ -1266,6 +1270,42 @@ function shortTaskTitle(value: unknown): string {
|
|
|
1266
1270
|
return text.replace(/[-_]/g, " ").slice(0, 200);
|
|
1267
1271
|
}
|
|
1268
1272
|
|
|
1273
|
+
function delegatedTaskTitle(agent: unknown): string {
|
|
1274
|
+
return `Contact ${shortTaskTitle(agent)}`;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
function formatElapsedSeconds(elapsedSeconds: number): string {
|
|
1278
|
+
const totalSeconds = Math.max(0, Math.round(elapsedSeconds));
|
|
1279
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
1280
|
+
const seconds = totalSeconds % 60;
|
|
1281
|
+
return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
function formatProgressState(state: string): string {
|
|
1285
|
+
if (state === "submitted") return "Queued";
|
|
1286
|
+
if (state === "working") return "Working";
|
|
1287
|
+
return shortTaskTitle(state);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
function delegatedProgressDetails(
|
|
1291
|
+
agent: unknown,
|
|
1292
|
+
state: string,
|
|
1293
|
+
elapsedSeconds: number,
|
|
1294
|
+
detail?: string,
|
|
1295
|
+
): string {
|
|
1296
|
+
const elapsed = formatElapsedSeconds(elapsedSeconds);
|
|
1297
|
+
const progress = `${formatProgressState(state)} · ${elapsed}`;
|
|
1298
|
+
const update = detail ? shortTaskTitle(detail) : "";
|
|
1299
|
+
|
|
1300
|
+
if (elapsedSeconds >= SLACK_CALM_PROGRESS_THRESHOLD_SECONDS) {
|
|
1301
|
+
const agentName = shortTaskTitle(agent);
|
|
1302
|
+
const context = update ? ` — ${update}.` : ".";
|
|
1303
|
+
return `${progress}${context} This is taking longer than usual, but ${agentName} is still working. I’ll post the result here.`;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
return update ? `${progress} — ${update}` : progress;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1269
1309
|
async function postSlackJson(
|
|
1270
1310
|
token: string,
|
|
1271
1311
|
method: string,
|
|
@@ -1315,18 +1355,18 @@ async function startSlackRunProgress(
|
|
|
1315
1355
|
...(incoming.tenantId ? { recipient_team_id: incoming.tenantId } : {}),
|
|
1316
1356
|
...(incoming.senderId ? { recipient_user_id: incoming.senderId } : {}),
|
|
1317
1357
|
task_display_mode: "plan",
|
|
1318
|
-
markdown_text: "
|
|
1358
|
+
markdown_text: "I’m looking into this for you.",
|
|
1319
1359
|
chunks: [
|
|
1320
1360
|
{
|
|
1321
1361
|
type: "plan_update",
|
|
1322
|
-
title: "
|
|
1362
|
+
title: "I’m looking into this for you",
|
|
1323
1363
|
},
|
|
1324
1364
|
{
|
|
1325
1365
|
type: "task_update",
|
|
1326
1366
|
id: "agent-native:context",
|
|
1327
|
-
title: "
|
|
1367
|
+
title: "Review the request",
|
|
1328
1368
|
status: "in_progress",
|
|
1329
|
-
details: "
|
|
1369
|
+
details: "Finding the information needed for an answer",
|
|
1330
1370
|
},
|
|
1331
1371
|
],
|
|
1332
1372
|
});
|
|
@@ -1373,7 +1413,7 @@ function createSlackRunProgress(
|
|
|
1373
1413
|
const toolTaskIds = new Map<string, string>();
|
|
1374
1414
|
const agentTaskIds = new Map<string, string>();
|
|
1375
1415
|
tasks.set("agent-native:context", {
|
|
1376
|
-
title: "
|
|
1416
|
+
title: "Review the request",
|
|
1377
1417
|
status: "in_progress",
|
|
1378
1418
|
});
|
|
1379
1419
|
let sequence = 0;
|
|
@@ -1540,9 +1580,19 @@ function createSlackRunProgress(
|
|
|
1540
1580
|
: event.status === "done"
|
|
1541
1581
|
? "complete"
|
|
1542
1582
|
: "error";
|
|
1543
|
-
const title =
|
|
1583
|
+
const title = delegatedTaskTitle(event.agent);
|
|
1544
1584
|
tasks.set(id, { title, status });
|
|
1545
|
-
await append({
|
|
1585
|
+
await append({
|
|
1586
|
+
type: "task_update",
|
|
1587
|
+
id,
|
|
1588
|
+
title,
|
|
1589
|
+
status,
|
|
1590
|
+
...(event.status === "start"
|
|
1591
|
+
? {
|
|
1592
|
+
details: `I’m contacting ${shortTaskTitle(event.agent)} for an answer.`,
|
|
1593
|
+
}
|
|
1594
|
+
: {}),
|
|
1595
|
+
});
|
|
1546
1596
|
} else if (event.type === "agent_call_progress") {
|
|
1547
1597
|
// A2A calls can stay healthy for minutes. Keep the same native Slack
|
|
1548
1598
|
// task card alive with each real downstream poll rather than creating
|
|
@@ -1550,10 +1600,13 @@ function createSlackRunProgress(
|
|
|
1550
1600
|
const id =
|
|
1551
1601
|
agentTaskIds.get(event.agent) ?? taskId("agent", event.agent);
|
|
1552
1602
|
agentTaskIds.set(event.agent, id);
|
|
1553
|
-
const title =
|
|
1554
|
-
const details =
|
|
1555
|
-
|
|
1556
|
-
|
|
1603
|
+
const title = delegatedTaskTitle(event.agent);
|
|
1604
|
+
const details = delegatedProgressDetails(
|
|
1605
|
+
event.agent,
|
|
1606
|
+
event.state,
|
|
1607
|
+
event.elapsedSeconds,
|
|
1608
|
+
event.detail,
|
|
1609
|
+
);
|
|
1557
1610
|
tasks.set(id, { title, status: "in_progress" });
|
|
1558
1611
|
await append({
|
|
1559
1612
|
type: "task_update",
|
|
@@ -1566,9 +1619,9 @@ function createSlackRunProgress(
|
|
|
1566
1619
|
await append({
|
|
1567
1620
|
type: "task_update",
|
|
1568
1621
|
id: "agent-native:context",
|
|
1569
|
-
title: "
|
|
1622
|
+
title: "Review the request",
|
|
1570
1623
|
status: "in_progress",
|
|
1571
|
-
details: shortTaskTitle(event.label)
|
|
1624
|
+
details: `Working · ${shortTaskTitle(event.label)}`,
|
|
1572
1625
|
});
|
|
1573
1626
|
}
|
|
1574
1627
|
},
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
normalizeModelForEngine,
|
|
16
16
|
resolveEngine,
|
|
17
17
|
} from "../agent/engine/index.js";
|
|
18
|
+
import { resolveMainChatMaxOutputTokens } from "../agent/engine/output-tokens.js";
|
|
18
19
|
import { PROVIDER_TO_ENV } from "../agent/engine/provider-env-vars.js";
|
|
19
20
|
import type { AgentEngine, EngineMessage } from "../agent/engine/types.js";
|
|
20
21
|
import {
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
readDeployCredentialEnv,
|
|
46
47
|
} from "../server/credential-provider.js";
|
|
47
48
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
49
|
+
import { normalizeReasoningEffortForRequest } from "../shared/reasoning-effort.js";
|
|
48
50
|
import { A2A_CONTINUATION_QUEUED_MARKER } from "./a2a-continuation-marker.js";
|
|
49
51
|
import {
|
|
50
52
|
clearIntegrationAwaitingInput,
|
|
@@ -866,6 +868,18 @@ async function processIncomingMessage(
|
|
|
866
868
|
signal,
|
|
867
869
|
threadId,
|
|
868
870
|
approvedToolCalls: incoming.approvedToolCalls,
|
|
871
|
+
// Messaging integrations are interactive chat surfaces. They
|
|
872
|
+
// need the same initial completion headroom as web chat so
|
|
873
|
+
// reasoning cannot consume the small per-engine default and
|
|
874
|
+
// leave a user-facing Slack reply empty.
|
|
875
|
+
maxOutputTokens: resolveMainChatMaxOutputTokens(resolvedModel),
|
|
876
|
+
// Explicitly resolve the normal chat default so an empty-final
|
|
877
|
+
// retry can step its reasoning effort down rather than
|
|
878
|
+
// repeatedly letting the engine choose Medium.
|
|
879
|
+
reasoningEffort: normalizeReasoningEffortForRequest(
|
|
880
|
+
resolvedModel,
|
|
881
|
+
undefined,
|
|
882
|
+
),
|
|
869
883
|
});
|
|
870
884
|
return usage;
|
|
871
885
|
},
|
|
@@ -216,6 +216,12 @@ const messages = {
|
|
|
216
216
|
promptTitle: "Talk to your app",
|
|
217
217
|
promptDescription:
|
|
218
218
|
"Voice mode keeps listening while the agent navigates and takes actions.",
|
|
219
|
+
setupTitle: "Set up voice mode",
|
|
220
|
+
setupDescription:
|
|
221
|
+
"Connect Builder to use managed voice with credits, or use your own OpenAI API key.",
|
|
222
|
+
connectBuilder: "Connect Builder",
|
|
223
|
+
useOpenAiKey: "Use OpenAI API key",
|
|
224
|
+
startWithOpenAiKey: "Start with OpenAI key",
|
|
219
225
|
start: "Start voice mode",
|
|
220
226
|
keepDictating: "Keep dictating",
|
|
221
227
|
showChat: "Show chat",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export const HOSTED_DEFAULT_MODEL_EXPERIMENT_ID =
|
|
2
|
+
"hosted-default-model-sonnet-5-vs-gpt-5-6-luna-2026-07";
|
|
3
|
+
|
|
4
|
+
export const HOSTED_DEFAULT_MODEL_CONTROL = {
|
|
5
|
+
id: "sonnet-5",
|
|
6
|
+
model: "claude-sonnet-5",
|
|
7
|
+
weight: 80,
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export const HOSTED_DEFAULT_MODEL_TREATMENT = {
|
|
11
|
+
id: "gpt-5-6-luna",
|
|
12
|
+
model: "gpt-5-6-luna",
|
|
13
|
+
weight: 20,
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
export interface HostedDefaultModelExperimentAssignment {
|
|
17
|
+
experimentId: string;
|
|
18
|
+
variantId: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface HostedDefaultModelExperimentResolution {
|
|
22
|
+
model: string;
|
|
23
|
+
assignment: HostedDefaultModelExperimentAssignment;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type HostedExperimentEnv = Record<string, string | undefined>;
|
|
27
|
+
|
|
28
|
+
const FIRST_PARTY_HOST_SUFFIX = ".agent-native.com";
|
|
29
|
+
const ENABLED_VALUES = new Set(["1", "true", "on", "yes"]);
|
|
30
|
+
const DISABLED_VALUES = new Set(["0", "false", "off", "no"]);
|
|
31
|
+
|
|
32
|
+
function hostnameFromUrl(value: string | undefined): string | null {
|
|
33
|
+
const trimmed = value?.trim();
|
|
34
|
+
if (!trimmed) return null;
|
|
35
|
+
try {
|
|
36
|
+
const url = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)
|
|
37
|
+
? new URL(trimmed)
|
|
38
|
+
: new URL(`https://${trimmed}`);
|
|
39
|
+
return url.hostname.toLowerCase();
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The rollout is automatic only on first-party hosted app domains. Operators
|
|
47
|
+
* can explicitly enable or disable it for preview and emergency rollback.
|
|
48
|
+
*/
|
|
49
|
+
export function isHostedDefaultModelExperimentEnabled(
|
|
50
|
+
env: HostedExperimentEnv = process.env,
|
|
51
|
+
): boolean {
|
|
52
|
+
const override =
|
|
53
|
+
env.AGENT_NATIVE_HOSTED_MODEL_EXPERIMENT?.trim().toLowerCase();
|
|
54
|
+
if (override && DISABLED_VALUES.has(override)) return false;
|
|
55
|
+
if (override && ENABLED_VALUES.has(override)) return true;
|
|
56
|
+
|
|
57
|
+
const hostnames = [
|
|
58
|
+
env.APP_URL,
|
|
59
|
+
env.BETTER_AUTH_URL,
|
|
60
|
+
env.URL,
|
|
61
|
+
env.DEPLOY_URL,
|
|
62
|
+
env.VERCEL_PROJECT_PRODUCTION_URL,
|
|
63
|
+
env.VERCEL_URL,
|
|
64
|
+
]
|
|
65
|
+
.map(hostnameFromUrl)
|
|
66
|
+
.filter((hostname): hostname is string => Boolean(hostname));
|
|
67
|
+
|
|
68
|
+
return hostnames.some(
|
|
69
|
+
(hostname) =>
|
|
70
|
+
hostname === "agent-native.com" ||
|
|
71
|
+
hostname.endsWith(FIRST_PARTY_HOST_SUFFIX),
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Stable cross-app bucket: the same authenticated user receives the same
|
|
77
|
+
* variant in every hosted template for the life of this experiment id.
|
|
78
|
+
*/
|
|
79
|
+
export function hostedDefaultModelExperimentBucket(userId: string): number {
|
|
80
|
+
const input = `${HOSTED_DEFAULT_MODEL_EXPERIMENT_ID}:${userId.trim().toLowerCase()}`;
|
|
81
|
+
let hash = 0x811c9dc5;
|
|
82
|
+
for (let index = 0; index < input.length; index++) {
|
|
83
|
+
hash ^= input.charCodeAt(index);
|
|
84
|
+
hash = Math.imul(hash, 0x01000193);
|
|
85
|
+
}
|
|
86
|
+
return (hash >>> 0) % 100;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function resolveHostedDefaultModelExperiment(args: {
|
|
90
|
+
userId: string | null | undefined;
|
|
91
|
+
engineName: string;
|
|
92
|
+
isDefaultModelSelection: boolean;
|
|
93
|
+
supportedModels?: readonly string[];
|
|
94
|
+
env?: HostedExperimentEnv;
|
|
95
|
+
}): HostedDefaultModelExperimentResolution | null {
|
|
96
|
+
const userId = args.userId?.trim();
|
|
97
|
+
if (!userId) return null;
|
|
98
|
+
if (args.engineName !== "builder") return null;
|
|
99
|
+
if (!args.isDefaultModelSelection) return null;
|
|
100
|
+
if (!isHostedDefaultModelExperimentEnabled(args.env)) return null;
|
|
101
|
+
|
|
102
|
+
const variant =
|
|
103
|
+
hostedDefaultModelExperimentBucket(userId) <
|
|
104
|
+
HOSTED_DEFAULT_MODEL_TREATMENT.weight
|
|
105
|
+
? HOSTED_DEFAULT_MODEL_TREATMENT
|
|
106
|
+
: HOSTED_DEFAULT_MODEL_CONTROL;
|
|
107
|
+
if (args.supportedModels && !args.supportedModels.includes(variant.model)) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
model: variant.model,
|
|
113
|
+
assignment: {
|
|
114
|
+
experimentId: HOSTED_DEFAULT_MODEL_EXPERIMENT_ID,
|
|
115
|
+
variantId: variant.id,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -69,6 +69,18 @@ async function resolveOwner(event: H3Event): Promise<string> {
|
|
|
69
69
|
return session.email;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function canManageExperiments(ownerEmail: string): boolean {
|
|
73
|
+
// Local development keeps the built-in dashboard usable without additional
|
|
74
|
+
// setup. Hosted deployments fail closed unless the operator supplies an
|
|
75
|
+
// explicit allowlist, because experiments affect every user in the app.
|
|
76
|
+
if (process.env.NODE_ENV !== "production") return true;
|
|
77
|
+
const admins = (process.env.AGENT_NATIVE_EXPERIMENT_ADMIN_EMAILS ?? "")
|
|
78
|
+
.split(",")
|
|
79
|
+
.map((email) => email.trim().toLowerCase())
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
return admins.includes(ownerEmail.trim().toLowerCase());
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
function parseSince(q: Record<string, any>): number {
|
|
73
85
|
const raw = q.since;
|
|
74
86
|
if (typeof raw === "string" && raw.length > 0) {
|
|
@@ -236,6 +248,11 @@ export function createObservabilityHandler() {
|
|
|
236
248
|
return getEvalStats(parseSince(q), { userId: owner });
|
|
237
249
|
}
|
|
238
250
|
|
|
251
|
+
if (parts[0] === "experiments" && !canManageExperiments(owner)) {
|
|
252
|
+
setResponseStatus(event, 403);
|
|
253
|
+
return { error: "Experiment administrator access required" };
|
|
254
|
+
}
|
|
255
|
+
|
|
239
256
|
// POST /experiments — create experiment. Records the calling user as
|
|
240
257
|
// the owner so subsequent PUT / POST results require the same caller.
|
|
241
258
|
if (method === "POST" && parts.length === 1 && parts[0] === "experiments") {
|
|
@@ -972,7 +972,10 @@ export async function updateExperiment(
|
|
|
972
972
|
sets.push("status = ?");
|
|
973
973
|
args.push(updates.status);
|
|
974
974
|
if (updates.status === "running" && !updates.endedAt) {
|
|
975
|
-
|
|
975
|
+
// Preserve the original exposure window when a paused experiment
|
|
976
|
+
// resumes; resetting it would silently discard the first run period from
|
|
977
|
+
// the results.
|
|
978
|
+
sets.push("started_at = COALESCE(started_at, ?)");
|
|
976
979
|
args.push(Date.now());
|
|
977
980
|
}
|
|
978
981
|
}
|
|
@@ -100,6 +100,11 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
100
100
|
successfulTools: number;
|
|
101
101
|
failedTools: number;
|
|
102
102
|
createdAt: number;
|
|
103
|
+
experimentAssignments?: Array<{
|
|
104
|
+
experimentId: string;
|
|
105
|
+
variantId: string;
|
|
106
|
+
}>;
|
|
107
|
+
modelSelectionSource?: string;
|
|
103
108
|
}): void {
|
|
104
109
|
const provider = llmProviderFromEngine(args.engineName, args.model);
|
|
105
110
|
const costUsd = costUsdFromCenticents(args.costCentsX100);
|
|
@@ -126,6 +131,7 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
126
131
|
tool_calls: args.toolCalls,
|
|
127
132
|
successful_tools: args.successfulTools,
|
|
128
133
|
failed_tools: args.failedTools,
|
|
134
|
+
model_selection_source: args.modelSelectionSource,
|
|
129
135
|
created_at: new Date(args.createdAt).toISOString(),
|
|
130
136
|
created_at_ms: args.createdAt,
|
|
131
137
|
$ai_trace_id: args.runId,
|
|
@@ -145,6 +151,18 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
145
151
|
$ai_request_count: 1,
|
|
146
152
|
$ai_total_cost_usd: costUsd,
|
|
147
153
|
};
|
|
154
|
+
if (args.experimentAssignments?.length) {
|
|
155
|
+
properties.experiment_ids = args.experimentAssignments
|
|
156
|
+
.map((assignment) => assignment.experimentId)
|
|
157
|
+
.join(",");
|
|
158
|
+
properties.experiment_variants = args.experimentAssignments
|
|
159
|
+
.map((assignment) => assignment.variantId)
|
|
160
|
+
.join(",");
|
|
161
|
+
if (args.experimentAssignments.length === 1) {
|
|
162
|
+
properties.experiment_id = args.experimentAssignments[0].experimentId;
|
|
163
|
+
properties.experiment_variant = args.experimentAssignments[0].variantId;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
148
166
|
if (error) properties.error_message = error;
|
|
149
167
|
|
|
150
168
|
for (const key of Object.keys(properties)) {
|
|
@@ -245,6 +263,12 @@ export async function instrumentAgentLoop(opts: {
|
|
|
245
263
|
* reads. */
|
|
246
264
|
userId: string | null;
|
|
247
265
|
config: ObservabilityConfig;
|
|
266
|
+
metadata?: Record<string, unknown> | null;
|
|
267
|
+
experimentAssignments?: Array<{
|
|
268
|
+
experimentId: string;
|
|
269
|
+
variantId: string;
|
|
270
|
+
}>;
|
|
271
|
+
modelSelectionSource?: string;
|
|
248
272
|
classifyError?: (error: unknown) =>
|
|
249
273
|
| {
|
|
250
274
|
status?: "success" | "error";
|
|
@@ -268,6 +292,15 @@ export async function instrumentAgentLoop(opts: {
|
|
|
268
292
|
"agent.thread_id": threadId ?? undefined,
|
|
269
293
|
"agent.user_id": userId ?? undefined,
|
|
270
294
|
"agent.model": loopOpts.model,
|
|
295
|
+
"agent.model_selection_source": opts.modelSelectionSource,
|
|
296
|
+
"agent.experiment_id":
|
|
297
|
+
opts.experimentAssignments?.length === 1
|
|
298
|
+
? opts.experimentAssignments[0].experimentId
|
|
299
|
+
: undefined,
|
|
300
|
+
"agent.experiment_variant":
|
|
301
|
+
opts.experimentAssignments?.length === 1
|
|
302
|
+
? opts.experimentAssignments[0].variantId
|
|
303
|
+
: undefined,
|
|
271
304
|
});
|
|
272
305
|
|
|
273
306
|
const spans: TraceSpan[] = [];
|
|
@@ -424,7 +457,7 @@ export async function instrumentAgentLoop(opts: {
|
|
|
424
457
|
let usage: AgentLoopUsage | undefined;
|
|
425
458
|
let runStatus: "success" | "error" = "success";
|
|
426
459
|
let errorMessage: string | null = null;
|
|
427
|
-
let runMetadata: Record<string, unknown> | null = null;
|
|
460
|
+
let runMetadata: Record<string, unknown> | null = opts.metadata ?? null;
|
|
428
461
|
try {
|
|
429
462
|
usage = await runAgentLoop({ ...loopOpts, send: instrumentedSend });
|
|
430
463
|
} catch (err: any) {
|
|
@@ -434,7 +467,11 @@ export async function instrumentAgentLoop(opts: {
|
|
|
434
467
|
classification?.errorMessage === undefined
|
|
435
468
|
? (err?.message ?? String(err))
|
|
436
469
|
: classification.errorMessage;
|
|
437
|
-
|
|
470
|
+
const errorMetadata = classification?.metadata ?? null;
|
|
471
|
+
runMetadata =
|
|
472
|
+
runMetadata || errorMetadata
|
|
473
|
+
? { ...(runMetadata ?? {}), ...(errorMetadata ?? {}) }
|
|
474
|
+
: null;
|
|
438
475
|
throw err;
|
|
439
476
|
} finally {
|
|
440
477
|
const runEnd = Date.now();
|
|
@@ -501,6 +538,8 @@ export async function instrumentAgentLoop(opts: {
|
|
|
501
538
|
successfulTools,
|
|
502
539
|
failedTools,
|
|
503
540
|
createdAt: runStart,
|
|
541
|
+
experimentAssignments: opts.experimentAssignments,
|
|
542
|
+
modelSelectionSource: opts.modelSelectionSource,
|
|
504
543
|
});
|
|
505
544
|
}
|
|
506
545
|
|