@agent-native/core 0.96.0 → 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 +39 -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 +9 -2
- package/corpus/core/src/a2a/auth-policy.ts +33 -0
- package/corpus/core/src/agent/durable-background.ts +15 -7
- package/corpus/core/src/agent/run-store.ts +13 -4
- 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/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/agent-chat-adapter.ts +9 -9
- 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/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/secrets/storage.ts +47 -27
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +54 -12
- package/corpus/core/src/server/core-routes-plugin.ts +30 -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 +9 -0
- package/corpus/core/src/server/request-origin.ts +63 -0
- package/corpus/core/src/server/transcribe-voice.ts +1 -50
- 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/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/templates/analytics/actions/compose-dashboard.ts +65 -37
- 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/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-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 +3 -2
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
- 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/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/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/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/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/agent-chat-adapter.js +7 -3
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +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/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/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.map +1 -1
- package/dist/server/agent-chat-plugin.js +47 -13
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +23 -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 +9 -0
- 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/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/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/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 +10 -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/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
|
@@ -1169,12 +1169,20 @@ export function createCoreRoutesPlugin(
|
|
|
1169
1169
|
}),
|
|
1170
1170
|
);
|
|
1171
1171
|
|
|
1172
|
-
// Defense-in-depth CSRF check for state-changing /_agent-native/* routes
|
|
1173
|
-
//
|
|
1174
|
-
//
|
|
1175
|
-
//
|
|
1176
|
-
|
|
1177
|
-
|
|
1172
|
+
// Defense-in-depth CSRF check for state-changing /_agent-native/* routes
|
|
1173
|
+
// (see `csrf.ts` for the threat model and allowlist) is registered by
|
|
1174
|
+
// `getH3App()` itself (framework-request-handler.ts), synchronously, on
|
|
1175
|
+
// the very first call to `getH3App(nitroApp)` for this process — NOT
|
|
1176
|
+
// here. Registering it inside this plugin's own async init chain would
|
|
1177
|
+
// race against agent-chat-plugin's action-route registration (a
|
|
1178
|
+
// SEPARATE, independently-async-initialized Nitro plugin file in real
|
|
1179
|
+
// deployments): whichever plugin's `getH3App(nitroApp).use(...)` call
|
|
1180
|
+
// happened to resolve first would win the position in the middleware
|
|
1181
|
+
// array, and CSRF losing that race would let an action route match and
|
|
1182
|
+
// run before the CSRF check ever saw the request. Centralizing the
|
|
1183
|
+
// registration in `getH3App()`'s one-time bootstrap makes it the first
|
|
1184
|
+
// middleware any plugin's route can possibly land behind, regardless of
|
|
1185
|
+
// plugin init ordering.
|
|
1178
1186
|
|
|
1179
1187
|
// Agent discovery primitive — shared by headless CLI/A2A surfaces and
|
|
1180
1188
|
// UI shells that need to show connected peer apps without depending on
|
|
@@ -1275,8 +1283,11 @@ export function createCoreRoutesPlugin(
|
|
|
1275
1283
|
return { error: "executionId required" };
|
|
1276
1284
|
}
|
|
1277
1285
|
|
|
1278
|
-
const {
|
|
1279
|
-
|
|
1286
|
+
const {
|
|
1287
|
+
hasConfiguredA2ASecret,
|
|
1288
|
+
isLoopbackAddress,
|
|
1289
|
+
isTrustedLocalRuntime,
|
|
1290
|
+
} = await import("../a2a/auth-policy.js");
|
|
1280
1291
|
if (hasConfiguredA2ASecret()) {
|
|
1281
1292
|
const { verifyInternalToken, extractBearerToken } =
|
|
1282
1293
|
await import("../integrations/internal-token.js");
|
|
@@ -1285,12 +1296,17 @@ export function createCoreRoutesPlugin(
|
|
|
1285
1296
|
setResponseStatus(event, 401);
|
|
1286
1297
|
return { error: "Invalid or expired processor token" };
|
|
1287
1298
|
}
|
|
1288
|
-
} else
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1299
|
+
} else {
|
|
1300
|
+
const loopback = isLoopbackAddress(
|
|
1301
|
+
getRequestIP(event, { xForwardedFor: false }),
|
|
1302
|
+
);
|
|
1303
|
+
if (!isTrustedLocalRuntime({ loopback })) {
|
|
1304
|
+
setResponseStatus(event, 503);
|
|
1305
|
+
return {
|
|
1306
|
+
error:
|
|
1307
|
+
"Sandbox execution processor not configured — set A2A_SECRET on this deployment (or A2A_ALLOW_UNSIGNED_INTERNAL=1 for trusted local dev).",
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1294
1310
|
}
|
|
1295
1311
|
|
|
1296
1312
|
try {
|
|
@@ -50,6 +50,8 @@ import {
|
|
|
50
50
|
setResponseStatus,
|
|
51
51
|
} from "h3";
|
|
52
52
|
|
|
53
|
+
import { getConfiguredAppBasePath } from "./app-base-path.js";
|
|
54
|
+
|
|
53
55
|
/**
|
|
54
56
|
* Path prefixes (relative to the framework prefix `/_agent-native`) that are
|
|
55
57
|
* allowed to receive cross-origin state-changing POSTs without first-party
|
|
@@ -144,9 +146,10 @@ function requestHasCookies(event: any): boolean {
|
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
/**
|
|
147
|
-
*
|
|
148
|
-
* `
|
|
149
|
-
*
|
|
149
|
+
* The path is the full request URL pathname (e.g.
|
|
150
|
+
* `/_agent-native/actions/foo` or `/app/_agent-native/actions/foo`).
|
|
151
|
+
* `frameworkPrefix` is the root framework route prefix without a trailing
|
|
152
|
+
* slash, e.g. `/_agent-native`.
|
|
150
153
|
*/
|
|
151
154
|
function isOnAllowlist(pathname: string, frameworkPrefix: string): boolean {
|
|
152
155
|
if (!pathname.startsWith(frameworkPrefix)) return false;
|
|
@@ -157,6 +160,21 @@ function isOnAllowlist(pathname: string, frameworkPrefix: string): boolean {
|
|
|
157
160
|
return false;
|
|
158
161
|
}
|
|
159
162
|
|
|
163
|
+
function matchingFrameworkPrefix(
|
|
164
|
+
pathname: string,
|
|
165
|
+
frameworkPrefix: string,
|
|
166
|
+
): string | undefined {
|
|
167
|
+
if (pathname.startsWith(frameworkPrefix)) return frameworkPrefix;
|
|
168
|
+
|
|
169
|
+
const basePath = getConfiguredAppBasePath();
|
|
170
|
+
const basePathFrameworkPrefix = `${basePath}${frameworkPrefix}`;
|
|
171
|
+
if (basePath && pathname.startsWith(basePathFrameworkPrefix)) {
|
|
172
|
+
return basePathFrameworkPrefix;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
|
|
160
178
|
/**
|
|
161
179
|
* Create the framework CSRF middleware.
|
|
162
180
|
*
|
|
@@ -176,8 +194,9 @@ export function createCsrfMiddleware(
|
|
|
176
194
|
if (!STATE_CHANGING_METHODS.has(method)) return undefined;
|
|
177
195
|
|
|
178
196
|
const pathname = event.url?.pathname ?? "";
|
|
179
|
-
|
|
180
|
-
if (
|
|
197
|
+
const matchingPrefix = matchingFrameworkPrefix(pathname, frameworkPrefix);
|
|
198
|
+
if (!matchingPrefix) return undefined;
|
|
199
|
+
if (isOnAllowlist(pathname, matchingPrefix)) return undefined;
|
|
181
200
|
|
|
182
201
|
// No cookie = no risk of confused-deputy CSRF on the session cookie.
|
|
183
202
|
if (!requestHasCookies(event)) return undefined;
|
|
@@ -17,6 +17,7 @@ import { setResponseHeader, setResponseStatus } from "h3";
|
|
|
17
17
|
import { getMissingDefaultPlugins } from "../deploy/route-discovery.js";
|
|
18
18
|
import { getConfiguredAppBasePath } from "./app-base-path.js";
|
|
19
19
|
import { captureError } from "./capture-error.js";
|
|
20
|
+
import { createCsrfMiddleware } from "./csrf.js";
|
|
20
21
|
|
|
21
22
|
const BOOTSTRAPPED = new WeakSet<object>();
|
|
22
23
|
const IN_BOOTSTRAP = new WeakSet<object>();
|
|
@@ -164,6 +165,27 @@ export function getH3App(nitroApp: any): H3AppShim {
|
|
|
164
165
|
prepend: true,
|
|
165
166
|
});
|
|
166
167
|
|
|
168
|
+
// CSRF (see csrf.ts): registered here — synchronously, on the very
|
|
169
|
+
// first `getH3App()` call for this nitroApp — rather than inside
|
|
170
|
+
// createCoreRoutesPlugin's own async init chain. Real deployments mount
|
|
171
|
+
// core-routes and agent-chat as SEPARATE, independently-async-initialized
|
|
172
|
+
// Nitro plugin files with no explicit ordering between them; both
|
|
173
|
+
// eventually call `getH3App(nitroApp).use(...)` to register their own
|
|
174
|
+
// routes (CSRF, action routes) after their own async setup (DB reads,
|
|
175
|
+
// dynamic imports) resolves in unpredictable relative order. The
|
|
176
|
+
// readiness gate above only guarantees every tracked plugin has FINISHED
|
|
177
|
+
// registering by the time a gated request is released — it does NOT
|
|
178
|
+
// guarantee CSRF's registration call happens to `.push()` onto
|
|
179
|
+
// `~middleware` before an action route's does. If agent-chat's action
|
|
180
|
+
// route push happened to land first, that route would match and run
|
|
181
|
+
// before CSRF ever saw the request. Registering CSRF here instead makes
|
|
182
|
+
// it the first non-prepended middleware pushed onto the array for this
|
|
183
|
+
// nitroApp, full stop — every plugin's own route registrations reach
|
|
184
|
+
// `getH3App()` (and therefore run after this point) before they can
|
|
185
|
+
// register anything, regardless of which plugin's async chain resolves
|
|
186
|
+
// first.
|
|
187
|
+
registerMiddleware(nitroApp, "", createCsrfMiddleware());
|
|
188
|
+
|
|
167
189
|
// Primary gate: Nitro bridges this `request` hook to h3's `config.onRequest`,
|
|
168
190
|
// which h3 awaits BEFORE `handler()` snapshots middleware and resolves the
|
|
169
191
|
// route. The middleware gate above runs too late on production dispatchers —
|
|
@@ -466,7 +488,18 @@ function registerMiddleware(
|
|
|
466
488
|
let originalPathname: string | undefined;
|
|
467
489
|
let originalEventPath: string | undefined;
|
|
468
490
|
let hadEventPath = false;
|
|
491
|
+
// Only true once this specific middleware invocation has actually
|
|
492
|
+
// stripped a mount prefix (i.e. `path` was non-empty and matched).
|
|
493
|
+
// Global (`path === ""`) middleware never mutates event.path/pathname,
|
|
494
|
+
// so `restoreOriginalPath` must be a no-op for it — otherwise it would
|
|
495
|
+
// unconditionally `delete event.path` on every pass-through (hadEventPath
|
|
496
|
+
// defaults to false), corrupting the event for any middleware that runs
|
|
497
|
+
// later in the chain (a real bug: two or more global middlewares in
|
|
498
|
+
// sequence, e.g. security-headers + CORS + CSRF, would wipe event.path
|
|
499
|
+
// for everything downstream, including the final route handler).
|
|
500
|
+
let didStripPath = false;
|
|
469
501
|
const restoreOriginalPath = () => {
|
|
502
|
+
if (!didStripPath) return;
|
|
470
503
|
if (originalPathname !== undefined) {
|
|
471
504
|
try {
|
|
472
505
|
event.url.pathname = originalPathname;
|
|
@@ -502,6 +535,7 @@ function registerMiddleware(
|
|
|
502
535
|
const eventAny = event as any;
|
|
503
536
|
hadEventPath = "path" in eventAny;
|
|
504
537
|
originalEventPath = eventAny.path;
|
|
538
|
+
didStripPath = true;
|
|
505
539
|
try {
|
|
506
540
|
originalPathname = event.url.pathname;
|
|
507
541
|
// Save the full path in context so handlers that need the original URL
|
|
@@ -3,7 +3,6 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import {
|
|
4
4
|
defineEventHandler,
|
|
5
5
|
getMethod,
|
|
6
|
-
getRequestHeader,
|
|
7
6
|
readBody,
|
|
8
7
|
setResponseStatus,
|
|
9
8
|
type H3Event,
|
|
@@ -15,6 +14,7 @@ import { readAppSecret } from "../secrets/storage.js";
|
|
|
15
14
|
import { getSession } from "./auth.js";
|
|
16
15
|
import { resolveBuilderCredentials } from "./credential-provider.js";
|
|
17
16
|
import { runWithRequestContext } from "./request-context.js";
|
|
17
|
+
import { isSameOriginRequest } from "./request-origin.js";
|
|
18
18
|
|
|
19
19
|
interface GoogleRealtimeSessionResponse {
|
|
20
20
|
websocketUrl: string;
|
|
@@ -22,41 +22,6 @@ interface GoogleRealtimeSessionResponse {
|
|
|
22
22
|
websocketProtocol?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function isSameOriginRequest(event: H3Event): boolean {
|
|
26
|
-
const host = getRequestHeader(event, "host");
|
|
27
|
-
const origin = getRequestHeader(event, "origin");
|
|
28
|
-
if (origin && host) {
|
|
29
|
-
try {
|
|
30
|
-
const parsed = new URL(origin);
|
|
31
|
-
if (parsed.host === host) return true;
|
|
32
|
-
if (parsed.protocol === "tauri:" && parsed.hostname === "localhost") {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
if (
|
|
36
|
-
(parsed.protocol === "http:" || parsed.protocol === "https:") &&
|
|
37
|
-
parsed.hostname === "tauri.localhost" &&
|
|
38
|
-
(host.startsWith("localhost:") || host.startsWith("127.0.0.1:"))
|
|
39
|
-
) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
if (
|
|
43
|
-
parsed.protocol === "http:" &&
|
|
44
|
-
(parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1") &&
|
|
45
|
-
parsed.port === "1420" &&
|
|
46
|
-
(host.startsWith("localhost:") || host.startsWith("127.0.0.1:"))
|
|
47
|
-
) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
} catch {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const fetchSite = getRequestHeader(event, "sec-fetch-site");
|
|
56
|
-
if (fetchSite) return fetchSite === "same-origin" || fetchSite === "none";
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
25
|
export async function resolveGoogleRealtimeCredentials(opts: {
|
|
61
26
|
userEmail?: string | null;
|
|
62
27
|
orgId?: string | null;
|
|
@@ -738,9 +738,31 @@ async function getDurableChangesSinceForUser(
|
|
|
738
738
|
}
|
|
739
739
|
|
|
740
740
|
try {
|
|
741
|
+
// Scope the fetch to rows that could ever be visible to this caller
|
|
742
|
+
// before paying to JSON.parse and visibility-check every deployment-wide
|
|
743
|
+
// event: deployment-global rows (no owner, no org), the caller's own
|
|
744
|
+
// rows, the caller's org's rows, and resource-scoped rows (owner/org
|
|
745
|
+
// don't gate those — access is decided below by
|
|
746
|
+
// `getChangeVisibilityForUser`'s access-aware branch, which can grant a
|
|
747
|
+
// non-owner sharee, so resource-scoped rows must still flow through that
|
|
748
|
+
// check regardless of who owns them). This lets Postgres/SQLite use the
|
|
749
|
+
// `sync_events_owner_version_idx` / `sync_events_org_version_idx` indexes
|
|
750
|
+
// instead of scanning every tenant's activity on every poll. The OR group
|
|
751
|
+
// is parenthesized so `version > ?` ANDs against the whole group, not
|
|
752
|
+
// just the first term. A caller with no org passes a null `orgId` bind
|
|
753
|
+
// param, which makes `org_id = ?` evaluate to no match for every row
|
|
754
|
+
// (including null-org rows) in both dialects — mirroring the
|
|
755
|
+
// `event.orgId && orgId` truthy check in `getChangeVisibilityForUser`.
|
|
741
756
|
const result = await getDbExec().execute({
|
|
742
|
-
sql: `SELECT version, event_json FROM sync_events WHERE version > ?
|
|
743
|
-
|
|
757
|
+
sql: `SELECT version, event_json FROM sync_events WHERE version > ?
|
|
758
|
+
AND (
|
|
759
|
+
(owner IS NULL AND org_id IS NULL)
|
|
760
|
+
OR owner = ?
|
|
761
|
+
OR org_id = ?
|
|
762
|
+
OR resource_type IS NOT NULL
|
|
763
|
+
)
|
|
764
|
+
ORDER BY version ASC LIMIT ?`,
|
|
765
|
+
args: [since, userEmail, orgId ?? null, DURABLE_READ_LIMIT + 1],
|
|
744
766
|
});
|
|
745
767
|
const events: ChangeEvent[] = [];
|
|
746
768
|
let version = Math.max(_version, since);
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "./credential-provider.js";
|
|
27
27
|
import { getH3App } from "./framework-request-handler.js";
|
|
28
28
|
import { runWithRequestContext } from "./request-context.js";
|
|
29
|
+
import { isSameOriginRequest } from "./request-origin.js";
|
|
29
30
|
|
|
30
31
|
export const REALTIME_VOICE_SESSION_PATH =
|
|
31
32
|
"/_agent-native/realtime-voice/session";
|
|
@@ -301,6 +302,10 @@ function createSessionHandler(
|
|
|
301
302
|
) {
|
|
302
303
|
return defineEventHandler(async (event: H3Event) => {
|
|
303
304
|
if (getMethod(event) !== "POST") return invalidMethod(event);
|
|
305
|
+
if (!isSameOriginRequest(event)) {
|
|
306
|
+
setResponseStatus(event, 403);
|
|
307
|
+
return { error: "Cross-origin request rejected" };
|
|
308
|
+
}
|
|
304
309
|
setResponseHeader(event, "Cache-Control", "no-store");
|
|
305
310
|
|
|
306
311
|
const auth = await authenticateVoiceRequest(event, options);
|
|
@@ -529,6 +534,10 @@ function createToolHandler(
|
|
|
529
534
|
) {
|
|
530
535
|
return defineEventHandler(async (event: H3Event) => {
|
|
531
536
|
if (getMethod(event) !== "POST") return invalidMethod(event);
|
|
537
|
+
if (!isSameOriginRequest(event)) {
|
|
538
|
+
setResponseStatus(event, 403);
|
|
539
|
+
return { error: "Cross-origin request rejected" };
|
|
540
|
+
}
|
|
532
541
|
setResponseHeader(event, "Cache-Control", "no-store");
|
|
533
542
|
|
|
534
543
|
const auth = await authenticateVoiceRequest(event, options);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getRequestHeader, type H3Event } from "h3";
|
|
2
|
+
|
|
3
|
+
function isLoopbackHost(host: string): boolean {
|
|
4
|
+
return host.startsWith("localhost:") || host.startsWith("127.0.0.1:");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Reject cross-site POSTs. Cookies are `SameSite=None; Secure` over HTTPS so
|
|
9
|
+
* the browser would otherwise attach the session to a forged form submission
|
|
10
|
+
* from evil.com, causing us to spend provider credits on the user's behalf.
|
|
11
|
+
* Same-origin browsers always send `Origin` on POST; if it's missing we fall
|
|
12
|
+
* back to `Sec-Fetch-Site` so Safari's fetch-spec behavior still works.
|
|
13
|
+
*/
|
|
14
|
+
export function isSameOriginRequest(event: H3Event): boolean {
|
|
15
|
+
const host = getRequestHeader(event, "host");
|
|
16
|
+
const origin = getRequestHeader(event, "origin");
|
|
17
|
+
if (origin && host) {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = new URL(origin);
|
|
20
|
+
const forwardedProto = getRequestHeader(event, "x-forwarded-proto");
|
|
21
|
+
const forwardedProtocol =
|
|
22
|
+
forwardedProto === "https" || forwardedProto === "http"
|
|
23
|
+
? `${forwardedProto}:`
|
|
24
|
+
: null;
|
|
25
|
+
const matchesScheme = forwardedProtocol
|
|
26
|
+
? parsed.protocol === forwardedProtocol
|
|
27
|
+
: parsed.protocol === "https:" ||
|
|
28
|
+
(parsed.protocol === "http:" && isLoopbackHost(host));
|
|
29
|
+
if (parsed.host === host && matchesScheme) return true;
|
|
30
|
+
// Tauri desktop dev serves the tray WebView from localhost:1420 while
|
|
31
|
+
// the app server lives on the template dev port. Production Tauri
|
|
32
|
+
// WebViews can also send a tauri://localhost origin. Trust that custom
|
|
33
|
+
// scheme, while limiting the web-scheme desktop origins below to a
|
|
34
|
+
// loopback app server so arbitrary websites still fail the CSRF check.
|
|
35
|
+
if (parsed.protocol === "tauri:" && parsed.hostname === "localhost") {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (
|
|
39
|
+
(parsed.protocol === "http:" || parsed.protocol === "https:") &&
|
|
40
|
+
parsed.hostname === "tauri.localhost" &&
|
|
41
|
+
isLoopbackHost(host)
|
|
42
|
+
) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (
|
|
46
|
+
parsed.protocol === "http:" &&
|
|
47
|
+
(parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1") &&
|
|
48
|
+
parsed.port === "1420" &&
|
|
49
|
+
isLoopbackHost(host)
|
|
50
|
+
) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const fetchSite = getRequestHeader(event, "sec-fetch-site");
|
|
59
|
+
if (fetchSite) return fetchSite === "same-origin" || fetchSite === "none";
|
|
60
|
+
// No Origin and no Sec-Fetch-Site: likely a non-browser client (curl,
|
|
61
|
+
// server-side) — safe to allow, CSRF requires a browser with ambient cookies.
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
import {
|
|
21
21
|
defineEventHandler,
|
|
22
22
|
getMethod,
|
|
23
|
-
getRequestHeader,
|
|
24
23
|
readMultipartFormData,
|
|
25
24
|
setResponseStatus,
|
|
26
25
|
type H3Event,
|
|
@@ -43,6 +42,7 @@ import {
|
|
|
43
42
|
resolveSecret,
|
|
44
43
|
} from "./credential-provider.js";
|
|
45
44
|
import { runWithRequestContext } from "./request-context.js";
|
|
45
|
+
import { isSameOriginRequest } from "./request-origin.js";
|
|
46
46
|
|
|
47
47
|
const WHISPER_URL = "https://api.openai.com/v1/audio/transcriptions";
|
|
48
48
|
const GROQ_URL = "https://api.groq.com/openai/v1/audio/transcriptions";
|
|
@@ -75,55 +75,6 @@ const BUILDER_GEMINI_TRANSCRIPTION_MODEL = "gemini-3-1-flash-lite";
|
|
|
75
75
|
const GEMINI_MODEL = "gemini-2.0-flash-lite";
|
|
76
76
|
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent`;
|
|
77
77
|
|
|
78
|
-
/**
|
|
79
|
-
* Reject cross-site POSTs. Cookies are `SameSite=None; Secure` over HTTPS so
|
|
80
|
-
* the browser would otherwise attach the session to a forged form submission
|
|
81
|
-
* from evil.com, causing us to spend OpenAI credits on the user's behalf.
|
|
82
|
-
* Same-origin browsers always send `Origin` on POST; if it's missing we fall
|
|
83
|
-
* back to `Sec-Fetch-Site` so Safari's fetch-spec behavior still works.
|
|
84
|
-
*/
|
|
85
|
-
function isSameOriginRequest(event: H3Event): boolean {
|
|
86
|
-
const host = getRequestHeader(event, "host");
|
|
87
|
-
const origin = getRequestHeader(event, "origin");
|
|
88
|
-
if (origin && host) {
|
|
89
|
-
try {
|
|
90
|
-
const parsed = new URL(origin);
|
|
91
|
-
if (parsed.host === host) return true;
|
|
92
|
-
// Tauri desktop dev serves the tray WebView from localhost:1420 while
|
|
93
|
-
// the app server lives on the template dev port. Production Tauri
|
|
94
|
-
// WebViews can also send a tauri://localhost origin. Treat only those
|
|
95
|
-
// desktop origins as trusted cross-origin callers; arbitrary websites
|
|
96
|
-
// still fail the CSRF check.
|
|
97
|
-
if (parsed.protocol === "tauri:" && parsed.hostname === "localhost") {
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
if (
|
|
101
|
-
(parsed.protocol === "http:" || parsed.protocol === "https:") &&
|
|
102
|
-
parsed.hostname === "tauri.localhost" &&
|
|
103
|
-
(host.startsWith("localhost:") || host.startsWith("127.0.0.1:"))
|
|
104
|
-
) {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
if (
|
|
108
|
-
parsed.protocol === "http:" &&
|
|
109
|
-
(parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1") &&
|
|
110
|
-
parsed.port === "1420" &&
|
|
111
|
-
(host.startsWith("localhost:") || host.startsWith("127.0.0.1:"))
|
|
112
|
-
) {
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
} catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const fetchSite = getRequestHeader(event, "sec-fetch-site");
|
|
121
|
-
if (fetchSite) return fetchSite === "same-origin" || fetchSite === "none";
|
|
122
|
-
// No Origin and no Sec-Fetch-Site: likely a non-browser client (curl,
|
|
123
|
-
// server-side) — safe to allow, CSRF requires a browser with ambient cookies.
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
78
|
/**
|
|
128
79
|
* Derive an AbortSignal that fires when the client disconnects mid-request
|
|
129
80
|
* (e.g. the desktop client's own 8s ceiling firing before a provider call's
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"build": "agent-native build",
|
|
8
8
|
"start": "agent-native start",
|
|
9
9
|
"typecheck": "agent-native typecheck",
|
|
10
|
+
"doctor": "agent-native doctor",
|
|
10
11
|
"action": "agent-native action",
|
|
11
12
|
"script": "agent-native script",
|
|
12
13
|
"skills:update": "agent-native skills update scaffold --project",
|
|
@@ -43,8 +44,7 @@
|
|
|
43
44
|
"tailwind-merge": "^3.5.0",
|
|
44
45
|
"tailwindcss": "^4.1.18",
|
|
45
46
|
"tsx": "^4.20.3",
|
|
46
|
-
"typescript": "catalog:",
|
|
47
47
|
"typescript-7": "catalog:",
|
|
48
|
-
"vite": "
|
|
48
|
+
"vite": "8.1.0"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -77,6 +77,9 @@ SQL to the caller — they never leak another tenant's rows:
|
|
|
77
77
|
(`agent` | `human` | `system`), `status`, `threadId`/`turnId`, `action`,
|
|
78
78
|
`sinceMs`, `limit`.
|
|
79
79
|
- `get-audit-event` — one event by id, with its redacted input payload.
|
|
80
|
+
- `export-audit-events` — bulk CSV/NDJSON export (same filters minus `limit`,
|
|
81
|
+
plus `format` and `maxRows`) for offline/compliance pulls; itself audited
|
|
82
|
+
via `onRead`.
|
|
80
83
|
|
|
81
84
|
Call them from the UI with `useActionQuery` to build an activity feed or a
|
|
82
85
|
"who changed this" line — never hand-write a fetch to the audit table.
|
|
@@ -61,7 +61,7 @@ Use the web-request tool with ${keys.SLACK_WEBHOOK}.
|
|
|
61
61
|
| `triggerType` | `"schedule" \| "event"` | How the automation fires |
|
|
62
62
|
| `event` | `string?` | Event name to subscribe to (event triggers) |
|
|
63
63
|
| `condition` | `string?` | Natural-language condition evaluated before dispatch |
|
|
64
|
-
| `mode` | `"agentic"
|
|
64
|
+
| `mode` | `"agentic"` | Full agent loop (only supported mode; `"deterministic"` was removed — never implemented, rejected at define time) |
|
|
65
65
|
| `model` | `string?` | Override the model for this trigger's agent loop |
|
|
66
66
|
| `domain` | `string?` | Grouping tag (mail, calendar, clips, etc.) |
|
|
67
67
|
| `createdBy` | `string?` | Owner email |
|
|
@@ -107,6 +107,14 @@ async function handleDefine(
|
|
|
107
107
|
return `Error: An automation named "${name}" already exists. Use a different name or delete the existing one first.`;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
if (args.mode === "deterministic") {
|
|
111
|
+
return (
|
|
112
|
+
"Error: Deterministic mode was removed — it was never implemented and " +
|
|
113
|
+
"automations that set it never fired. Create the automation without " +
|
|
114
|
+
"mode (agentic), and describe the exact fixed steps in the automation body."
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
110
118
|
const triggerType = args.trigger_type === "schedule" ? "schedule" : "event";
|
|
111
119
|
const meta: TriggerFrontmatter = {
|
|
112
120
|
schedule: args.schedule || "",
|
|
@@ -114,7 +122,7 @@ async function handleDefine(
|
|
|
114
122
|
triggerType,
|
|
115
123
|
event: args.event || undefined,
|
|
116
124
|
condition: args.condition || undefined,
|
|
117
|
-
mode:
|
|
125
|
+
mode: "agentic",
|
|
118
126
|
domain: args.domain || undefined,
|
|
119
127
|
createdBy: owner,
|
|
120
128
|
runAs: "creator",
|
|
@@ -268,8 +276,8 @@ export function createAutomationToolEntries(
|
|
|
268
276
|
mode: {
|
|
269
277
|
type: "string",
|
|
270
278
|
description:
|
|
271
|
-
'"agentic" (full agent loop, can use tools)
|
|
272
|
-
enum: ["agentic"
|
|
279
|
+
'"agentic" (full agent loop, can use tools) — the only supported mode. Used by define.',
|
|
280
|
+
enum: ["agentic"],
|
|
273
281
|
},
|
|
274
282
|
domain: {
|
|
275
283
|
type: "string",
|
|
@@ -15,7 +15,13 @@ export interface TriggerFrontmatter {
|
|
|
15
15
|
event?: string;
|
|
16
16
|
/** Natural-language condition evaluated by Haiku before dispatch. */
|
|
17
17
|
condition?: string;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* "agentic" = full runAgentLoop; the only mode `manage-automations` will
|
|
20
|
+
* define/update going forward. "deterministic" was removed from the
|
|
21
|
+
* advertised surface (never implemented) and is legacy-only: rows created
|
|
22
|
+
* before the removal may still carry it, and the dispatcher's
|
|
23
|
+
* warn-and-skip branch keeps them inert by design — do not make them fire.
|
|
24
|
+
*/
|
|
19
25
|
mode: "agentic" | "deterministic";
|
|
20
26
|
/** Domain tag for filtering in per-template UIs. */
|
|
21
27
|
domain?: string;
|