@agent-native/core 0.169.1 → 0.170.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/agent-native.eject.json +4 -1
- package/bin/agent-native.js +23 -5
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- package/corpus/templates/analytics/app/routes/$.tsx +10 -0
- package/corpus/templates/analytics/app/routes.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
- package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
- package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
- package/corpus/templates/analytics/server/lib/slack.ts +4 -2
- package/corpus/templates/analytics/vitest.config.ts +6 -1
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/assets/app/routes/library.tsx +5 -3
- package/corpus/templates/assets/app/routes.ts +3 -1
- package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
- package/corpus/templates/assets/vitest.config.ts +6 -1
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/brain/app/routes/sources.tsx +8 -3
- package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
- package/corpus/templates/brain/vitest.config.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
- package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
- package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
- package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
- package/corpus/templates/calendar/app/routes.ts +3 -1
- package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
- package/corpus/templates/calendar/server/onboarding.ts +85 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/calendar/shared/api.ts +9 -1
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/chat/app/routes.ts +3 -1
- package/corpus/templates/chat/vitest.config.ts +8 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/clips/actions/get-meeting.ts +9 -4
- package/corpus/templates/clips/actions/list-recordings.ts +16 -3
- package/corpus/templates/clips/actions/search-meetings.ts +1 -0
- package/corpus/templates/clips/actions/view-screen.ts +8 -1
- package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
- package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
- package/corpus/templates/clips/desktop/src/app.tsx +53 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
- package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
- package/corpus/templates/clips/server/lib/emails.ts +17 -33
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
- package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
- package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
- package/corpus/templates/content/app/i18n-data.ts +25 -0
- package/corpus/templates/content/app/routes.ts +3 -1
- package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
- package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
- package/corpus/templates/content/vitest.config.ts +7 -1
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
- package/corpus/templates/design/actions/generate-design.ts +98 -47
- package/corpus/templates/design/actions/get-design-system.ts +6 -1
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
- package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
- package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
- package/corpus/templates/design/app/pages/Index.tsx +2 -0
- package/corpus/templates/design/app/pages/Templates.tsx +0 -10
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
- package/corpus/templates/design/app/routes.ts +3 -1
- package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
- package/corpus/templates/design/shared/canvas-math.ts +612 -206
- package/corpus/templates/design/shared/pen-path.ts +37 -0
- package/corpus/templates/design/vitest.config.ts +7 -1
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
- package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
- package/corpus/templates/dispatch/app/routes.ts +3 -1
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/factory/.env.example +2 -7
- package/corpus/templates/factory/AGENTS.md +3 -0
- package/corpus/templates/factory/README.md +5 -3
- package/corpus/templates/factory/actions/create-factory.ts +16 -3
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
- package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
- package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
- package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
- package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
- package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
- package/corpus/templates/factory/app/routes/factory.tsx +84 -11
- package/corpus/templates/factory/app/routes.ts +3 -1
- package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
- package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
- package/corpus/templates/factory/vitest.config.ts +17 -2
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
- package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
- package/corpus/templates/forms/vitest.config.ts +1 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/macros/app/routes.ts +3 -1
- package/corpus/templates/macros/vitest.config.ts +6 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
- package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
- package/corpus/templates/mail/app/routes/$.tsx +9 -0
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
- package/corpus/templates/mail/app/routes/$view.tsx +47 -1
- package/corpus/templates/mail/app/routes.ts +3 -1
- package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
- package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
- package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
- package/corpus/templates/mail/server/onboarding.ts +66 -18
- package/corpus/templates/mail/vitest.config.ts +6 -1
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/plan/app/routes/settings.tsx +4 -1
- package/corpus/templates/plan/app/routes.ts +3 -1
- package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/plan/netlify.toml +1 -1
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/slides/actions/patch-deck.ts +79 -10
- package/corpus/templates/slides/actions/update-slide.ts +11 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
- package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/slides/app/routes.ts +3 -1
- package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
- package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/slides/tsconfig.json +5 -0
- package/corpus/templates/slides/vitest.config.ts +6 -1
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
- package/corpus/templates/tasks/app/routes.ts +3 -1
- package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/tasks/vitest.config.ts +7 -1
- package/dist/action.d.ts +91 -0
- package/dist/action.js +50 -0
- package/dist/agent/abort-reasons.d.ts +38 -0
- package/dist/agent/abort-reasons.js +49 -0
- package/dist/agent/engine/ai-sdk-engine.js +8 -5
- package/dist/agent/engine/anthropic-engine.js +7 -5
- package/dist/agent/engine/first-event-timeout.d.ts +42 -17
- package/dist/agent/engine/first-event-timeout.js +67 -25
- package/dist/agent/production-agent.d.ts +23 -0
- package/dist/agent/production-agent.js +107 -102
- package/dist/agent/run-loop-with-resume.d.ts +2 -28
- package/dist/agent/run-loop-with-resume.js +25 -40
- package/dist/agent/run-manager.js +5 -4
- package/dist/agent/run-store.d.ts +55 -0
- package/dist/agent/run-store.js +124 -1
- package/dist/agent/tool-search.js +2 -1
- package/dist/agent/types.d.ts +9 -4
- package/dist/app-config/configuration-error.d.ts +11 -0
- package/dist/app-config/configuration-error.js +14 -0
- package/dist/app-config/index.d.ts +1 -0
- package/dist/app-config/index.js +1 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +10 -0
- package/dist/app-config/plugins.d.ts +34 -0
- package/dist/app-config/plugins.js +39 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
- package/dist/app-config/run-lifecycle-invariants.js +18 -25
- package/dist/app-config/schema.d.ts +16 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/chat-threads/schema-migrations.js +20 -0
- package/dist/chat-threads/store.js +21 -4
- package/dist/cli/native-dependencies.d.ts +4 -0
- package/dist/cli/native-dependencies.js +15 -0
- package/dist/client/EnvironmentBadge.d.ts +1 -1
- package/dist/client/EnvironmentBadge.js +40 -5
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -14
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +2 -1
- package/dist/client/agent-page/use-jobs.js +3 -5
- package/dist/client/agent-sidebar-state.js +3 -1
- package/dist/client/blocks/library/code-tabs.js +5 -0
- package/dist/client/blocks/library/code.js +1 -0
- package/dist/client/chat-first/apps-rail.js +2 -2
- package/dist/client/chat-model-groups.d.ts +12 -0
- package/dist/client/chat-model-groups.js +3 -2
- package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
- package/dist/client/integrations/GoogleProductLogo.js +45 -0
- package/dist/client/integrations/index.d.ts +2 -0
- package/dist/client/integrations/index.js +2 -0
- package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
- package/dist/client/integrations/workspace-provider-oauth.js +13 -0
- package/dist/client/resources/mcp-integration-catalog.js +0 -29
- package/dist/client/settings/SettingsTabsPage.js +10 -6
- package/dist/client/sharing/ShareButton.js +11 -2
- package/dist/client/use-chat-models.d.ts +6 -0
- package/dist/client/use-chat-models.js +10 -0
- package/dist/client/use-db-sync.js +27 -9
- package/dist/connections/catalog.d.ts +111 -9
- package/dist/connections/catalog.js +86 -30
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/ddl-guard.d.ts +0 -4
- package/dist/db/ddl-guard.js +46 -0
- package/dist/deploy/build.d.ts +19 -0
- package/dist/deploy/build.js +190 -16
- package/dist/deploy/function-bundle.d.ts +45 -0
- package/dist/deploy/function-bundle.js +337 -0
- package/dist/deploy/workspace-deploy.js +19 -1
- package/dist/eject/workspace-connections.js +4 -0
- package/dist/email-catalog/registry.d.ts +4 -0
- package/dist/email-catalog/registry.js +79 -14
- package/dist/extensions/content-patch.js +14 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/plugin.d.ts +10 -0
- package/dist/integrations/plugin.js +40 -6
- package/dist/jobs/actions/run-automation-now.d.ts +2 -1
- package/dist/jobs/actions/run-automation-now.js +11 -5
- package/dist/jobs/frontmatter.js +53 -2
- package/dist/jobs/run-now.d.ts +11 -1
- package/dist/jobs/run-now.js +42 -7
- package/dist/jobs/scheduler.d.ts +1 -0
- package/dist/jobs/scheduler.js +2 -1
- package/dist/localization/core-messages/ar-SA.js +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts +2 -5
- package/dist/localization/default-messages.js +2 -5
- package/dist/mcp/build-server.d.ts +9 -0
- package/dist/mcp/build-server.js +37 -8
- package/dist/mcp-client/oauth-client.d.ts +7 -0
- package/dist/mcp-client/oauth-client.js +12 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/lifecycle.d.ts +11 -0
- package/dist/oauth-tokens/lifecycle.js +17 -0
- package/dist/oauth-tokens/store.js +7 -0
- package/dist/observability/posthog-ai.d.ts +15 -1
- package/dist/observability/posthog-ai.js +24 -12
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.js +158 -28
- package/dist/onboarding/app-profile.js +2 -2
- package/dist/onboarding/plugin.js +10 -2
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
- package/dist/server/agent-chat/action-filters-a2a.js +48 -9
- package/dist/server/agent-chat-plugin.js +36 -9
- package/dist/server/agent-discovery.js +43 -20
- package/dist/server/auth.js +18 -16
- package/dist/server/beta-opt-out-html.js +45 -4
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +23 -7
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.js +87 -6
- package/dist/server/builder-oauth.d.ts +1 -7
- package/dist/server/builder-oauth.js +80 -163
- package/dist/server/core-routes-plugin.d.ts +29 -0
- package/dist/server/core-routes-plugin.js +100 -20
- package/dist/server/default-plugins.d.ts +18 -0
- package/dist/server/default-plugins.js +22 -0
- package/dist/server/edge.d.ts +1 -0
- package/dist/server/edge.js +1 -0
- package/dist/server/framework-request-handler.js +31 -3
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.js +3 -0
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/onboarding-html.js +37 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.js +72 -20
- package/dist/shared/agent-sidebar-url.d.ts +1 -0
- package/dist/shared/agent-sidebar-url.js +1 -0
- package/dist/shared/environment-lanes.d.ts +2 -0
- package/dist/shared/environment-lanes.js +3 -1
- package/dist/shared/index.d.ts +3 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/surface-visibility.d.ts +31 -0
- package/dist/shared/surface-visibility.js +57 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/chat/app/routes.ts +3 -1
- package/dist/templates/chat/vitest.config.ts +8 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/default/app/routes.ts +3 -1
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/tracking/registry.d.ts +11 -0
- package/dist/tracking/registry.js +5 -2
- package/dist/triggers/actions.js +10 -3
- package/dist/usage/store.js +23 -3
- package/dist/user-profile/actions/get-auth-methods.js +18 -5
- package/dist/vite/client.js +24 -5
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/template-clips-capture-everywhere.mdx +29 -30
- package/docs/content/template-clips-developers.mdx +4 -4
- package/docs/content/template-clips.mdx +3 -1
- package/package.json +2 -2
- package/src/eject/workspace-connections.ts +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/chat/app/routes.ts +3 -1
- package/src/templates/chat/vitest.config.ts +8 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/default/app/routes.ts +3 -1
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
|
@@ -2,8 +2,8 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import Ajv from "ajv";
|
|
3
3
|
import { defineEventHandler, getHeader, setResponseHeader, setResponseStatus, getMethod, } from "h3";
|
|
4
4
|
import { parseA2AAgentActivityPart } from "../a2a/activity.js";
|
|
5
|
-
import { describeToolParameterSignature, isAgentActionStopError, stripUnsupportedSchemaKeywords, } from "../action.js";
|
|
6
|
-
import {
|
|
5
|
+
import { describeToolParameterSignature, isActionHiddenFromEveryAgentSurface, isAgentActionStopError, stripUnsupportedSchemaKeywords, } from "../action.js";
|
|
6
|
+
import { MAX_BACKGROUND_RUN_CONTINUATIONS, MAX_CONSECUTIVE_NO_PROGRESS_CONTINUATIONS, MAX_TURN_WALL_CLOCK_MS, } from "../app-config/run-lifecycle-invariants.js";
|
|
7
7
|
import { readAppState } from "../application-state/script-helpers.js";
|
|
8
8
|
import { isReadOnlyShellCommand } from "../coding-tools/index.js";
|
|
9
9
|
import { getDbExec, isTransientDatabaseError } from "../db/client.js";
|
|
@@ -746,7 +746,6 @@ function maxRetriesForError(err) {
|
|
|
746
746
|
return MAX_RETRIES;
|
|
747
747
|
}
|
|
748
748
|
const TOOL_INPUT_ACTIVITY_INTERVAL_MS = 1500;
|
|
749
|
-
const ACTION_PREPARATION_ZERO_BYTE_RESTART_LIMIT = 2;
|
|
750
749
|
/**
|
|
751
750
|
* How long an attempt must have run before its retry is worth narrating.
|
|
752
751
|
*
|
|
@@ -2187,7 +2186,10 @@ export function actionsToEngineTools(actions) {
|
|
|
2187
2186
|
*/
|
|
2188
2187
|
export async function executeAgentToolCall(options) {
|
|
2189
2188
|
const entry = options.actions[options.name];
|
|
2190
|
-
|
|
2189
|
+
// The caller's registry is the surface: A2A hands this the external one, so
|
|
2190
|
+
// reject only what no surface may run — an MCP-only action is `agentTool:
|
|
2191
|
+
// false` and still legitimately callable here.
|
|
2192
|
+
if (!entry || isActionHiddenFromEveryAgentSurface(entry)) {
|
|
2191
2193
|
return {
|
|
2192
2194
|
status: "failed",
|
|
2193
2195
|
output: `Unknown or unavailable tool: ${options.name}`,
|
|
@@ -3286,12 +3288,22 @@ export async function runAgentLoop(opts) {
|
|
|
3286
3288
|
: 0;
|
|
3287
3289
|
// A per-tool timeout above the chunk's own soft timeout can never fire — the
|
|
3288
3290
|
// chunk boundary always wins — so the 12-minute default is dead code on a
|
|
3289
|
-
// ~40s hosted foreground chunk.
|
|
3290
|
-
//
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3291
|
+
// ~40s hosted foreground chunk.
|
|
3292
|
+
//
|
|
3293
|
+
// TAKEN FROM THE CALLER'S ACTUAL BUDGET, not re-derived. Re-deriving it asked
|
|
3294
|
+
// `resolveRunSoftTimeoutMs` for the generic background ceiling (13 min) even
|
|
3295
|
+
// when the caller was a background AUTOMATION, whose real budget is its own
|
|
3296
|
+
// hard abort minus headroom (10 min − 20s = 9m40s via
|
|
3297
|
+
// `resolveBackgroundAutomationSoftTimeoutMs`). The ceiling came out ABOVE the
|
|
3298
|
+
// run budget, so every per-tool timeout on that path was dead code and the
|
|
3299
|
+
// chunk boundary won instead — which is the exact failure
|
|
3300
|
+
// `RUN_TOOL_TIMEOUT_HEADROOM_MS` exists to prevent, reintroduced by guessing
|
|
3301
|
+
// at a number the caller already knew.
|
|
3302
|
+
const runToolTimeoutCeilingMs = resolveRunToolTimeoutCeilingMs(opts.runSoftTimeoutMs ??
|
|
3303
|
+
resolveRunSoftTimeoutMs(undefined, {
|
|
3304
|
+
useHostedDefault: true,
|
|
3305
|
+
backgroundFunction: isInBackgroundFunctionRuntime(),
|
|
3306
|
+
}));
|
|
3295
3307
|
const toolCallHistory = [];
|
|
3296
3308
|
const sourceSweepToolCallHistory = seedSourceSweepToolCallsFromHistory(messages, actions);
|
|
3297
3309
|
let sourceSweepDelegationGuardActive = hasExhaustedSourceSweepBudget({
|
|
@@ -3495,7 +3507,6 @@ export async function runAgentLoop(opts) {
|
|
|
3495
3507
|
const toolInputBytes = new Map();
|
|
3496
3508
|
let lastToolInputActivityAt = 0;
|
|
3497
3509
|
const activeToolInputs = new Map();
|
|
3498
|
-
let zeroByteToolInputRestart;
|
|
3499
3510
|
let endedForNoProgress = false;
|
|
3500
3511
|
// Bracket the engine call for the run manager's no-progress backstop
|
|
3501
3512
|
// (`inFlightWorkDelta` in run-manager.ts). That backstop measures the
|
|
@@ -3547,48 +3558,55 @@ export async function runAgentLoop(opts) {
|
|
|
3547
3558
|
...(typeof progressBytes === "number" ? { progressBytes } : {}),
|
|
3548
3559
|
});
|
|
3549
3560
|
};
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3561
|
+
/**
|
|
3562
|
+
* The ONLY in-loop stall bound left, and it covers exactly one thing:
|
|
3563
|
+
* a model call whose stream opened and produced NOTHING AT ALL.
|
|
3564
|
+
*
|
|
3565
|
+
* WHAT WAS HERE, AND WHY IT IS GONE. Two 90s watchdogs used to run for
|
|
3566
|
+
* the whole stream — one on silence between engine frames, one on a
|
|
3567
|
+
* tool input whose byte count stopped growing — plus a zero-byte
|
|
3568
|
+
* restart tripwire. Each inferred death from the ABSENCE of a
|
|
3569
|
+
* particular event, and that inference is unsound on this transport:
|
|
3570
|
+
* the Anthropic SDK drops the provider's `ping` keepalives before they
|
|
3571
|
+
* reach any consumer (`core/streaming.js`: `if (sse.event === 'ping')
|
|
3572
|
+
* continue;`, with no opt-out), so a healthy stream mid-generation is
|
|
3573
|
+
* byte-for-byte indistinguishable from a wedged one.
|
|
3574
|
+
*
|
|
3575
|
+
* That is not an edge case, it is normal operation. A tool whose input
|
|
3576
|
+
* is not eagerly streamed emits no `input_json_delta` at all while the
|
|
3577
|
+
* provider composes its arguments, so writing a large file or filing a
|
|
3578
|
+
* long structured result is a content-silent window whose length is set
|
|
3579
|
+
* by the size of the argument. Production bore it out: of 27 one-shot
|
|
3580
|
+
* analyst runs, 2 completed. Guards added for reliability were the
|
|
3581
|
+
* thing taking it away.
|
|
3582
|
+
*
|
|
3583
|
+
* WHAT STILL CATCHES A REAL WEDGE — none of which can fire on
|
|
3584
|
+
* slow-but-healthy work:
|
|
3585
|
+
* • the engine's own first-event abort
|
|
3586
|
+
* (`FIRST_STREAM_EVENT_TIMEOUT_MS`, 120s): a connection that opens
|
|
3587
|
+
* and never speaks
|
|
3588
|
+
* • the engine's total-stream deadline (`STREAM_TOTAL_TIMEOUT_MS`,
|
|
3589
|
+
* 14min): one model call end to end, which is what bounds a socket
|
|
3590
|
+
* that wedges MID-stream on the runtimes with no outer budget
|
|
3591
|
+
* (local dev and self-hosted resolve the soft timeout to 0)
|
|
3592
|
+
* • the run-manager backstop, for the segments OUTSIDE the stream
|
|
3593
|
+
* (`inFlightWorkDelta` suspends it while the stream is open)
|
|
3594
|
+
* • the per-tool timeout, which bounds tool EXECUTION at the tool
|
|
3595
|
+
* • the chunk / run budget, which bounds COST rather than health
|
|
3596
|
+
* • the stale reaper, which bounds worker liveness
|
|
3597
|
+
*
|
|
3598
|
+
* The cap below survives only because it guards the "nothing has
|
|
3599
|
+
* happened yet" window on the clamped hosted FOREGROUND runtime, where
|
|
3600
|
+
* the ~57s platform wall arrives before the engine's 120s bound could.
|
|
3601
|
+
* The first real frame releases it, so long thinking, long tool inputs
|
|
3602
|
+
* and long outputs are all past it by construction.
|
|
3603
|
+
*/
|
|
3604
|
+
const noProgressDeadlineAt = () => {
|
|
3580
3605
|
if (hasReceivedFirstEngineEvent ||
|
|
3581
3606
|
!isClampedForegroundRuntimeForThisCall) {
|
|
3582
|
-
return
|
|
3607
|
+
return Number.POSITIVE_INFINITY;
|
|
3583
3608
|
}
|
|
3584
|
-
return
|
|
3585
|
-
};
|
|
3586
|
-
const noProgressDeadlineAt = () => {
|
|
3587
|
-
const actionDeadlineAt = actionPreparationDeadlineAt();
|
|
3588
|
-
const modelDeadlineAt = modelStreamNoProgressDeadlineAt();
|
|
3589
|
-
return actionDeadlineAt === undefined
|
|
3590
|
-
? modelDeadlineAt
|
|
3591
|
-
: Math.min(actionDeadlineAt, modelDeadlineAt);
|
|
3609
|
+
return (lastModelStreamProgressAt + FOREGROUND_FIRST_MODEL_EVENT_TIMEOUT_MS);
|
|
3592
3610
|
};
|
|
3593
3611
|
const hasNoProgressStalled = () => Date.now() >= noProgressDeadlineAt();
|
|
3594
3612
|
const checkpointNoProgress = () => {
|
|
@@ -3624,6 +3642,14 @@ export async function runAgentLoop(opts) {
|
|
|
3624
3642
|
};
|
|
3625
3643
|
const nextEngineEventWithNoProgressTimeout = async (iterator) => {
|
|
3626
3644
|
const deadlineAt = noProgressDeadlineAt();
|
|
3645
|
+
// No deadline at all is the COMMON case now — every runtime except a
|
|
3646
|
+
// clamped hosted foreground call that has not yet seen its first
|
|
3647
|
+
// frame. Await the iterator directly rather than racing it: a
|
|
3648
|
+
// `setTimeout` of Infinity is coerced to 1ms by Node and would
|
|
3649
|
+
// checkpoint instantly, turning "no bound" into "the tightest bound
|
|
3650
|
+
// there is".
|
|
3651
|
+
if (!Number.isFinite(deadlineAt))
|
|
3652
|
+
return iterator.next();
|
|
3627
3653
|
const timeoutMs = Math.max(0, deadlineAt - Date.now());
|
|
3628
3654
|
if (timeoutMs <= 0) {
|
|
3629
3655
|
checkpointNoProgress();
|
|
@@ -3662,37 +3688,6 @@ export async function runAgentLoop(opts) {
|
|
|
3662
3688
|
bytes,
|
|
3663
3689
|
});
|
|
3664
3690
|
};
|
|
3665
|
-
const resetZeroByteToolInputRestart = (toolName) => {
|
|
3666
|
-
if (!zeroByteToolInputRestart)
|
|
3667
|
-
return;
|
|
3668
|
-
if (!toolName || zeroByteToolInputRestart.toolName === toolName) {
|
|
3669
|
-
zeroByteToolInputRestart = undefined;
|
|
3670
|
-
}
|
|
3671
|
-
};
|
|
3672
|
-
const noteZeroByteToolInputStart = (toolName) => {
|
|
3673
|
-
if (!toolName)
|
|
3674
|
-
return false;
|
|
3675
|
-
const now = Date.now();
|
|
3676
|
-
if (zeroByteToolInputRestart?.toolName === toolName) {
|
|
3677
|
-
zeroByteToolInputRestart = {
|
|
3678
|
-
...zeroByteToolInputRestart,
|
|
3679
|
-
lastStartedAt: now,
|
|
3680
|
-
count: zeroByteToolInputRestart.count + 1,
|
|
3681
|
-
};
|
|
3682
|
-
}
|
|
3683
|
-
else {
|
|
3684
|
-
zeroByteToolInputRestart = {
|
|
3685
|
-
toolName,
|
|
3686
|
-
firstStartedAt: now,
|
|
3687
|
-
lastStartedAt: now,
|
|
3688
|
-
count: 1,
|
|
3689
|
-
};
|
|
3690
|
-
}
|
|
3691
|
-
return (zeroByteToolInputRestart.count >=
|
|
3692
|
-
ACTION_PREPARATION_ZERO_BYTE_RESTART_LIMIT &&
|
|
3693
|
-
now - zeroByteToolInputRestart.firstStartedAt >=
|
|
3694
|
-
ACTION_PREPARATION_NO_PROGRESS_TIMEOUT_MS);
|
|
3695
|
-
};
|
|
3696
3691
|
const eventIterator = eventStream[Symbol.asyncIterator]();
|
|
3697
3692
|
let eventIteratorDone = false;
|
|
3698
3693
|
openModelStreamBracket();
|
|
@@ -3734,7 +3729,6 @@ export async function runAgentLoop(opts) {
|
|
|
3734
3729
|
}
|
|
3735
3730
|
}
|
|
3736
3731
|
if (event.type === "text-delta") {
|
|
3737
|
-
resetZeroByteToolInputRestart();
|
|
3738
3732
|
streamedAssistantText += event.text;
|
|
3739
3733
|
send({ type: "text", text: event.text });
|
|
3740
3734
|
}
|
|
@@ -3758,17 +3752,12 @@ export async function runAgentLoop(opts) {
|
|
|
3758
3752
|
...(event.id ? { id: event.id } : {}),
|
|
3759
3753
|
});
|
|
3760
3754
|
sendToolInputActivity(event.name, key, undefined, true);
|
|
3761
|
-
if (noteZeroByteToolInputStart(event.name)) {
|
|
3762
|
-
checkpointNoProgress();
|
|
3763
|
-
break;
|
|
3764
|
-
}
|
|
3765
3755
|
}
|
|
3766
3756
|
else if (event.type === "tool-input-delta") {
|
|
3767
3757
|
const key = event.id ?? event.name;
|
|
3768
3758
|
const toolName = event.name ??
|
|
3769
3759
|
(event.id ? toolInputNames.get(event.id) : undefined);
|
|
3770
3760
|
let progressBytes;
|
|
3771
|
-
let startedZeroByteInput = false;
|
|
3772
3761
|
if (key) {
|
|
3773
3762
|
const hadByteRecord = toolInputBytes.has(key);
|
|
3774
3763
|
const previous = hadByteRecord
|
|
@@ -3780,12 +3769,6 @@ export async function runAgentLoop(opts) {
|
|
|
3780
3769
|
toolInputBytes.set(key, progressBytes);
|
|
3781
3770
|
if (!hadByteRecord || progressBytes > previous) {
|
|
3782
3771
|
trackActiveToolInput(key, toolName, progressBytes);
|
|
3783
|
-
if (progressBytes > 0) {
|
|
3784
|
-
resetZeroByteToolInputRestart();
|
|
3785
|
-
}
|
|
3786
|
-
else if (!hadByteRecord) {
|
|
3787
|
-
startedZeroByteInput = true;
|
|
3788
|
-
}
|
|
3789
3772
|
}
|
|
3790
3773
|
}
|
|
3791
3774
|
if (event.text) {
|
|
@@ -3797,12 +3780,6 @@ export async function runAgentLoop(opts) {
|
|
|
3797
3780
|
});
|
|
3798
3781
|
}
|
|
3799
3782
|
sendToolInputActivity(toolName, key, progressBytes);
|
|
3800
|
-
if (startedZeroByteInput &&
|
|
3801
|
-
toolName &&
|
|
3802
|
-
noteZeroByteToolInputStart(toolName)) {
|
|
3803
|
-
checkpointNoProgress();
|
|
3804
|
-
break;
|
|
3805
|
-
}
|
|
3806
3783
|
}
|
|
3807
3784
|
else if (event.type === "gateway-heartbeat") {
|
|
3808
3785
|
send({ type: "stream_keepalive" });
|
|
@@ -7801,6 +7778,20 @@ export function createProductionAgentHandler(options) {
|
|
|
7801
7778
|
backgroundFunction: false,
|
|
7802
7779
|
}))
|
|
7803
7780
|
: null;
|
|
7781
|
+
// The budget this run ACTUALLY executes inside, resolved once and used by
|
|
7782
|
+
// both `startRun` (which arms the chunk timer with it) and the agent loop
|
|
7783
|
+
// (which clamps per-tool timeouts under it). Resolving it only inside
|
|
7784
|
+
// `startRun` left the loop to re-derive a generic hosted/background
|
|
7785
|
+
// ceiling, so an app-configured chunk shorter than that ceiling got
|
|
7786
|
+
// per-tool timeouts longer than the chunk containing them — dead code, and
|
|
7787
|
+
// the chunk boundary won instead. `resolveRunSoftTimeoutMs` clamps an
|
|
7788
|
+
// already-resolved number to itself, so passing it back in is a no-op.
|
|
7789
|
+
const resolvedRunSoftTimeoutMs = resolveRunSoftTimeoutMs(selfChainBudget && !selfChainBudget.skipToBoundary
|
|
7790
|
+
? selfChainBudget.softTimeoutMs
|
|
7791
|
+
: options.runSoftTimeoutMs, {
|
|
7792
|
+
useHostedDefault: true,
|
|
7793
|
+
backgroundFunction: runsInBackgroundFunction,
|
|
7794
|
+
});
|
|
7804
7795
|
const startedRun = startRun(runId, effectiveThreadId, async (rawSend, signal) => {
|
|
7805
7796
|
const send = (event) => {
|
|
7806
7797
|
rawSend(event);
|
|
@@ -7895,6 +7886,15 @@ export function createProductionAgentHandler(options) {
|
|
|
7895
7886
|
providerOptions: options.providerOptions,
|
|
7896
7887
|
executionMode: requestMode,
|
|
7897
7888
|
maxIterations: loopSettings.maxIterations,
|
|
7889
|
+
// Same `startRun` chunk and same signal as the main loop, so
|
|
7890
|
+
// the same budget. Left off, the loop re-derives the generic
|
|
7891
|
+
// hosted/background ceiling, which can sit above the chunk
|
|
7892
|
+
// these nested calls actually run inside — and then the
|
|
7893
|
+
// per-tool timeout is unreachable and the chunk boundary
|
|
7894
|
+
// preempts it.
|
|
7895
|
+
...(resolvedRunSoftTimeoutMs > 0
|
|
7896
|
+
? { runSoftTimeoutMs: resolvedRunSoftTimeoutMs }
|
|
7897
|
+
: {}),
|
|
7898
7898
|
});
|
|
7899
7899
|
// Attribute custom-agent sub-calls under their own label
|
|
7900
7900
|
// so the Usage panel separates them from the main chat.
|
|
@@ -8054,6 +8054,13 @@ export function createProductionAgentHandler(options) {
|
|
|
8054
8054
|
priorTurnInputTokens: turnInputTokens,
|
|
8055
8055
|
finalResponseGuard: options.finalResponseGuard,
|
|
8056
8056
|
finalResponseGuardRequestText: messageToPersist,
|
|
8057
|
+
// The chunk this loop is running inside, so a per-tool timeout is
|
|
8058
|
+
// clamped under the budget it can actually spend rather than under a
|
|
8059
|
+
// re-derived generic ceiling. `0` (local dev) keeps the loop's own
|
|
8060
|
+
// fallback.
|
|
8061
|
+
...(resolvedRunSoftTimeoutMs > 0
|
|
8062
|
+
? { runSoftTimeoutMs: resolvedRunSoftTimeoutMs }
|
|
8063
|
+
: {}),
|
|
8057
8064
|
...(options.toolLimits ? { toolLimits: options.toolLimits } : {}),
|
|
8058
8065
|
...(threadId
|
|
8059
8066
|
? { threadId: effectiveThreadId, turnId: effectiveTurnId }
|
|
@@ -8216,9 +8223,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8216
8223
|
// (durable-background worker, plain foreground POST) is unaffected:
|
|
8217
8224
|
// `selfChainBudget` is `null` for them and this falls through to the
|
|
8218
8225
|
// exact prior value.
|
|
8219
|
-
softTimeoutMs:
|
|
8220
|
-
? selfChainBudget.softTimeoutMs
|
|
8221
|
-
: options.runSoftTimeoutMs,
|
|
8226
|
+
softTimeoutMs: resolvedRunSoftTimeoutMs,
|
|
8222
8227
|
useHostedSoftTimeoutDefault: true,
|
|
8223
8228
|
// Lift the soft-timeout clamp to ~13min ONLY when this run is actually
|
|
8224
8229
|
// executing inside a real Netlify `-background` function (15-min budget,
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* Both paths route through `appendAgentLoopContinuation` so the agent sees a
|
|
21
21
|
* uniform "continue" instruction regardless of which recovery fired.
|
|
22
22
|
*/
|
|
23
|
+
import { SERVER_OWNED_ABORT_REASONS, clientAbortReason } from "./abort-reasons.js";
|
|
23
24
|
import type { EngineMessage } from "./engine/types.js";
|
|
24
25
|
import { runAgentLoop, type AgentLoopContinuationReason } from "./production-agent.js";
|
|
25
26
|
import type { ResolveRunSoftTimeoutOptions, RunChunkControl } from "./run-manager.js";
|
|
@@ -38,34 +39,7 @@ export declare function appendDurableContinuationContext(messages: EngineMessage
|
|
|
38
39
|
*/
|
|
39
40
|
export declare const MAX_BACKGROUND_RATE_LIMIT_CONTINUATIONS = 1;
|
|
40
41
|
export declare const BACKGROUND_RATE_LIMIT_CONTINUATION_DELAY_MS = 20000;
|
|
41
|
-
|
|
42
|
-
* Abort reasons the SERVER sets on a run's own controller. Everything else —
|
|
43
|
-
* including any reason a client passes to the abort route — is a user Stop.
|
|
44
|
-
*
|
|
45
|
-
* Kept deliberately short. Each entry is a bound this package owns and can name
|
|
46
|
-
* in a terminal outcome; if you are adding a fourth, check first whether the
|
|
47
|
-
* bound belongs in `run-manager.ts` at all.
|
|
48
|
-
*
|
|
49
|
-
* Exported so the abort route can refuse these words from a client. That check
|
|
50
|
-
* belongs at the boundary where untrusted input enters, not here: by the time a
|
|
51
|
-
* reason reaches an `AbortSignal` it is just a string, and nothing downstream
|
|
52
|
-
* can tell who wrote it.
|
|
53
|
-
*/
|
|
54
|
-
export declare const SERVER_OWNED_ABORT_REASONS: Set<string>;
|
|
55
|
-
/**
|
|
56
|
-
* The abort reason to record for a client-initiated Stop.
|
|
57
|
-
*
|
|
58
|
-
* A caller reaching the abort route is a person pressing Stop, so it must not
|
|
59
|
-
* be able to name a bound only the server can reach: the terminal outcome keys
|
|
60
|
-
* off the abort reason, and a client sending `background_automation_hard_timeout`
|
|
61
|
-
* would file its own Stop as a server-side failure. Anything unrecognised,
|
|
62
|
-
* malformed, or reserved falls back to `"user"`.
|
|
63
|
-
*
|
|
64
|
-
* Normalised here rather than in the route because this is where the meaning of
|
|
65
|
-
* the string is decided — downstream it is just a string, and nothing can tell
|
|
66
|
-
* who wrote it.
|
|
67
|
-
*/
|
|
68
|
-
export declare function clientAbortReason(raw: unknown): string;
|
|
42
|
+
export { SERVER_OWNED_ABORT_REASONS, clientAbortReason };
|
|
69
43
|
/** Machine-readable code carried on the give-up terminal `error` event so the
|
|
70
44
|
* client renders a loud "stopped before finishing" terminal instead of an
|
|
71
45
|
* ambiguous silent stall. Deliberately NOT in the client's auto-recoverable
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* uniform "continue" instruction regardless of which recovery fired.
|
|
22
22
|
*/
|
|
23
23
|
import { MAX_BACKGROUND_RUN_LOOP_CONTINUATIONS, MAX_RUN_LOOP_CONTINUATIONS, } from "../app-config/run-lifecycle-invariants.js";
|
|
24
|
+
import { SERVER_OWNED_ABORT_REASONS, clientAbortReason, } from "./abort-reasons.js";
|
|
24
25
|
import { runAgentLoop, appendAgentLoopContinuation, isResumableEngineError, isTransientProviderRateLimitError, continuationReasonForResumableError, lastUnfinishedPreparingActionToolFromEvents, resolveFinalResponseGuardRequestText, SELF_CHAIN_MIN_CONTINUATION_BUDGET_MS, } from "./production-agent.js";
|
|
25
26
|
import { resolveRunSoftTimeoutMs } from "./run-manager.js";
|
|
26
27
|
import { getCurrentTurnEventsForThread } from "./run-store.js";
|
|
@@ -194,45 +195,10 @@ function waitForBackgroundRateLimitCooldown(signal) {
|
|
|
194
195
|
signal.addEventListener("abort", finish, { once: true });
|
|
195
196
|
});
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
* Kept deliberately short. Each entry is a bound this package owns and can name
|
|
202
|
-
* in a terminal outcome; if you are adding a fourth, check first whether the
|
|
203
|
-
* bound belongs in `run-manager.ts` at all.
|
|
204
|
-
*
|
|
205
|
-
* Exported so the abort route can refuse these words from a client. That check
|
|
206
|
-
* belongs at the boundary where untrusted input enters, not here: by the time a
|
|
207
|
-
* reason reaches an `AbortSignal` it is just a string, and nothing downstream
|
|
208
|
-
* can tell who wrote it.
|
|
209
|
-
*/
|
|
210
|
-
export const SERVER_OWNED_ABORT_REASONS = new Set([
|
|
211
|
-
"no_progress",
|
|
212
|
-
"run_timeout",
|
|
213
|
-
"background_automation_hard_timeout",
|
|
214
|
-
]);
|
|
215
|
-
/**
|
|
216
|
-
* The abort reason to record for a client-initiated Stop.
|
|
217
|
-
*
|
|
218
|
-
* A caller reaching the abort route is a person pressing Stop, so it must not
|
|
219
|
-
* be able to name a bound only the server can reach: the terminal outcome keys
|
|
220
|
-
* off the abort reason, and a client sending `background_automation_hard_timeout`
|
|
221
|
-
* would file its own Stop as a server-side failure. Anything unrecognised,
|
|
222
|
-
* malformed, or reserved falls back to `"user"`.
|
|
223
|
-
*
|
|
224
|
-
* Normalised here rather than in the route because this is where the meaning of
|
|
225
|
-
* the string is decided — downstream it is just a string, and nothing can tell
|
|
226
|
-
* who wrote it.
|
|
227
|
-
*/
|
|
228
|
-
export function clientAbortReason(raw) {
|
|
229
|
-
if (typeof raw !== "string")
|
|
230
|
-
return "user";
|
|
231
|
-
const reason = raw.trim();
|
|
232
|
-
if (!/^[a-z0-9_-]{1,64}$/i.test(reason))
|
|
233
|
-
return "user";
|
|
234
|
-
return SERVER_OWNED_ABORT_REASONS.has(reason.toLowerCase()) ? "user" : reason;
|
|
235
|
-
}
|
|
198
|
+
// Re-exported from the leaf module so existing importers keep working. Callers
|
|
199
|
+
// that need ONLY these two symbols must import `./abort-reasons.js` directly —
|
|
200
|
+
// reaching them through this module drags the whole run loop into their graph.
|
|
201
|
+
export { SERVER_OWNED_ABORT_REASONS, clientAbortReason };
|
|
236
202
|
/** Machine-readable code carried on the give-up terminal `error` event so the
|
|
237
203
|
* client renders a loud "stopped before finishing" terminal instead of an
|
|
238
204
|
* ambiguous silent stall. Deliberately NOT in the client's auto-recoverable
|
|
@@ -268,8 +234,19 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
|
|
|
268
234
|
control) {
|
|
269
235
|
const finalResponseGuardRequestText = opts.finalResponseGuardRequestText ??
|
|
270
236
|
resolveFinalResponseGuardRequestText(opts.messages);
|
|
271
|
-
const stableOpts = { ...opts, finalResponseGuardRequestText };
|
|
272
237
|
const timeoutMs = resolveRunSoftTimeoutMs(softTimeoutMs, timeoutOptions);
|
|
238
|
+
// Hand the loop the budget it is ACTUALLY running inside, so a per-tool
|
|
239
|
+
// timeout is clamped under this chunk rather than under a re-derived generic
|
|
240
|
+
// ceiling. A background automation's budget is its own hard abort minus
|
|
241
|
+
// headroom and is materially smaller than the background chat ceiling; the
|
|
242
|
+
// loop had no way to know that and guessed high, which made every per-tool
|
|
243
|
+
// timeout on that path unreachable. `0` means "no soft-timeout regime"
|
|
244
|
+
// (local dev), where the loop's own fallback is the right answer.
|
|
245
|
+
const stableOpts = {
|
|
246
|
+
...opts,
|
|
247
|
+
finalResponseGuardRequestText,
|
|
248
|
+
...(timeoutMs > 0 ? { runSoftTimeoutMs: timeoutMs } : {}),
|
|
249
|
+
};
|
|
273
250
|
let finalOutcomeReported = false;
|
|
274
251
|
const reportFinalOutcome = (outcome) => {
|
|
275
252
|
if (finalOutcomeReported)
|
|
@@ -475,6 +452,14 @@ control) {
|
|
|
475
452
|
let attemptOutcome;
|
|
476
453
|
const nextUsage = await runAgentLoop({
|
|
477
454
|
...stableOpts,
|
|
455
|
+
// THIS round's budget, not the invocation's. `stableOpts` carries the
|
|
456
|
+
// full `timeoutMs`, but round 2+ runs inside `roundTimeoutMs` — what
|
|
457
|
+
// is left after the earlier rounds spent wall-clock. Clamping a
|
|
458
|
+
// per-tool timeout against the full window puts it above the round
|
|
459
|
+
// that contains it, so the round timer wins and the per-tool timeout
|
|
460
|
+
// is unreachable — the same inversion `RUN_TOOL_TIMEOUT_HEADROOM_MS`
|
|
461
|
+
// exists to prevent, one scope down.
|
|
462
|
+
runSoftTimeoutMs: roundTimeoutMs,
|
|
478
463
|
send,
|
|
479
464
|
signal: controller.signal,
|
|
480
465
|
onOutcome: (outcome) => {
|
|
@@ -140,10 +140,11 @@ export function resolveRunNoProgressTimeoutMs(params) {
|
|
|
140
140
|
* Every pair listed here suspends the no-progress backstop for as long as it is
|
|
141
141
|
* open, so each one MUST be bounded by a watchdog of its own — tool calls by
|
|
142
142
|
* the per-tool timeout, cross-app calls by the A2A poll timeout, the model
|
|
143
|
-
* stream by
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
143
|
+
* stream by the engine's own first-event abort plus the chunk budget (the 90s
|
|
144
|
+
* in-loop watchdog that used to sit here is gone — see
|
|
145
|
+
* run-lifecycle-invariants.ts). A pair added here without SOME bound turns the
|
|
146
|
+
* backstop off for the rest of the run, which is strictly worse than the stall
|
|
147
|
+
* it was meant to catch.
|
|
147
148
|
*
|
|
148
149
|
* Note what that leaves: the model-stream bound covers waiting for the engine,
|
|
149
150
|
* not a hang while the loop processes a frame it already has. Nothing here
|
|
@@ -268,6 +268,43 @@ export declare function insertRun(id: string, threadId: string, turnId?: string,
|
|
|
268
268
|
*/
|
|
269
269
|
dispatchPayload?: string;
|
|
270
270
|
}): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* Which stale window the reaper applied to a row, in ms.
|
|
273
|
+
*
|
|
274
|
+
* MIRRORS `backgroundAwareStaleCutoffSql`, which decides the same thing in SQL
|
|
275
|
+
* because it has to run inside the conditional UPDATE. Kept beside it and
|
|
276
|
+
* covered by a test asserting the three cases agree — a drift here reports the
|
|
277
|
+
* wrong window on a real incident, which is worse than reporting none.
|
|
278
|
+
*/
|
|
279
|
+
export declare function staleWindowMsForRow(row: {
|
|
280
|
+
dispatchMode?: string | null;
|
|
281
|
+
hasDispatchPayload?: boolean;
|
|
282
|
+
maxStaleMs?: number;
|
|
283
|
+
}): number;
|
|
284
|
+
/**
|
|
285
|
+
* The liveness forensics for one reap, as a compact `key=value` line.
|
|
286
|
+
*
|
|
287
|
+
* THE FIELD THAT MATTERS IS `hbAheadOfProgress`. A worker that died takes its
|
|
288
|
+
* heartbeat with it, so heartbeat and last-progress stop together and this is
|
|
289
|
+
* ~0. A worker still running while the agent loop stops producing keeps
|
|
290
|
+
* heartbeating, and this grows without bound — those are opposite bugs that
|
|
291
|
+
* look identical in `agent_runs` today. Production showed runs where the
|
|
292
|
+
* heartbeat ran 3,000s past the last progress; nothing recorded that, so
|
|
293
|
+
* nothing could act on it.
|
|
294
|
+
*
|
|
295
|
+
* Numbers, booleans and an enum only — no prompt, no result, no user content —
|
|
296
|
+
* so this obeys the same privacy rule as event properties and log lines.
|
|
297
|
+
*/
|
|
298
|
+
export declare function describeStaleReap(row: {
|
|
299
|
+
startedAt?: number | null;
|
|
300
|
+
heartbeatAt?: number | null;
|
|
301
|
+
lastProgressAt?: number | null;
|
|
302
|
+
inFlightSince?: number | null;
|
|
303
|
+
dispatchMode?: string | null;
|
|
304
|
+
hasDispatchPayload?: boolean;
|
|
305
|
+
maxStaleMs?: number;
|
|
306
|
+
now: number;
|
|
307
|
+
}): string;
|
|
271
308
|
/**
|
|
272
309
|
* Atomically claim a background-dispatched run for processing. The foreground
|
|
273
310
|
* POST inserts the run row with `dispatch_mode = 'background'`; the FIRST
|
|
@@ -480,6 +517,24 @@ export declare const RUN_DIAG_STAGE: {
|
|
|
480
517
|
* no boundary previously recorded anywhere.
|
|
481
518
|
*/
|
|
482
519
|
readonly runBoundaryReached: "run_boundary_reached";
|
|
520
|
+
/**
|
|
521
|
+
* A stale reaper flipped this run to `errored`. Detail carries the liveness
|
|
522
|
+
* forensics — see `describeStaleReap`.
|
|
523
|
+
*
|
|
524
|
+
* WHY THIS EXISTS. `stale_run` is the single largest terminal outcome on the
|
|
525
|
+
* one-shot automation path (14 of 27 runs in one production deployment) and
|
|
526
|
+
* the row records nothing about WHY: `error_detail` is a fixed sentence for
|
|
527
|
+
* every reap, so a correct reap and a false one are indistinguishable after
|
|
528
|
+
* the fact. Every question worth asking needed a number nobody stored — was
|
|
529
|
+
* the worker dead, or was it heartbeating happily while the loop stopped
|
|
530
|
+
* producing? which of the three stale windows fired? was the in-flight grace
|
|
531
|
+
* in play? One production run heartbeated 3,309s past a 600s hard abort and
|
|
532
|
+
* there is no way to tell from the row what kept it alive.
|
|
533
|
+
*
|
|
534
|
+
* Diagnostics only: nothing reads this to make a decision, and it cannot
|
|
535
|
+
* change whether a row is reaped.
|
|
536
|
+
*/
|
|
537
|
+
readonly staleRunReaped: "stale_run_reaped";
|
|
483
538
|
};
|
|
484
539
|
export type RunDiagStage = (typeof RUN_DIAG_STAGE)[keyof typeof RUN_DIAG_STAGE];
|
|
485
540
|
/**
|