@agent-native/core 0.113.0 → 0.114.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 +164 -0
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +11 -0
- package/corpus/core/README.md +61 -174
- package/corpus/core/agent-native.eject.json +164 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +38 -0
- package/corpus/core/docs/content/package-lifecycle.mdx +54 -4
- package/corpus/core/package.json +15 -2
- package/corpus/core/src/cli/eject.ts +1594 -0
- package/corpus/core/src/cli/index.ts +16 -0
- package/corpus/core/src/client/index.ts +4 -0
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +8 -2
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +7 -2
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +17 -3
- package/corpus/core/src/client/resources/index.ts +19 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +9 -1
- package/corpus/core/src/client/resources/runtime.ts +1 -0
- package/corpus/core/src/client/setup-connections/catalog.ts +6 -0
- package/corpus/core/src/client/setup-connections/index.ts +1 -0
- package/corpus/core/src/client/setup-connections/runtime.ts +1 -0
- package/corpus/core/src/connections/catalog.ts +41 -24
- package/corpus/core/src/connections/index.ts +1 -0
- package/corpus/core/src/connections/runtime.ts +1 -0
- package/corpus/core/src/eject/provider-api-definitions.ts +193 -0
- package/corpus/core/src/eject/remote-mcp-presets.ts +137 -0
- package/corpus/core/src/eject/setup-readiness-ui.tsx +29 -0
- package/corpus/core/src/eject/workspace-connections.ts +92 -0
- package/corpus/core/src/index.ts +1 -0
- package/corpus/core/src/integrations/adapter-overrides.ts +12 -0
- package/corpus/core/src/integrations/eject/messaging-adapters.ts +85 -0
- package/corpus/core/src/integrations/index.ts +5 -1
- package/corpus/core/src/integrations/plugin.ts +34 -12
- package/corpus/core/src/integrations/runtime.ts +1 -0
- package/corpus/core/src/integrations/types.ts +3 -1
- package/corpus/core/src/package-lifecycle/eject-manifest.ts +345 -0
- package/corpus/core/src/package-lifecycle/index.ts +1 -0
- package/corpus/core/src/provider-api/index.ts +46 -12
- package/corpus/core/src/provider-api/runtime.ts +1 -0
- package/corpus/core/src/setup-connections/index.ts +1 -0
- package/corpus/core/src/shared/merge-by-id.ts +14 -0
- package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/corpus/core/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/core/src/templates/default/AGENTS.md +6 -5
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/corpus/core/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/core/src/templates/headless/AGENTS.md +5 -4
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/core/src/templates/workspace-core/AGENTS.md +4 -4
- package/corpus/core/src/templates/workspace-root/AGENTS.md +4 -4
- package/corpus/core/src/vite/client.ts +25 -2
- package/corpus/templates/analytics/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/assets/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/brain/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/brain/actions/remediate-legacy-capture-audiences.ts +167 -0
- package/corpus/templates/brain/app/lib/brain-chat-readiness.ts +6 -0
- package/corpus/templates/brain/app/routes/_index.tsx +8 -0
- package/corpus/templates/brain/app/routes.ts +1 -0
- package/corpus/templates/brain/changelog/2026-07-19-ask-starts-immediately-when-builder-s-managed-ai-connection-.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-19-slack-and-granola-backfills-now-process-captures-concurrentl.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-19-source-review-settings-now-control-knowledge-approval.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-19-the-manage-agent-page-now-opens-correctly-from-brain-navigat.md +6 -0
- package/corpus/templates/brain/server/db/schema.ts +3 -0
- package/corpus/templates/brain/server/lib/brain.ts +41 -2
- package/corpus/templates/brain/server/lib/connectors.ts +379 -113
- package/corpus/templates/brain/server/lib/meeting-audience.ts +38 -0
- package/corpus/templates/brain/server/plugins/db.ts +10 -0
- package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +6 -4
- package/corpus/templates/calendar/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/corpus/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/chat/AGENTS.md +3 -2
- package/corpus/templates/clips/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/content/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/design/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/dispatch/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/forms/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/macros/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/mail/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/plan/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/slides/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/corpus/templates/tasks/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/corpus/templates/tasks/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/corpus/toolkit/CHANGELOG.md +6 -0
- package/corpus/toolkit/agent-native.eject.json +411 -0
- package/corpus/toolkit/package.json +5 -2
- package/dist/cli/eject.d.ts +21 -0
- package/dist/cli/eject.d.ts.map +1 -0
- package/dist/cli/eject.js +1145 -0
- package/dist/cli/eject.js.map +1 -0
- package/dist/cli/index.js +15 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +4 -3
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.js +3 -3
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts +4 -3
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +2 -2
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts +4 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +9 -7
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/index.d.ts +3 -0
- package/dist/client/resources/index.d.ts.map +1 -1
- package/dist/client/resources/index.js +3 -0
- package/dist/client/resources/index.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +2 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +6 -2
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/runtime.d.ts +2 -0
- package/dist/client/resources/runtime.d.ts.map +1 -0
- package/dist/client/resources/runtime.js +2 -0
- package/dist/client/resources/runtime.js.map +1 -0
- package/dist/client/setup-connections/catalog.d.ts +2 -0
- package/dist/client/setup-connections/catalog.d.ts.map +1 -0
- package/dist/client/setup-connections/catalog.js +7 -0
- package/dist/client/setup-connections/catalog.js.map +1 -0
- package/dist/client/setup-connections/index.d.ts +1 -0
- package/dist/client/setup-connections/index.d.ts.map +1 -1
- package/dist/client/setup-connections/index.js +1 -0
- package/dist/client/setup-connections/index.js.map +1 -1
- package/dist/client/setup-connections/runtime.d.ts +2 -0
- package/dist/client/setup-connections/runtime.d.ts.map +1 -0
- package/dist/client/setup-connections/runtime.js +2 -0
- package/dist/client/setup-connections/runtime.js.map +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +5 -3
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +16 -8
- package/dist/connections/catalog.js.map +1 -1
- package/dist/connections/index.d.ts +1 -1
- package/dist/connections/index.d.ts.map +1 -1
- package/dist/connections/index.js +1 -1
- package/dist/connections/index.js.map +1 -1
- package/dist/connections/runtime.d.ts +2 -0
- package/dist/connections/runtime.d.ts.map +1 -0
- package/dist/connections/runtime.js +2 -0
- package/dist/connections/runtime.js.map +1 -0
- package/dist/eject/provider-api-definitions.d.ts +34 -0
- package/dist/eject/provider-api-definitions.d.ts.map +1 -0
- package/dist/eject/provider-api-definitions.js +88 -0
- package/dist/eject/provider-api-definitions.js.map +1 -0
- package/dist/eject/remote-mcp-presets.d.ts +17 -0
- package/dist/eject/remote-mcp-presets.d.ts.map +1 -0
- package/dist/eject/remote-mcp-presets.js +81 -0
- package/dist/eject/remote-mcp-presets.js.map +1 -0
- package/dist/eject/setup-readiness-ui.d.ts +7 -0
- package/dist/eject/setup-readiness-ui.d.ts.map +1 -0
- package/dist/eject/setup-readiness-ui.js +13 -0
- package/dist/eject/setup-readiness-ui.js.map +1 -0
- package/dist/eject/workspace-connections.d.ts +11 -0
- package/dist/eject/workspace-connections.d.ts.map +1 -0
- package/dist/eject/workspace-connections.js +47 -0
- package/dist/eject/workspace-connections.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapter-overrides.d.ts +3 -0
- package/dist/integrations/adapter-overrides.d.ts.map +1 -0
- package/dist/integrations/adapter-overrides.js +7 -0
- package/dist/integrations/adapter-overrides.js.map +1 -0
- package/dist/integrations/eject/messaging-adapters.d.ts +12 -0
- package/dist/integrations/eject/messaging-adapters.d.ts.map +1 -0
- package/dist/integrations/eject/messaging-adapters.js +49 -0
- package/dist/integrations/eject/messaging-adapters.js.map +1 -0
- package/dist/integrations/index.d.ts +3 -2
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +2 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts +32 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +19 -12
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/runtime.d.ts +2 -0
- package/dist/integrations/runtime.d.ts.map +1 -0
- package/dist/integrations/runtime.js +2 -0
- package/dist/integrations/runtime.js.map +1 -0
- package/dist/integrations/types.d.ts +3 -1
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/package-lifecycle/eject-manifest.d.ts +43 -0
- package/dist/package-lifecycle/eject-manifest.d.ts.map +1 -0
- package/dist/package-lifecycle/eject-manifest.js +219 -0
- package/dist/package-lifecycle/eject-manifest.js.map +1 -0
- package/dist/package-lifecycle/index.d.ts +1 -0
- package/dist/package-lifecycle/index.d.ts.map +1 -1
- package/dist/package-lifecycle/index.js +1 -0
- package/dist/package-lifecycle/index.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts +6 -2
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +25 -12
- package/dist/provider-api/index.js.map +1 -1
- package/dist/provider-api/runtime.d.ts +2 -0
- package/dist/provider-api/runtime.d.ts.map +1 -0
- package/dist/provider-api/runtime.js +2 -0
- package/dist/provider-api/runtime.js.map +1 -0
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/setup-connections/index.d.ts +1 -1
- package/dist/setup-connections/index.d.ts.map +1 -1
- package/dist/setup-connections/index.js +1 -1
- package/dist/setup-connections/index.js.map +1 -1
- package/dist/shared/merge-by-id.d.ts +5 -0
- package/dist/shared/merge-by-id.d.ts.map +1 -0
- package/dist/shared/merge-by-id.js +7 -0
- package/dist/shared/merge-by-id.js.map +1 -0
- package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/dist/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/dist/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/dist/templates/chat/AGENTS.md +3 -2
- package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/dist/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/dist/templates/default/AGENTS.md +6 -5
- package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/dist/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/dist/templates/headless/AGENTS.md +5 -4
- package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
- package/dist/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/dist/templates/workspace-core/AGENTS.md +4 -4
- package/dist/templates/workspace-root/AGENTS.md +4 -4
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +22 -2
- package/dist/vite/client.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +38 -0
- package/docs/content/package-lifecycle.mdx +54 -4
- package/package.json +15 -2
- package/src/a2a/agent-card.ts +83 -0
- package/src/a2a/artifact-response.ts +1648 -0
- package/src/a2a/auth-policy.ts +66 -0
- package/src/a2a/caller-auth.ts +102 -0
- package/src/a2a/client.ts +876 -0
- package/src/a2a/correlation.ts +50 -0
- package/src/a2a/handlers.ts +1285 -0
- package/src/a2a/index.ts +50 -0
- package/src/a2a/invoke.ts +348 -0
- package/src/a2a/response-text.ts +53 -0
- package/src/a2a/server.ts +586 -0
- package/src/a2a/task-store.ts +917 -0
- package/src/a2a/types.ts +221 -0
- package/src/a2a-claims.ts +52 -0
- package/src/action-change-marker.ts +74 -0
- package/src/action-ui.ts +38 -0
- package/src/action.ts +1406 -0
- package/src/adapters/cli/index.ts +6 -0
- package/src/adapters/cli/registry.ts +73 -0
- package/src/adapters/cli/shell-adapter.ts +92 -0
- package/src/adapters/cli/types.ts +27 -0
- package/src/agent/action-continuation-guidance.ts +38 -0
- package/src/agent/app-model-defaults.ts +201 -0
- package/src/agent/context-xray/actions/context-evict.ts +56 -0
- package/src/agent/context-xray/actions/context-manifest-get.ts +75 -0
- package/src/agent/context-xray/actions/context-pin.ts +56 -0
- package/src/agent/context-xray/actions/context-preview-get.ts +134 -0
- package/src/agent/context-xray/actions/context-report.ts +75 -0
- package/src/agent/context-xray/actions/context-restore.ts +51 -0
- package/src/agent/context-xray/actions/errors.ts +40 -0
- package/src/agent/context-xray/apply-directives.ts +137 -0
- package/src/agent/context-xray/directives-store.ts +178 -0
- package/src/agent/context-xray/identity.ts +37 -0
- package/src/agent/context-xray/manifest.ts +284 -0
- package/src/agent/context-xray/migrations.ts +32 -0
- package/src/agent/context-xray/plugin.ts +23 -0
- package/src/agent/context-xray/schema.ts +17 -0
- package/src/agent/context-xray/segments.ts +194 -0
- package/src/agent/context-xray/tokenize.ts +93 -0
- package/src/agent/default-model.ts +5 -0
- package/src/agent/durable-background.ts +547 -0
- package/src/agent/engine/ai-sdk-engine.ts +565 -0
- package/src/agent/engine/anthropic-engine.ts +320 -0
- package/src/agent/engine/builder-engine.ts +1110 -0
- package/src/agent/engine/builder-gateway-headers.ts +44 -0
- package/src/agent/engine/builtin.ts +122 -0
- package/src/agent/engine/context-directives-transform.ts +73 -0
- package/src/agent/engine/continuation-dispatch-retry.ts +168 -0
- package/src/agent/engine/credential-errors.ts +69 -0
- package/src/agent/engine/index.ts +54 -0
- package/src/agent/engine/openai-compatible-endpoint.ts +25 -0
- package/src/agent/engine/output-tokens.ts +181 -0
- package/src/agent/engine/provider-env-vars.ts +69 -0
- package/src/agent/engine/registry.ts +853 -0
- package/src/agent/engine/tool-call-journal-seed.ts +85 -0
- package/src/agent/engine/translate-ai-sdk.ts +407 -0
- package/src/agent/engine/translate-anthropic.ts +611 -0
- package/src/agent/engine/types.ts +310 -0
- package/src/agent/harness/acp-adapter.ts +893 -0
- package/src/agent/harness/acp-builtin.ts +70 -0
- package/src/agent/harness/ai-sdk-adapter.ts +509 -0
- package/src/agent/harness/background.ts +365 -0
- package/src/agent/harness/builtin.ts +50 -0
- package/src/agent/harness/index.ts +86 -0
- package/src/agent/harness/lifecycle.ts +498 -0
- package/src/agent/harness/registry.ts +97 -0
- package/src/agent/harness/runner.ts +182 -0
- package/src/agent/harness/store.ts +466 -0
- package/src/agent/harness/translate.ts +130 -0
- package/src/agent/harness/types.ts +129 -0
- package/src/agent/index.ts +32 -0
- package/src/agent/loop-settings.ts +186 -0
- package/src/agent/model-config.ts +363 -0
- package/src/agent/observational-memory/compactor.ts +78 -0
- package/src/agent/observational-memory/config.ts +78 -0
- package/src/agent/observational-memory/index.ts +79 -0
- package/src/agent/observational-memory/internal-run.ts +89 -0
- package/src/agent/observational-memory/message-text.ts +49 -0
- package/src/agent/observational-memory/migrations.ts +44 -0
- package/src/agent/observational-memory/observer.ts +128 -0
- package/src/agent/observational-memory/plugin.ts +35 -0
- package/src/agent/observational-memory/prompts.ts +53 -0
- package/src/agent/observational-memory/read.ts +131 -0
- package/src/agent/observational-memory/reflector.ts +119 -0
- package/src/agent/observational-memory/schema.ts +48 -0
- package/src/agent/observational-memory/store.ts +275 -0
- package/src/agent/observational-memory/types.ts +65 -0
- package/src/agent/processors.ts +209 -0
- package/src/agent/production-agent.ts +8254 -0
- package/src/agent/run-loop-with-resume.ts +394 -0
- package/src/agent/run-manager.ts +1825 -0
- package/src/agent/run-ownership.ts +75 -0
- package/src/agent/run-store.ts +2601 -0
- package/src/agent/runtime-context.ts +169 -0
- package/src/agent/thread-data-builder.ts +1584 -0
- package/src/agent/tool-call-journal.ts +368 -0
- package/src/agent/tool-error-redaction.ts +52 -0
- package/src/agent/tool-result-images.ts +178 -0
- package/src/agent/tool-search.ts +376 -0
- package/src/agent/types.ts +372 -0
- package/src/agent-native/index.ts +198 -0
- package/src/agent-web/config.ts +253 -0
- package/src/agent-web/generator.ts +382 -0
- package/src/agent-web/index.ts +36 -0
- package/src/appearance/actions/change-appearance.ts +35 -0
- package/src/application-state/emitter.ts +81 -0
- package/src/application-state/handlers.ts +121 -0
- package/src/application-state/index.ts +44 -0
- package/src/application-state/script-helpers.ts +155 -0
- package/src/application-state/store.ts +274 -0
- package/src/assets/branding/agent-native.icon/Assets/background.svg +3 -0
- package/src/assets/branding/agent-native.icon/Assets/foreground.svg +12 -0
- package/src/assets/branding/agent-native.icon/icon.json +49 -0
- package/src/assets/branding/favicon.png +0 -0
- package/src/assets/branding/favicon.svg +1 -0
- package/src/assets/branding/icon-on-dark.svg +10 -0
- package/src/assets/branding/icon-on-light.svg +10 -0
- package/src/assets/branding/mac-app-icon.svg +1 -0
- package/src/assets/branding/slack-bot/agent-native-1024.png +0 -0
- package/src/assets/branding/slack-bot/agent-native-512.png +0 -0
- package/src/assets/branding/tray-icon.svg +6 -0
- package/src/assets/branding/wordmark-on-dark.svg +21 -0
- package/src/assets/branding/wordmark-on-light.svg +21 -0
- package/src/assets/fonts/LICENSE_LIBERATION +96 -0
- package/src/assets/fonts/LICENSE_NOTO_NASKH_ARABIC +93 -0
- package/src/assets/fonts/LiberationSans-Bold.ttf +0 -0
- package/src/assets/fonts/LiberationSans-Regular.ttf +0 -0
- package/src/assets/fonts/NotoNaskhArabic-Variable.ttf +0 -0
- package/src/audit/actions/export-audit-events.ts +162 -0
- package/src/audit/actions/get-audit-event.ts +24 -0
- package/src/audit/actions/list-audit-events.ts +66 -0
- package/src/audit/cleanup-job.ts +100 -0
- package/src/audit/config.ts +90 -0
- package/src/audit/index.ts +43 -0
- package/src/audit/record.ts +180 -0
- package/src/audit/redact.ts +109 -0
- package/src/audit/store.ts +346 -0
- package/src/audit/types.ts +141 -0
- package/src/automation/index.ts +802 -0
- package/src/brand-kit/brand-signals.ts +124 -0
- package/src/brand-kit/fig/index.ts +64 -0
- package/src/brand-kit/index.ts +72 -0
- package/src/brand-kit/types.ts +113 -0
- package/src/browser-sessions/actions.ts +302 -0
- package/src/browser-sessions/routes.ts +234 -0
- package/src/browser-sessions/store.ts +679 -0
- package/src/browser-sessions/types.ts +84 -0
- package/src/changelog/parse.ts +328 -0
- package/src/chat-threads/emitter.ts +22 -0
- package/src/chat-threads/schema.ts +43 -0
- package/src/chat-threads/store.ts +1311 -0
- package/src/checkpoints/index.ts +15 -0
- package/src/checkpoints/service.ts +142 -0
- package/src/checkpoints/store.ts +153 -0
- package/src/cli/add.ts +425 -0
- package/src/cli/agent.ts +424 -0
- package/src/cli/agents.ts +122 -0
- package/src/cli/app-skill.ts +1455 -0
- package/src/cli/atomic-json-file.ts +324 -0
- package/src/cli/audit-agent-web.ts +324 -0
- package/src/cli/changelog.ts +199 -0
- package/src/cli/claude-code-participant.ts +515 -0
- package/src/cli/code-agent-commands.ts +270 -0
- package/src/cli/code-agent-connector.ts +1109 -0
- package/src/cli/code-agent-executor.ts +1970 -0
- package/src/cli/code-agent-output-smoother.ts +140 -0
- package/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
- package/src/cli/code-agent-runs.ts +548 -0
- package/src/cli/code.ts +1805 -0
- package/src/cli/codex-cli-participant.ts +496 -0
- package/src/cli/connect.ts +2714 -0
- package/src/cli/content-local.ts +442 -0
- package/src/cli/context-xray-local.ts +2193 -0
- package/src/cli/create-workspace.ts +30 -0
- package/src/cli/create.ts +2247 -0
- package/src/cli/deploy-build.ts +50 -0
- package/src/cli/design-connect.ts +3187 -0
- package/src/cli/doctor.ts +472 -0
- package/src/cli/eject.ts +1594 -0
- package/src/cli/eval.ts +134 -0
- package/src/cli/gateway-helpers.ts +70 -0
- package/src/cli/index.ts +1217 -0
- package/src/cli/info.ts +105 -0
- package/src/cli/invoke.ts +288 -0
- package/src/cli/mcp-config-writers.ts +857 -0
- package/src/cli/mcp.ts +594 -0
- package/src/cli/migrate.ts +1813 -0
- package/src/cli/migration-codemod.ts +646 -0
- package/src/cli/multi-frontier-runs.ts +1952 -0
- package/src/cli/package-lifecycle.ts +823 -0
- package/src/cli/plan-blocks.ts +143 -0
- package/src/cli/plan-local.ts +3189 -0
- package/src/cli/plan-publish-store.ts +138 -0
- package/src/cli/pr-visual-recap-workflow.ts +2 -0
- package/src/cli/recap.ts +5 -0
- package/src/cli/setup-agents.ts +120 -0
- package/src/cli/skills-content/assets-skill.ts +83 -0
- package/src/cli/skills-content/canvas.ts +153 -0
- package/src/cli/skills-content/connection.ts +52 -0
- package/src/cli/skills-content/content-skill.ts +120 -0
- package/src/cli/skills-content/design-exploration-skill.ts +118 -0
- package/src/cli/skills-content/design-visual-edit-skill.ts +228 -0
- package/src/cli/skills-content/document-quality.ts +196 -0
- package/src/cli/skills-content/exemplar.ts +69 -0
- package/src/cli/skills-content/help.ts +77 -0
- package/src/cli/skills-content/index.ts +22 -0
- package/src/cli/skills-content/local-files.ts +100 -0
- package/src/cli/skills-content/plan-setup-auth.ts +80 -0
- package/src/cli/skills-content/visual-plan-skill.ts +493 -0
- package/src/cli/skills-content/visual-recap-skill.ts +553 -0
- package/src/cli/skills-content/visualize-repo-skill.ts +93 -0
- package/src/cli/skills-content/wireframe.ts +349 -0
- package/src/cli/skills.ts +4340 -0
- package/src/cli/sync-builder-starter-manifest.ts +631 -0
- package/src/cli/telemetry.ts +136 -0
- package/src/cli/templates-meta.ts +269 -0
- package/src/cli/upgrade.ts +956 -0
- package/src/cli/visualize-repo.ts +715 -0
- package/src/cli/workspace-dev.ts +1486 -0
- package/src/cli/workspacify.ts +258 -0
- package/src/client/AgentAskPopover.tsx +89 -0
- package/src/client/AgentChatHome.tsx +66 -0
- package/src/client/AgentNative.tsx +161 -0
- package/src/client/AgentNativeEmbedded.tsx +288 -0
- package/src/client/AgentNativeFrame.tsx +151 -0
- package/src/client/AgentPanel.tsx +3437 -0
- package/src/client/AgentTaskCard.tsx +273 -0
- package/src/client/AppearancePicker.tsx +79 -0
- package/src/client/AssistantChat.tsx +5793 -0
- package/src/client/ClientOnly.tsx +22 -0
- package/src/client/CommandMenu.tsx +726 -0
- package/src/client/ConnectBuilderCard.tsx +390 -0
- package/src/client/DefaultSpinner.tsx +47 -0
- package/src/client/ErrorBoundary.tsx +359 -0
- package/src/client/ErrorReportActions.tsx +69 -0
- package/src/client/FeedbackButton.tsx +553 -0
- package/src/client/HighlightedCodeBlock.tsx +173 -0
- package/src/client/IframeEmbed.tsx +151 -0
- package/src/client/KeepTabOpenNotice.tsx +181 -0
- package/src/client/MultiTabAssistantChat.tsx +2576 -0
- package/src/client/NewWorkspaceAppFlow.tsx +525 -0
- package/src/client/PoweredByBadge.tsx +284 -0
- package/src/client/RunStuckBanner.tsx +431 -0
- package/src/client/StarfieldBackground.tsx +466 -0
- package/src/client/Turnstile.tsx +125 -0
- package/src/client/active-run-state.ts +139 -0
- package/src/client/agent-chat/index.ts +279 -0
- package/src/client/agent-chat-adapter.ts +3692 -0
- package/src/client/agent-chat.ts +1233 -0
- package/src/client/agent-engine-key.ts +122 -0
- package/src/client/agent-page/AgentContextTab.tsx +487 -0
- package/src/client/agent-page/AgentEmptyState.tsx +44 -0
- package/src/client/agent-page/AgentJobsTab.tsx +441 -0
- package/src/client/agent-page/AgentTabFrame.tsx +39 -0
- package/src/client/agent-page/AgentTabsPage.tsx +1096 -0
- package/src/client/agent-page/types.ts +18 -0
- package/src/client/agent-page/use-jobs.ts +150 -0
- package/src/client/agent-sidebar-state.ts +166 -0
- package/src/client/analytics/index.ts +40 -0
- package/src/client/analytics-session.ts +70 -0
- package/src/client/analytics.ts +1757 -0
- package/src/client/api-path.ts +124 -0
- package/src/client/app-providers.tsx +230 -0
- package/src/client/appearance.ts +130 -0
- package/src/client/application-state.ts +154 -0
- package/src/client/assistant-ui-recovery.tsx +205 -0
- package/src/client/automation/index.ts +4 -0
- package/src/client/automation.ts +22 -0
- package/src/client/blocks/AiEditableField.tsx +30 -0
- package/src/client/blocks/BlockView.tsx +145 -0
- package/src/client/blocks/RegistryBlockDataProvider.tsx +121 -0
- package/src/client/blocks/SchemaBlockEditor.tsx +457 -0
- package/src/client/blocks/agent.ts +95 -0
- package/src/client/blocks/code-block-direction.ts +21 -0
- package/src/client/blocks/index.ts +308 -0
- package/src/client/blocks/library/AnnotatedCodeBlock.tsx +710 -0
- package/src/client/blocks/library/ApiEndpointBlock.tsx +1120 -0
- package/src/client/blocks/library/DataModelBlock.tsx +775 -0
- package/src/client/blocks/library/DiffBlock.tsx +1854 -0
- package/src/client/blocks/library/FileTreeBlock.tsx +868 -0
- package/src/client/blocks/library/HighlightedCode.tsx +260 -0
- package/src/client/blocks/library/JsonExplorerBlock.tsx +608 -0
- package/src/client/blocks/library/MermaidBlock.tsx +362 -0
- package/src/client/blocks/library/OpenApiSpecBlock.tsx +998 -0
- package/src/client/blocks/library/annotated-code.config.ts +101 -0
- package/src/client/blocks/library/annotation-rail.tsx +1020 -0
- package/src/client/blocks/library/api-endpoint.config.ts +207 -0
- package/src/client/blocks/library/block-copy.ts +399 -0
- package/src/client/blocks/library/callout.config.ts +57 -0
- package/src/client/blocks/library/callout.tsx +149 -0
- package/src/client/blocks/library/checklist.config.ts +56 -0
- package/src/client/blocks/library/checklist.tsx +208 -0
- package/src/client/blocks/library/code-filename-label.tsx +59 -0
- package/src/client/blocks/library/code-highlight.tsx +178 -0
- package/src/client/blocks/library/code-tabs.config.ts +70 -0
- package/src/client/blocks/library/code-tabs.tsx +606 -0
- package/src/client/blocks/library/code.config.ts +69 -0
- package/src/client/blocks/library/code.tsx +440 -0
- package/src/client/blocks/library/columns.config.ts +85 -0
- package/src/client/blocks/library/columns.tsx +334 -0
- package/src/client/blocks/library/data-model.config.ts +152 -0
- package/src/client/blocks/library/dev-doc-ui.tsx +191 -0
- package/src/client/blocks/library/diagram.config.ts +222 -0
- package/src/client/blocks/library/diagram.tsx +958 -0
- package/src/client/blocks/library/diff.config.ts +115 -0
- package/src/client/blocks/library/file-tree.config.ts +92 -0
- package/src/client/blocks/library/html.config.ts +79 -0
- package/src/client/blocks/library/html.tsx +258 -0
- package/src/client/blocks/library/json-explorer.config.ts +74 -0
- package/src/client/blocks/library/mermaid.config.ts +49 -0
- package/src/client/blocks/library/narrow-container.tsx +37 -0
- package/src/client/blocks/library/openapi-spec.config.ts +66 -0
- package/src/client/blocks/library/question-form.config.ts +127 -0
- package/src/client/blocks/library/question-form.tsx +944 -0
- package/src/client/blocks/library/sanitize-html.ts +343 -0
- package/src/client/blocks/library/server-specs.ts +338 -0
- package/src/client/blocks/library/specs.tsx +308 -0
- package/src/client/blocks/library/table.config.ts +61 -0
- package/src/client/blocks/library/table.tsx +449 -0
- package/src/client/blocks/library/tabs.config.ts +96 -0
- package/src/client/blocks/library/tabs.tsx +665 -0
- package/src/client/blocks/library/wireframe-icons.ts +210 -0
- package/src/client/blocks/library/wireframe-kit.tsx +1850 -0
- package/src/client/blocks/library/wireframe.config.ts +539 -0
- package/src/client/blocks/library/wireframe.tsx +535 -0
- package/src/client/blocks/mdx.ts +364 -0
- package/src/client/blocks/provider.tsx +51 -0
- package/src/client/blocks/registry.ts +83 -0
- package/src/client/blocks/schema-form/introspect.ts +201 -0
- package/src/client/blocks/server.ts +170 -0
- package/src/client/blocks/types.ts +415 -0
- package/src/client/browser-session-bridge.ts +548 -0
- package/src/client/browser-tab-id.ts +36 -0
- package/src/client/builder-frame.ts +194 -0
- package/src/client/builder-mark.tsx +21 -0
- package/src/client/changelog/Changelog.tsx +333 -0
- package/src/client/changelog/index.ts +1 -0
- package/src/client/chat/ChatHistoryList.tsx +7 -0
- package/src/client/chat/attachment-adapters.ts +426 -0
- package/src/client/chat/connectors.ts +1579 -0
- package/src/client/chat/index.ts +160 -0
- package/src/client/chat/markdown-renderer.tsx +693 -0
- package/src/client/chat/message-components.tsx +1326 -0
- package/src/client/chat/repo-helpers.ts +281 -0
- package/src/client/chat/run-recovery.tsx +994 -0
- package/src/client/chat/runtime.ts +1810 -0
- package/src/client/chat/tool-call-display.tsx +1270 -0
- package/src/client/chat/tool-render-registry.tsx +144 -0
- package/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
- package/src/client/chat/use-reconnect-reader-owner.ts +28 -0
- package/src/client/chat/widgets/DataChartRenderer.tsx +242 -0
- package/src/client/chat/widgets/DataChartWidget.tsx +51 -0
- package/src/client/chat/widgets/DataInsightsWidget.tsx +59 -0
- package/src/client/chat/widgets/DataTableWidget.tsx +240 -0
- package/src/client/chat/widgets/InlineExtensionWidget.tsx +60 -0
- package/src/client/chat/widgets/builtin-tool-renderers.tsx +213 -0
- package/src/client/chat/widgets/data-widget-types.ts +1 -0
- package/src/client/chat/widgets/inline-extension-result.ts +86 -0
- package/src/client/chat-model-groups.ts +171 -0
- package/src/client/chat-thread-url.ts +11 -0
- package/src/client/chat-view-transition.ts +213 -0
- package/src/client/client-action.ts +21 -0
- package/src/client/client-bootstrap.ts +7 -0
- package/src/client/client-surface.ts +41 -0
- package/src/client/clipboard.ts +89 -0
- package/src/client/code-agent-chat-adapter.ts +537 -0
- package/src/client/collab/index.ts +60 -0
- package/src/client/command-navigation/index.ts +15 -0
- package/src/client/comments-review/index.ts +1 -0
- package/src/client/components/AgentPresenceChip.tsx +4 -0
- package/src/client/components/ApiKeySettings.tsx +309 -0
- package/src/client/components/CodeAgentIndicator.tsx +59 -0
- package/src/client/components/CodeRequiredDialog.tsx +470 -0
- package/src/client/components/LiveCursorOverlay.tsx +5 -0
- package/src/client/components/MissingKeyCard.tsx +61 -0
- package/src/client/components/PresenceBar.tsx +4 -0
- package/src/client/components/RecentEditHighlights.tsx +4 -0
- package/src/client/components/RemoteSelectionRings.tsx +5 -0
- package/src/client/components/icons/AgentNativeIcon.tsx +46 -0
- package/src/client/components/ui/dialog.tsx +1 -0
- package/src/client/components/ui/dropdown-menu.tsx +1 -0
- package/src/client/components/ui/hover-card.tsx +1 -0
- package/src/client/components/ui/message-scroller.tsx +131 -0
- package/src/client/components/ui/popover.tsx +1 -0
- package/src/client/components/ui/sheet.tsx +1 -0
- package/src/client/components/ui/tooltip.tsx +1 -0
- package/src/client/composer/index.ts +11 -0
- package/src/client/composer/runtime-adapters.tsx +123 -0
- package/src/client/composer/use-mention-search.ts +7 -0
- package/src/client/composer/wired-components.tsx +53 -0
- package/src/client/context-xray/ContextMeter.tsx +124 -0
- package/src/client/context-xray/ContextSegmentRow.tsx +27 -0
- package/src/client/context-xray/ContextTreemap.tsx +24 -0
- package/src/client/context-xray/ContextXRayPanel.tsx +59 -0
- package/src/client/context-xray/SegmentProvenancePopover.tsx +18 -0
- package/src/client/context-xray/format.ts +27 -0
- package/src/client/conversation/AgentConversation.tsx +555 -0
- package/src/client/conversation/code-agent-transcript.ts +283 -0
- package/src/client/conversation/index.ts +22 -0
- package/src/client/conversation/types.ts +85 -0
- package/src/client/conversation/use-near-bottom-autoscroll.ts +278 -0
- package/src/client/create-query-client.ts +86 -0
- package/src/client/db-admin/DataGrid.tsx +551 -0
- package/src/client/db-admin/DbAdminPage.tsx +218 -0
- package/src/client/db-admin/DevDatabaseLink.tsx +16 -0
- package/src/client/db-admin/EditableCell.tsx +451 -0
- package/src/client/db-admin/FilterBar.tsx +203 -0
- package/src/client/db-admin/ResultsGrid.tsx +114 -0
- package/src/client/db-admin/RowSidePanel.tsx +337 -0
- package/src/client/db-admin/SqlEditor.tsx +840 -0
- package/src/client/db-admin/TableBrowser.tsx +212 -0
- package/src/client/db-admin/TableEditor.tsx +760 -0
- package/src/client/db-admin/cell-format.ts +246 -0
- package/src/client/db-admin/changeset.ts +296 -0
- package/src/client/db-admin/export-utils.ts +78 -0
- package/src/client/db-admin/index.ts +33 -0
- package/src/client/db-admin/sql-storage.ts +134 -0
- package/src/client/db-admin/storage.ts +68 -0
- package/src/client/db-admin/useAgentSync.ts +226 -0
- package/src/client/db-admin/useDbAdmin.ts +294 -0
- package/src/client/dev-overlay/DevOverlay.tsx +576 -0
- package/src/client/dev-overlay/builtins.ts +40 -0
- package/src/client/dev-overlay/index.ts +23 -0
- package/src/client/dev-overlay/registry.ts +67 -0
- package/src/client/dev-overlay/types.ts +64 -0
- package/src/client/dev-overlay/use-dev-option.ts +78 -0
- package/src/client/dev-overlay/use-dev-overlay-shortcut.ts +31 -0
- package/src/client/dynamic-suggestions.ts +455 -0
- package/src/client/embed-auth.ts +544 -0
- package/src/client/embed.ts +54 -0
- package/src/client/error-capture.ts +690 -0
- package/src/client/error-format.ts +211 -0
- package/src/client/error-reporting.ts +100 -0
- package/src/client/extensions/AgentNativeExtensionFrame.e2e-host.tsx +136 -0
- package/src/client/extensions/AgentNativeExtensionFrame.tsx +708 -0
- package/src/client/extensions/EmbeddedExtension.tsx +604 -0
- package/src/client/extensions/ExtensionEditor.tsx +450 -0
- package/src/client/extensions/ExtensionQueryErrorState.tsx +47 -0
- package/src/client/extensions/ExtensionSlot.tsx +345 -0
- package/src/client/extensions/ExtensionViewer.tsx +1502 -0
- package/src/client/extensions/ExtensionViewerPage.tsx +32 -0
- package/src/client/extensions/ExtensionsListPage.tsx +432 -0
- package/src/client/extensions/ExtensionsSidebarSection.tsx +1259 -0
- package/src/client/extensions/InlineExtensionFrame.tsx +660 -0
- package/src/client/extensions/agent-native-extension-runtime.ts +495 -0
- package/src/client/extensions/delete-extension.ts +76 -0
- package/src/client/extensions/extension-load-error.ts +26 -0
- package/src/client/extensions/extension-order.ts +49 -0
- package/src/client/extensions/extension-popularity.ts +61 -0
- package/src/client/extensions/iframe-bridge.ts +377 -0
- package/src/client/extensions/index.ts +84 -0
- package/src/client/extensions/portable-extension.ts +712 -0
- package/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
- package/src/client/feature-flags/helpers.ts +77 -0
- package/src/client/feature-flags/index.ts +13 -0
- package/src/client/feature-flags/types.ts +29 -0
- package/src/client/feature-flags/use-feature-flag.ts +26 -0
- package/src/client/feedback-context.ts +90 -0
- package/src/client/frame-protocol.ts +168 -0
- package/src/client/frame.ts +329 -0
- package/src/client/guided-questions.tsx +1152 -0
- package/src/client/history/VersionHistoryPanel.tsx +175 -0
- package/src/client/history/index.ts +21 -0
- package/src/client/history/use-history.ts +114 -0
- package/src/client/hooks/index.ts +46 -0
- package/src/client/host/index.ts +170 -0
- package/src/client/host-bridge.ts +1272 -0
- package/src/client/host-tools.ts +190 -0
- package/src/client/i18n.tsx +798 -0
- package/src/client/index.ts +370 -0
- package/src/client/integrations/IntegrationCard.tsx +186 -0
- package/src/client/integrations/IntegrationsPanel.tsx +633 -0
- package/src/client/integrations/api.ts +295 -0
- package/src/client/integrations/index.ts +29 -0
- package/src/client/integrations/useIntegrationStatus.ts +52 -0
- package/src/client/mcp-app-host.ts +720 -0
- package/src/client/mcp-apps/McpAppRenderer.tsx +760 -0
- package/src/client/navigation/index.ts +54 -0
- package/src/client/notifications/NotificationsBell.tsx +383 -0
- package/src/client/notifications/index.ts +1 -0
- package/src/client/observability/ObservabilityDashboard.tsx +890 -0
- package/src/client/observability/ThumbsFeedback.tsx +160 -0
- package/src/client/observability/index.ts +20 -0
- package/src/client/observability/useObservability.ts +266 -0
- package/src/client/onboarding/OnboardingBanner.tsx +73 -0
- package/src/client/onboarding/OnboardingPanel.tsx +1036 -0
- package/src/client/onboarding/SetupButton.tsx +64 -0
- package/src/client/onboarding/index.ts +25 -0
- package/src/client/onboarding/use-onboarding.ts +164 -0
- package/src/client/onboarding/use-preview-mode.ts +40 -0
- package/src/client/org/InvitationBanner.tsx +148 -0
- package/src/client/org/OrgSwitcher.tsx +754 -0
- package/src/client/org/RequireActiveOrg.tsx +337 -0
- package/src/client/org/TeamPage.tsx +1432 -0
- package/src/client/org/hooks.ts +359 -0
- package/src/client/org/index.ts +70 -0
- package/src/client/org/workspace-app-links.ts +367 -0
- package/src/client/org-team/index.ts +1 -0
- package/src/client/progress/RunsTray.tsx +680 -0
- package/src/client/progress/index.ts +1 -0
- package/src/client/require-session.tsx +142 -0
- package/src/client/resources/BuiltinCapabilityDetail.tsx +258 -0
- package/src/client/resources/McpConnectionSuggestion.tsx +276 -0
- package/src/client/resources/McpIntegrationDialog.tsx +808 -0
- package/src/client/resources/McpServerDetail.tsx +230 -0
- package/src/client/resources/ResourceEditor.tsx +872 -0
- package/src/client/resources/ResourceTree.tsx +860 -0
- package/src/client/resources/ResourcesPanel.tsx +1960 -0
- package/src/client/resources/index.ts +25 -0
- package/src/client/resources/mcp-integration-catalog.ts +771 -0
- package/src/client/resources/mcp-integration-logos.ts +108 -0
- package/src/client/resources/runtime.ts +1 -0
- package/src/client/resources/use-builtin-capabilities.ts +113 -0
- package/src/client/resources/use-mcp-servers.ts +217 -0
- package/src/client/resources/use-resources.ts +402 -0
- package/src/client/review/ReviewCommentComposer.tsx +123 -0
- package/src/client/review/ReviewStatusBadge.tsx +39 -0
- package/src/client/review/ReviewThreadPanel.tsx +625 -0
- package/src/client/review/index.ts +38 -0
- package/src/client/review/use-review.ts +186 -0
- package/src/client/route-chunk-recovery/index.ts +1 -0
- package/src/client/route-chunk-recovery.ts +331 -0
- package/src/client/route-state.ts +455 -0
- package/src/client/route-warmup.tsx +543 -0
- package/src/client/session-replay-iframe.e2e-host.tsx +100 -0
- package/src/client/session-replay.ts +3417 -0
- package/src/client/settings/AgentsSection.tsx +441 -0
- package/src/client/settings/AutomationsSection.tsx +516 -0
- package/src/client/settings/BackgroundAgentSection.tsx +189 -0
- package/src/client/settings/BrowserSection.tsx +110 -0
- package/src/client/settings/DemoModeSection.tsx +48 -0
- package/src/client/settings/SecretsSection.tsx +875 -0
- package/src/client/settings/SettingsPanel.tsx +3162 -0
- package/src/client/settings/SettingsSection.tsx +283 -0
- package/src/client/settings/SettingsTabsPage.tsx +592 -0
- package/src/client/settings/UsageSection.tsx +401 -0
- package/src/client/settings/VoiceTranscriptionSection.tsx +960 -0
- package/src/client/settings/agent-settings-search.ts +220 -0
- package/src/client/settings/index.ts +27 -0
- package/src/client/settings/useBuilderStatus.ts +1055 -0
- package/src/client/setup-connections/BuilderConnectCard.tsx +89 -0
- package/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
- package/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
- package/src/client/setup-connections/catalog.ts +6 -0
- package/src/client/setup-connections/index.ts +47 -0
- package/src/client/setup-connections/runtime.ts +1 -0
- package/src/client/sharing/ShareButton.tsx +1748 -0
- package/src/client/sharing/ShareDialog.tsx +846 -0
- package/src/client/sharing/VisibilityBadge.tsx +4 -0
- package/src/client/sharing/index.ts +2 -0
- package/src/client/sse-event-processor.ts +2002 -0
- package/src/client/terminal/AgentTerminal.tsx +488 -0
- package/src/client/terminal/index.ts +7 -0
- package/src/client/theme.ts +27 -0
- package/src/client/tombstone/agent-presence-chip.ts +17 -0
- package/src/client/tombstone/editor.ts +265 -0
- package/src/client/tombstone/live-cursor-overlay.ts +21 -0
- package/src/client/tombstone/presence-bar.ts +17 -0
- package/src/client/tombstone/recent-edit-highlights.ts +17 -0
- package/src/client/tombstone/remote-selection-rings.ts +21 -0
- package/src/client/tombstone/rich-markdown-editor.ts +265 -0
- package/src/client/tombstone/ui-dialog.ts +49 -0
- package/src/client/tombstone/ui-dropdown-menu.ts +69 -0
- package/src/client/tombstone/ui-hover-card.ts +21 -0
- package/src/client/tombstone/ui-popover.ts +25 -0
- package/src/client/tombstone/ui-sheet.ts +49 -0
- package/src/client/tombstone/ui-tooltip.ts +29 -0
- package/src/client/tombstone/visual-style-controls.ts +61 -0
- package/src/client/tool-cells/BashCell.tsx +164 -0
- package/src/client/tool-cells/EditCell.tsx +303 -0
- package/src/client/tool-cells/FilesChangedSummary.tsx +208 -0
- package/src/client/tool-cells/WriteCell.tsx +145 -0
- package/src/client/tool-cells/index.ts +7 -0
- package/src/client/tool-display.ts +41 -0
- package/src/client/track.ts +57 -0
- package/src/client/transcription/BuilderTranscriptionCta.tsx +120 -0
- package/src/client/transcription/use-live-transcription.ts +292 -0
- package/src/client/ui/index.ts +55 -0
- package/src/client/uploads/index.ts +6 -0
- package/src/client/uploads/upload-editor-image.ts +79 -0
- package/src/client/uploads/use-upload-resource.ts +24 -0
- package/src/client/url-scrub.ts +51 -0
- package/src/client/use-action.ts +766 -0
- package/src/client/use-agent-chat-context.ts +63 -0
- package/src/client/use-agent-chat-home-handoff.ts +207 -0
- package/src/client/use-agent-chat.ts +53 -0
- package/src/client/use-agent-engine-configured.ts +211 -0
- package/src/client/use-avatar.ts +127 -0
- package/src/client/use-change-version.ts +150 -0
- package/src/client/use-chat-models.ts +252 -0
- package/src/client/use-chat-threads.ts +1262 -0
- package/src/client/use-db-sync.ts +1112 -0
- package/src/client/use-demo-mode-status.ts +30 -0
- package/src/client/use-dev-mode.ts +177 -0
- package/src/client/use-external-value.ts +40 -0
- package/src/client/use-pausing-interval.ts +65 -0
- package/src/client/use-pinch-zoom.ts +202 -0
- package/src/client/use-run-stuck-detection.ts +427 -0
- package/src/client/use-send-to-agent-chat.ts +85 -0
- package/src/client/use-session.ts +114 -0
- package/src/client/utils.ts +7 -0
- package/src/client/visual-style-controls.tsx +1 -0
- package/src/client/vite-dev-recovery-script.ts +226 -0
- package/src/client/voice-provider-status.ts +44 -0
- package/src/client/widgets/index.ts +41 -0
- package/src/code-agents/background-controller.ts +398 -0
- package/src/code-agents/background-run.ts +156 -0
- package/src/code-agents/index.ts +95 -0
- package/src/code-agents/prompt-attachments.ts +39 -0
- package/src/code-agents/transcript-normalizer.ts +750 -0
- package/src/code-agents/transcript-order.ts +73 -0
- package/src/coding-tools/index.ts +742 -0
- package/src/coding-tools/run-code.ts +1662 -0
- package/src/coding-tools/sandbox/adapter.ts +82 -0
- package/src/coding-tools/sandbox/background.ts +406 -0
- package/src/coding-tools/sandbox/executions-store.ts +517 -0
- package/src/coding-tools/sandbox/index.ts +132 -0
- package/src/coding-tools/sandbox/local-child-process-adapter.ts +217 -0
- package/src/collab/agent-identity.ts +5 -0
- package/src/collab/agent-presence.ts +341 -0
- package/src/collab/awareness-store.ts +196 -0
- package/src/collab/awareness.ts +317 -0
- package/src/collab/client-struct.ts +366 -0
- package/src/collab/client.ts +1205 -0
- package/src/collab/emitter.ts +31 -0
- package/src/collab/follow-mode.ts +107 -0
- package/src/collab/index.ts +151 -0
- package/src/collab/json-to-yjs.ts +504 -0
- package/src/collab/presence.ts +207 -0
- package/src/collab/recent-edits.ts +215 -0
- package/src/collab/routes.ts +191 -0
- package/src/collab/storage.ts +228 -0
- package/src/collab/struct-routes.ts +133 -0
- package/src/collab/text-to-yjs.ts +79 -0
- package/src/collab/undo.ts +432 -0
- package/src/collab/xml-ops.ts +68 -0
- package/src/collab/ydoc-manager.ts +544 -0
- package/src/command-navigation/actions.ts +100 -0
- package/src/command-navigation/index.ts +12 -0
- package/src/comments-review/index.ts +1 -0
- package/src/connections/catalog.ts +451 -0
- package/src/connections/index.ts +48 -0
- package/src/connections/reader.ts +911 -0
- package/src/connections/runtime.ts +1 -0
- package/src/credentials/index.ts +187 -0
- package/src/data-programs/actions.ts +335 -0
- package/src/data-programs/contract.ts +284 -0
- package/src/data-programs/execute.ts +693 -0
- package/src/data-programs/index.ts +72 -0
- package/src/data-programs/schema.ts +148 -0
- package/src/data-programs/store.ts +755 -0
- package/src/data-widgets/index.ts +376 -0
- package/src/db/client.ts +1627 -0
- package/src/db/create-get-db.ts +579 -0
- package/src/db/ddl-guard.ts +302 -0
- package/src/db/drizzle-config.ts +190 -0
- package/src/db/ensure-additive-columns.ts +430 -0
- package/src/db/index.ts +57 -0
- package/src/db/migrations.ts +691 -0
- package/src/db/request-telemetry.ts +154 -0
- package/src/db/runtime-diagnostics.ts +331 -0
- package/src/db/schema.ts +121 -0
- package/src/db/widen-columns.ts +75 -0
- package/src/db-admin/agent-tools.ts +202 -0
- package/src/db-admin/index.ts +26 -0
- package/src/db-admin/operations.ts +803 -0
- package/src/db-admin/routes.ts +174 -0
- package/src/db-admin/types.ts +110 -0
- package/src/demo/browser-state.ts +47 -0
- package/src/demo/fetch-interceptor.ts +175 -0
- package/src/demo/redact.ts +575 -0
- package/src/deploy/build.ts +3935 -0
- package/src/deploy/immutable-assets.ts +65 -0
- package/src/deploy/route-discovery.ts +458 -0
- package/src/deploy/workspace-core.ts +282 -0
- package/src/deploy/workspace-deploy.ts +1488 -0
- package/src/eject/provider-api-definitions.ts +193 -0
- package/src/eject/remote-mcp-presets.ts +137 -0
- package/src/eject/setup-readiness-ui.tsx +29 -0
- package/src/eject/workspace-connections.ts +92 -0
- package/src/embedding/agent.ts +159 -0
- package/src/embedding/bridge.ts +297 -0
- package/src/embedding/index.ts +43 -0
- package/src/embedding/protocol.ts +185 -0
- package/src/embedding/react.tsx +319 -0
- package/src/embeddings/index.ts +233 -0
- package/src/eval/agent-runner.ts +210 -0
- package/src/eval/define-eval.ts +55 -0
- package/src/eval/index.ts +49 -0
- package/src/eval/report.ts +75 -0
- package/src/eval/runner.ts +369 -0
- package/src/eval/scorer.ts +244 -0
- package/src/eval/types.ts +188 -0
- package/src/event-bus/bus.ts +140 -0
- package/src/event-bus/index.ts +3 -0
- package/src/event-bus/registry.ts +79 -0
- package/src/event-bus/types.ts +29 -0
- package/src/extensions/actions.ts +1636 -0
- package/src/extensions/change-marker.ts +54 -0
- package/src/extensions/content-patch.ts +468 -0
- package/src/extensions/fetch-tool.ts +461 -0
- package/src/extensions/html-shell.ts +803 -0
- package/src/extensions/local.ts +462 -0
- package/src/extensions/path.ts +40 -0
- package/src/extensions/proxy-security.ts +171 -0
- package/src/extensions/routes.ts +1080 -0
- package/src/extensions/schema.ts +269 -0
- package/src/extensions/session-replay-iframe.ts +131 -0
- package/src/extensions/slots/routes.ts +126 -0
- package/src/extensions/slots/schema.ts +87 -0
- package/src/extensions/slots/store.ts +450 -0
- package/src/extensions/store.ts +1347 -0
- package/src/extensions/theme.ts +114 -0
- package/src/extensions/url-safety.ts +316 -0
- package/src/extensions/web-content.ts +663 -0
- package/src/extensions/web-search-tool.ts +437 -0
- package/src/feature-flags/a2a-action-route.ts +56 -0
- package/src/feature-flags/actions/get-feature-flags.ts +24 -0
- package/src/feature-flags/actions/list-feature-flags.ts +69 -0
- package/src/feature-flags/actions/set-feature-flag.ts +89 -0
- package/src/feature-flags/index.ts +21 -0
- package/src/feature-flags/permissions.ts +53 -0
- package/src/feature-flags/plugin.ts +44 -0
- package/src/feature-flags/registry.ts +96 -0
- package/src/feature-flags/store.ts +176 -0
- package/src/file-upload/actions/upload-image.ts +213 -0
- package/src/file-upload/builder.ts +431 -0
- package/src/file-upload/index.ts +24 -0
- package/src/file-upload/pre-upload-attachments.ts +305 -0
- package/src/file-upload/registry.ts +125 -0
- package/src/file-upload/types.ts +89 -0
- package/src/guards/db-tool-scoping.ts +129 -0
- package/src/guards/index.ts +23 -0
- package/src/guards/no-drizzle-push.ts +116 -0
- package/src/guards/no-env-credentials.ts +229 -0
- package/src/guards/no-env-mutation.ts +114 -0
- package/src/guards/no-localhost-fallback.ts +124 -0
- package/src/guards/no-unscoped-credentials.ts +227 -0
- package/src/guards/no-unscoped-queries.ts +834 -0
- package/src/guards/scan-utils.ts +105 -0
- package/src/guards/types.ts +30 -0
- package/src/history/actions/create-resource-version.ts +92 -0
- package/src/history/actions/get-resource-version.ts +60 -0
- package/src/history/actions/list-resource-history.ts +53 -0
- package/src/history/actions/list-resource-versions.ts +43 -0
- package/src/history/actions/restore-resource-version.ts +96 -0
- package/src/history/index.ts +26 -0
- package/src/history/registry.ts +111 -0
- package/src/history/store.ts +379 -0
- package/src/history/types.ts +69 -0
- package/src/index.browser.ts +155 -0
- package/src/index.ts +408 -0
- package/src/ingestion/docx.ts +158 -0
- package/src/ingestion/figma-node-to-html.ts +1860 -0
- package/src/ingestion/figma.ts +548 -0
- package/src/ingestion/index.ts +107 -0
- package/src/ingestion/media.ts +264 -0
- package/src/ingestion/notion.ts +121 -0
- package/src/ingestion/office.ts +213 -0
- package/src/ingestion/orchestration.ts +160 -0
- package/src/ingestion/pptx.ts +331 -0
- package/src/ingestion/selection.ts +81 -0
- package/src/ingestion/website.ts +151 -0
- package/src/integrations/a2a-continuation-marker.ts +2 -0
- package/src/integrations/a2a-continuation-processor.ts +888 -0
- package/src/integrations/a2a-continuations-store.ts +643 -0
- package/src/integrations/adapter-overrides.ts +12 -0
- package/src/integrations/adapters/discord.ts +364 -0
- package/src/integrations/adapters/email.ts +1164 -0
- package/src/integrations/adapters/google-docs.ts +371 -0
- package/src/integrations/adapters/index.ts +29 -0
- package/src/integrations/adapters/microsoft-teams.ts +413 -0
- package/src/integrations/adapters/slack.ts +1914 -0
- package/src/integrations/adapters/telegram.ts +386 -0
- package/src/integrations/adapters/whatsapp.ts +358 -0
- package/src/integrations/awaiting-input-store.ts +130 -0
- package/src/integrations/catalog.ts +571 -0
- package/src/integrations/computer-supervision-store.ts +423 -0
- package/src/integrations/computer-supervision.ts +213 -0
- package/src/integrations/config-store.ts +131 -0
- package/src/integrations/controls-store.ts +187 -0
- package/src/integrations/eject/messaging-adapters.ts +85 -0
- package/src/integrations/google-docs-poller.ts +671 -0
- package/src/integrations/identity-links-store.ts +210 -0
- package/src/integrations/identity.ts +196 -0
- package/src/integrations/index.ts +220 -0
- package/src/integrations/installations-store.ts +677 -0
- package/src/integrations/integration-memory.ts +187 -0
- package/src/integrations/internal-token.ts +106 -0
- package/src/integrations/pending-tasks-retry-job.ts +286 -0
- package/src/integrations/pending-tasks-store.ts +468 -0
- package/src/integrations/plugin.ts +3048 -0
- package/src/integrations/remote-commands-store.ts +690 -0
- package/src/integrations/remote-devices-store.ts +492 -0
- package/src/integrations/remote-json-safety.ts +127 -0
- package/src/integrations/remote-push-delivery-job.ts +48 -0
- package/src/integrations/remote-push-delivery.ts +370 -0
- package/src/integrations/remote-push-store.ts +664 -0
- package/src/integrations/remote-retry-job.ts +55 -0
- package/src/integrations/remote-run-events-store.ts +222 -0
- package/src/integrations/remote-types.ts +186 -0
- package/src/integrations/runtime.ts +1 -0
- package/src/integrations/scope-store.ts +498 -0
- package/src/integrations/slack-manifest.ts +78 -0
- package/src/integrations/slack-oauth.ts +344 -0
- package/src/integrations/task-queue-stats.ts +144 -0
- package/src/integrations/thread-mapping-store.ts +134 -0
- package/src/integrations/types.ts +485 -0
- package/src/integrations/usage-budget-store.ts +906 -0
- package/src/integrations/webhook-delivery.ts +55 -0
- package/src/integrations/webhook-handler.ts +1939 -0
- package/src/jobs/actions/list-recurring-jobs.ts +105 -0
- package/src/jobs/actions/manage-recurring-job.ts +85 -0
- package/src/jobs/cron.ts +126 -0
- package/src/jobs/index.ts +9 -0
- package/src/jobs/scheduler.ts +703 -0
- package/src/jobs/tools.ts +367 -0
- package/src/local-artifacts/index.ts +1372 -0
- package/src/localization/actions/get-localization-preference.ts +24 -0
- package/src/localization/actions/set-localization-preference.ts +32 -0
- package/src/localization/default-messages.ts +1009 -0
- package/src/localization/index.ts +2 -0
- package/src/localization/server.ts +131 -0
- package/src/localization/shared.ts +208 -0
- package/src/mcp/actions/call-mcp-tool.ts +19 -0
- package/src/mcp/actions/create-org-service-token.ts +87 -0
- package/src/mcp/actions/list-mcp-tools.ts +18 -0
- package/src/mcp/actions/list-org-service-tokens.ts +44 -0
- package/src/mcp/actions/revoke-org-service-token.ts +30 -0
- package/src/mcp/actions/service-token-access.ts +121 -0
- package/src/mcp/ask-app-inline-tasks.ts +125 -0
- package/src/mcp/build-server.ts +2356 -0
- package/src/mcp/builtin-tools.ts +1506 -0
- package/src/mcp/connect-route.ts +1460 -0
- package/src/mcp/connect-store.ts +680 -0
- package/src/mcp/embed-app.ts +2051 -0
- package/src/mcp/embed-route.ts +84 -0
- package/src/mcp/external-agent-policy.ts +18 -0
- package/src/mcp/index.ts +47 -0
- package/src/mcp/oauth-route.ts +1016 -0
- package/src/mcp/oauth-store.ts +581 -0
- package/src/mcp/oauth-token.ts +227 -0
- package/src/mcp/org-directory.ts +343 -0
- package/src/mcp/route-paths.ts +34 -0
- package/src/mcp/screen-memory-stdio.ts +290 -0
- package/src/mcp/server.ts +507 -0
- package/src/mcp/stdio.ts +328 -0
- package/src/mcp/workspace-resolve.ts +261 -0
- package/src/mcp-client/app-api.ts +136 -0
- package/src/mcp-client/app-result.ts +64 -0
- package/src/mcp-client/builtin-capabilities.ts +146 -0
- package/src/mcp-client/builtin-store.ts +93 -0
- package/src/mcp-client/config.ts +281 -0
- package/src/mcp-client/errors.ts +54 -0
- package/src/mcp-client/hub-client.ts +172 -0
- package/src/mcp-client/hub-routes.ts +198 -0
- package/src/mcp-client/index.ts +504 -0
- package/src/mcp-client/manager.ts +968 -0
- package/src/mcp-client/oauth-client.ts +462 -0
- package/src/mcp-client/oauth-routes.ts +307 -0
- package/src/mcp-client/remote-store.ts +674 -0
- package/src/mcp-client/remote-url.ts +97 -0
- package/src/mcp-client/routes.ts +1093 -0
- package/src/mcp-client/screen-memory-local.ts +461 -0
- package/src/mcp-client/tool-policy.ts +182 -0
- package/src/mcp-client/visibility.ts +56 -0
- package/src/mcp-client/workspace-servers.ts +379 -0
- package/src/navigation/index.ts +170 -0
- package/src/notifications/actions.ts +151 -0
- package/src/notifications/channels.ts +410 -0
- package/src/notifications/index.ts +22 -0
- package/src/notifications/registry.ts +216 -0
- package/src/notifications/routes.ts +106 -0
- package/src/notifications/store.ts +236 -0
- package/src/notifications/types.ts +52 -0
- package/src/oauth-tokens/google-refresh.ts +175 -0
- package/src/oauth-tokens/index.ts +15 -0
- package/src/oauth-tokens/store.ts +384 -0
- package/src/observability/cleanup-job.ts +124 -0
- package/src/observability/evals.ts +507 -0
- package/src/observability/experiments.ts +359 -0
- package/src/observability/feedback.ts +332 -0
- package/src/observability/hosted-model-experiment.ts +118 -0
- package/src/observability/index.ts +62 -0
- package/src/observability/plugin.ts +31 -0
- package/src/observability/routes.ts +431 -0
- package/src/observability/sentiment.ts +261 -0
- package/src/observability/store.ts +1347 -0
- package/src/observability/traces.ts +789 -0
- package/src/observability/tracing.ts +157 -0
- package/src/observability/tracking-identity.ts +55 -0
- package/src/observability/types.ts +211 -0
- package/src/onboarding/default-steps.ts +428 -0
- package/src/onboarding/index.ts +22 -0
- package/src/onboarding/plugin.ts +262 -0
- package/src/onboarding/registry.ts +47 -0
- package/src/onboarding/types.ts +96 -0
- package/src/org/accept-pending.ts +98 -0
- package/src/org/auto-join-domain.ts +113 -0
- package/src/org/context.ts +614 -0
- package/src/org/free-email-providers.ts +124 -0
- package/src/org/handlers.ts +1153 -0
- package/src/org/index.ts +63 -0
- package/src/org/migrations.ts +105 -0
- package/src/org/permissions.ts +30 -0
- package/src/org/plugin.ts +255 -0
- package/src/org/schema.ts +28 -0
- package/src/org/types.ts +57 -0
- package/src/org-team/index.ts +1 -0
- package/src/package-lifecycle/deprecated-imports.ts +179 -0
- package/src/package-lifecycle/eject-manifest.ts +345 -0
- package/src/package-lifecycle/index.ts +7 -0
- package/src/package-lifecycle/manifest.ts +120 -0
- package/src/package-lifecycle/migration-manifest.ts +159 -0
- package/src/package-lifecycle/migration-message.ts +6 -0
- package/src/package-lifecycle/tombstone.ts +58 -0
- package/src/package-lifecycle/upgrade-error.ts +37 -0
- package/src/private-blob/index.ts +18 -0
- package/src/private-blob/registry.ts +242 -0
- package/src/private-blob/types.ts +55 -0
- package/src/progress/actions.ts +179 -0
- package/src/progress/index.ts +16 -0
- package/src/progress/registry.ts +127 -0
- package/src/progress/routes.ts +89 -0
- package/src/progress/store.ts +353 -0
- package/src/progress/types.ts +59 -0
- package/src/provider-api/actions/custom-provider-registration.ts +197 -0
- package/src/provider-api/actions/delete-staged-dataset.ts +5 -0
- package/src/provider-api/actions/github-repo-files.ts +266 -0
- package/src/provider-api/actions/list-staged-datasets.ts +5 -0
- package/src/provider-api/actions/provider-api-audit.ts +88 -0
- package/src/provider-api/actions/provider-api.ts +460 -0
- package/src/provider-api/actions/query-staged-dataset.ts +5 -0
- package/src/provider-api/actions/staged-datasets.ts +359 -0
- package/src/provider-api/corpus-jobs-store.ts +522 -0
- package/src/provider-api/corpus-jobs.ts +1817 -0
- package/src/provider-api/custom-registry.ts +456 -0
- package/src/provider-api/github-repo.ts +675 -0
- package/src/provider-api/gong.ts +108 -0
- package/src/provider-api/index.ts +5444 -0
- package/src/provider-api/quota-governor.ts +562 -0
- package/src/provider-api/runtime.ts +1 -0
- package/src/provider-api/staged-datasets-aggregate.ts +304 -0
- package/src/provider-api/staged-datasets-store.ts +441 -0
- package/src/provider-api/staging.ts +483 -0
- package/src/resources/agents.ts +65 -0
- package/src/resources/emitter.ts +54 -0
- package/src/resources/handlers.ts +728 -0
- package/src/resources/index.ts +4 -0
- package/src/resources/metadata.ts +252 -0
- package/src/resources/script-helpers.ts +160 -0
- package/src/resources/store.ts +1618 -0
- package/src/review/actions/consume-review-feedback.ts +48 -0
- package/src/review/actions/create-review-comment.ts +108 -0
- package/src/review/actions/delete-review-comment.ts +67 -0
- package/src/review/actions/get-review-feedback.ts +49 -0
- package/src/review/actions/list-review-comments.ts +87 -0
- package/src/review/actions/reply-review-comment.ts +118 -0
- package/src/review/actions/resolve-review-thread.ts +94 -0
- package/src/review/actions/send-review-thread-to-agent.ts +62 -0
- package/src/review/actions/set-review-status.ts +58 -0
- package/src/review/identity.ts +101 -0
- package/src/review/index.ts +45 -0
- package/src/review/mentions.ts +44 -0
- package/src/review/registry.ts +111 -0
- package/src/review/store.ts +997 -0
- package/src/review/types.ts +101 -0
- package/src/router/index.ts +24 -0
- package/src/scripts/agent-engines/list-agent-engines.ts +130 -0
- package/src/scripts/agent-engines/manage-agent-engine.ts +197 -0
- package/src/scripts/agent-engines/set-agent-engine.ts +84 -0
- package/src/scripts/agent-engines/test-agent-engine.ts +174 -0
- package/src/scripts/call-agent.ts +792 -0
- package/src/scripts/chat/index.ts +8 -0
- package/src/scripts/chat/open-chat.ts +56 -0
- package/src/scripts/chat/search-chats.ts +121 -0
- package/src/scripts/core-scripts.ts +22 -0
- package/src/scripts/db/check-scoping.ts +212 -0
- package/src/scripts/db/exec.ts +791 -0
- package/src/scripts/db/index.ts +19 -0
- package/src/scripts/db/migrate-encrypt-credentials.ts +223 -0
- package/src/scripts/db/migrate-encrypt-oauth-tokens.ts +213 -0
- package/src/scripts/db/migrate-user-api-keys.ts +257 -0
- package/src/scripts/db/patch.ts +820 -0
- package/src/scripts/db/query.ts +299 -0
- package/src/scripts/db/reset-dev-owner.ts +285 -0
- package/src/scripts/db/safety.ts +286 -0
- package/src/scripts/db/schema.ts +364 -0
- package/src/scripts/db/scoping.ts +341 -0
- package/src/scripts/db/sqlite-client.ts +78 -0
- package/src/scripts/db/tool-mode.ts +23 -0
- package/src/scripts/db/tool-schemas.ts +31 -0
- package/src/scripts/db/wipe-leaked-builder-keys.ts +201 -0
- package/src/scripts/dev/index.ts +296 -0
- package/src/scripts/dev/list-files.ts +119 -0
- package/src/scripts/dev/read-file.ts +77 -0
- package/src/scripts/dev/search-files.ts +151 -0
- package/src/scripts/dev/shell.ts +111 -0
- package/src/scripts/dev/write-file.ts +56 -0
- package/src/scripts/dev-session.ts +96 -0
- package/src/scripts/docs/index.ts +8 -0
- package/src/scripts/docs/search.ts +274 -0
- package/src/scripts/docs/source-search.ts +363 -0
- package/src/scripts/index.ts +15 -0
- package/src/scripts/manage-agent-loop-settings.ts +84 -0
- package/src/scripts/parse-args.ts +46 -0
- package/src/scripts/resources/delete-memory.ts +67 -0
- package/src/scripts/resources/delete.ts +69 -0
- package/src/scripts/resources/effective.ts +71 -0
- package/src/scripts/resources/index.ts +18 -0
- package/src/scripts/resources/list.ts +103 -0
- package/src/scripts/resources/migrate-learnings.ts +40 -0
- package/src/scripts/resources/read.ts +107 -0
- package/src/scripts/resources/save-memory.ts +99 -0
- package/src/scripts/resources/write.ts +158 -0
- package/src/scripts/runner.ts +339 -0
- package/src/scripts/utils.ts +130 -0
- package/src/search/index.ts +413 -0
- package/src/search-utils/index.ts +112 -0
- package/src/secrets/crypto.ts +228 -0
- package/src/secrets/index.ts +65 -0
- package/src/secrets/onboarding.ts +101 -0
- package/src/secrets/register-framework-secrets.ts +228 -0
- package/src/secrets/register.ts +129 -0
- package/src/secrets/routes.ts +697 -0
- package/src/secrets/schema.ts +52 -0
- package/src/secrets/storage.ts +561 -0
- package/src/secrets/substitution.ts +305 -0
- package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +150 -0
- package/src/server/action-change.ts +66 -0
- package/src/server/action-discovery.ts +774 -0
- package/src/server/action-routes.ts +608 -0
- package/src/server/agent-access.ts +72 -0
- package/src/server/agent-chat/action-filters-a2a.ts +339 -0
- package/src/server/agent-chat/browser-team-tools.ts +510 -0
- package/src/server/agent-chat/context-tools.ts +599 -0
- package/src/server/agent-chat/framework-prompts.ts +467 -0
- package/src/server/agent-chat/lazy-fs.ts +11 -0
- package/src/server/agent-chat/mcp-glue.ts +91 -0
- package/src/server/agent-chat/plugin-options.ts +379 -0
- package/src/server/agent-chat/process-run-failure.ts +62 -0
- package/src/server/agent-chat/prompt-resources.ts +1004 -0
- package/src/server/agent-chat/recurring-jobs-runtime.ts +80 -0
- package/src/server/agent-chat/request-surface.ts +71 -0
- package/src/server/agent-chat/run-code-tools.ts +67 -0
- package/src/server/agent-chat/script-entries.ts +796 -0
- package/src/server/agent-chat/shared-thread.ts +301 -0
- package/src/server/agent-chat/skill-frontmatter.ts +41 -0
- package/src/server/agent-chat-plugin.ts +5930 -0
- package/src/server/agent-discovery.ts +706 -0
- package/src/server/agent-engine-api-key-route.ts +236 -0
- package/src/server/agent-run-context.ts +204 -0
- package/src/server/agent-teams-run-queue.ts +344 -0
- package/src/server/agent-teams.ts +2257 -0
- package/src/server/agents-bundle.ts +464 -0
- package/src/server/analytics.ts +105 -0
- package/src/server/app-base-path.ts +79 -0
- package/src/server/app-name.ts +53 -0
- package/src/server/app-url.ts +184 -0
- package/src/server/attachment-actions.ts +276 -0
- package/src/server/attribution.ts +214 -0
- package/src/server/auth-marketing.ts +260 -0
- package/src/server/auth-plugin.ts +27 -0
- package/src/server/auth.ts +3803 -0
- package/src/server/better-auth-instance.ts +1197 -0
- package/src/server/builder-browser.ts +1701 -0
- package/src/server/builder-design-systems.ts +668 -0
- package/src/server/builder-space.ts +176 -0
- package/src/server/captcha.ts +63 -0
- package/src/server/capture-error.ts +64 -0
- package/src/server/cli-capture.ts +141 -0
- package/src/server/collab-plugin.ts +391 -0
- package/src/server/complete-text.ts +231 -0
- package/src/server/cookie-namespace.ts +159 -0
- package/src/server/core-routes-plugin.ts +4122 -0
- package/src/server/cors-origins.ts +60 -0
- package/src/server/create-server.ts +268 -0
- package/src/server/credential-provider.ts +1202 -0
- package/src/server/csrf.ts +229 -0
- package/src/server/date-utils.ts +42 -0
- package/src/server/deep-link.ts +119 -0
- package/src/server/derived-secret.ts +32 -0
- package/src/server/design-token-utils.ts +1032 -0
- package/src/server/desktop-sso.ts +83 -0
- package/src/server/edge.ts +69 -0
- package/src/server/email-actions.ts +218 -0
- package/src/server/email-template.ts +192 -0
- package/src/server/email-templates.ts +148 -0
- package/src/server/email.ts +219 -0
- package/src/server/embed-route.ts +283 -0
- package/src/server/embed-session.ts +805 -0
- package/src/server/embedded.ts +252 -0
- package/src/server/entry-server.tsx +154 -0
- package/src/server/framework-request-handler.ts +848 -0
- package/src/server/fusion-app.ts +447 -0
- package/src/server/google-auth-mode.ts +34 -0
- package/src/server/google-auth-plugin.ts +496 -0
- package/src/server/google-oauth-credentials.ts +128 -0
- package/src/server/google-oauth.ts +972 -0
- package/src/server/google-realtime-session.ts +182 -0
- package/src/server/h3-helpers.ts +174 -0
- package/src/server/http-response-telemetry.ts +396 -0
- package/src/server/identity-sso-store.ts +304 -0
- package/src/server/identity-sso.ts +514 -0
- package/src/server/index.ts +593 -0
- package/src/server/missing-key.ts +36 -0
- package/src/server/oauth-helpers.ts +44 -0
- package/src/server/oauth-public-origin.ts +44 -0
- package/src/server/oauth-return-url.ts +120 -0
- package/src/server/og-fonts-data.ts +15 -0
- package/src/server/og-fonts.ts +75 -0
- package/src/server/onboarding-html.ts +4040 -0
- package/src/server/open-route.ts +311 -0
- package/src/server/org-admin.ts +28 -0
- package/src/server/poll-events.ts +88 -0
- package/src/server/poll.ts +1224 -0
- package/src/server/prompts/framework-core-compact.ts +107 -0
- package/src/server/prompts/framework-core.ts +143 -0
- package/src/server/prompts/index.ts +16 -0
- package/src/server/prompts/model-overlays.ts +54 -0
- package/src/server/prompts/shared-rules.ts +104 -0
- package/src/server/realtime-voice.ts +967 -0
- package/src/server/recap-image-route.ts +242 -0
- package/src/server/recap-image-store.ts +185 -0
- package/src/server/request-context.ts +416 -0
- package/src/server/request-origin.ts +67 -0
- package/src/server/resources-plugin.ts +119 -0
- package/src/server/schema-prompt.ts +429 -0
- package/src/server/scoped-key-storage.ts +223 -0
- package/src/server/security-headers.ts +170 -0
- package/src/server/self-dispatch.ts +224 -0
- package/src/server/sentry-config.ts +73 -0
- package/src/server/sentry-plugin.ts +138 -0
- package/src/server/sentry.ts +444 -0
- package/src/server/short-lived-token.ts +170 -0
- package/src/server/social-og-image.ts +454 -0
- package/src/server/sse.ts +102 -0
- package/src/server/ssr-handler.ts +466 -0
- package/src/server/transcribe-voice.ts +1076 -0
- package/src/server/voice-providers-status.ts +118 -0
- package/src/server/workspace-oauth.ts +31 -0
- package/src/server/workspace-provider-oauth.ts +970 -0
- package/src/session-replay-iframe-protocol.ts +58 -0
- package/src/settings/handlers.ts +44 -0
- package/src/settings/index.ts +34 -0
- package/src/settings/org-settings.ts +83 -0
- package/src/settings/script-helpers.ts +24 -0
- package/src/settings/store.ts +247 -0
- package/src/settings/user-settings.ts +47 -0
- package/src/setup-connections/index.ts +90 -0
- package/src/setup-connections/onboarding.ts +47 -0
- package/src/shared/agent-access.ts +112 -0
- package/src/shared/agent-chat.ts +124 -0
- package/src/shared/agent-env.ts +46 -0
- package/src/shared/agent-readable-resource.ts +111 -0
- package/src/shared/agent-sidebar-url.ts +39 -0
- package/src/shared/cache-control.ts +25 -0
- package/src/shared/cloudflare-globals.d.ts +34 -0
- package/src/shared/context-xray.ts +172 -0
- package/src/shared/embed-auth.ts +6 -0
- package/src/shared/index.ts +83 -0
- package/src/shared/llm-connection.ts +42 -0
- package/src/shared/markdown-block-split.ts +129 -0
- package/src/shared/mcp-connect-content.ts +130 -0
- package/src/shared/mcp-embed-headers.ts +175 -0
- package/src/shared/mcp-integration-config.ts +101 -0
- package/src/shared/merge-by-id.ts +14 -0
- package/src/shared/oauth-state.ts +39 -0
- package/src/shared/reasoning-effort.ts +228 -0
- package/src/shared/route-warmup-config.ts +128 -0
- package/src/shared/runtime.ts +31 -0
- package/src/shared/social-meta.ts +82 -0
- package/src/shared/streaming-text-smoothing.ts +184 -0
- package/src/shared/truncate.ts +13 -0
- package/src/shared/workspace-app-audience.ts +177 -0
- package/src/shared/workspace-app-id.ts +54 -0
- package/src/sharing/access.ts +585 -0
- package/src/sharing/actions/create-agent-resource-link.ts +91 -0
- package/src/sharing/actions/extension-change.ts +22 -0
- package/src/sharing/actions/list-resource-shares.ts +93 -0
- package/src/sharing/actions/set-resource-visibility.ts +91 -0
- package/src/sharing/actions/share-resource.ts +322 -0
- package/src/sharing/actions/unshare-resource.ts +72 -0
- package/src/sharing/index.ts +35 -0
- package/src/sharing/registry.ts +201 -0
- package/src/sharing/schema.ts +99 -0
- package/src/styles/agent-conversation.css +766 -0
- package/src/styles/agent-native.css +938 -0
- package/src/styles/blocks.css +1717 -0
- package/src/styles/chat-history-list.css +1 -0
- package/src/styles/rich-markdown-editor.css +1 -0
- package/src/tailwind.preset.ts +140 -0
- package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/src/templates/chat/AGENTS.md +3 -2
- package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/src/templates/default/AGENTS.md +6 -5
- package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/src/templates/headless/AGENTS.md +5 -4
- package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
- package/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
- package/src/templates/workspace-core/AGENTS.md +4 -4
- package/src/templates/workspace-root/AGENTS.md +4 -4
- package/src/terminal/cli-registry.ts +57 -0
- package/src/terminal/index.ts +22 -0
- package/src/terminal/pty-server.ts +389 -0
- package/src/terminal/terminal-plugin.ts +265 -0
- package/src/testing.ts +23 -0
- package/src/tracking/index.ts +10 -0
- package/src/tracking/providers.ts +422 -0
- package/src/tracking/registry.ts +102 -0
- package/src/tracking/route.ts +108 -0
- package/src/tracking/types.ts +16 -0
- package/src/transcription/builder-transcription.ts +118 -0
- package/src/triggers/actions/list-automations.ts +99 -0
- package/src/triggers/actions/manage-automation.ts +78 -0
- package/src/triggers/actions.ts +333 -0
- package/src/triggers/condition-evaluator.ts +163 -0
- package/src/triggers/dispatcher.ts +536 -0
- package/src/triggers/index.ts +13 -0
- package/src/triggers/routes.ts +322 -0
- package/src/triggers/types.ts +42 -0
- package/src/types/pglite.d.ts +26 -0
- package/src/usage/store.ts +698 -0
- package/src/vite/action-types-plugin.ts +481 -0
- package/src/vite/agent-web-plugin.ts +78 -0
- package/src/vite/agents-bundle-plugin.ts +185 -0
- package/src/vite/client.ts +3039 -0
- package/src/vite/index.ts +21 -0
- package/src/voice/index.ts +18 -0
- package/src/voice/voice-cleanup-prompt.ts +38 -0
- package/src/voice/voice-context.ts +217 -0
- package/src/voice/voice-replacements.ts +75 -0
- package/src/workspace-connections/credentials.ts +603 -0
- package/src/workspace-connections/index.ts +72 -0
- package/src/workspace-connections/lifecycle.ts +43 -0
- package/src/workspace-connections/store.ts +1943 -0
- package/src/workspace-files/index.ts +18 -0
- package/src/workspace-files/store.ts +339 -0
- package/src/workspace-files/tool.ts +266 -0
|
@@ -0,0 +1,1205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side hook for collaborative document editing via Yjs.
|
|
3
|
+
*
|
|
4
|
+
* Creates a STABLE Y.Doc per docId that never changes identity. This allows
|
|
5
|
+
* TipTap's Collaboration extension to bind once without editor recreation.
|
|
6
|
+
* Server state is applied to the existing doc when it arrives.
|
|
7
|
+
*
|
|
8
|
+
* Also manages Yjs Awareness for cursor positions and user presence,
|
|
9
|
+
* synced via polling to the server's awareness endpoint.
|
|
10
|
+
*
|
|
11
|
+
* Connection sharing: connections live in a module-level, ref-counted registry
|
|
12
|
+
* keyed by docId (mirroring the SyncTransport registry in use-db-sync.ts).
|
|
13
|
+
* Every `useCollaborativeDoc` mount for the same docId attaches to ONE shared
|
|
14
|
+
* connection — one Y.Doc, one Awareness, one state fetch, one poll loop, one
|
|
15
|
+
* awareness POST cycle — instead of each hook instance opening an independent
|
|
16
|
+
* connection and doubling all collab traffic (e.g. a presence bar and the
|
|
17
|
+
* editor mounting the hook for the same doc). The first subscriber starts the
|
|
18
|
+
* connection; the last one leaving tears it down after a short linger so
|
|
19
|
+
* StrictMode double-mounts and rapid unmount/remounts don't thrash the doc.
|
|
20
|
+
*
|
|
21
|
+
* Transport improvements (vs previous version):
|
|
22
|
+
* - Local update POSTs are debounced and coalesced with Y.mergeUpdates (~80ms)
|
|
23
|
+
* to avoid per-keystroke requests. The batch is flushed immediately on
|
|
24
|
+
* visibilitychange/pagehide and before each poll/awareness cycle.
|
|
25
|
+
* - GET state?stateVector= is NOT fetched on every poll cycle. It is fetched:
|
|
26
|
+
* (a) on (re)connect / initial load, (b) when a poll response indicates a
|
|
27
|
+
* gap (version jump > ring-buffer size), (c) after applying an update fails,
|
|
28
|
+
* and (d) as a low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL
|
|
29
|
+
* poll cycles (~15×).
|
|
30
|
+
* - Network errors use exponential backoff with jitter (cap ~15s), reset on
|
|
31
|
+
* success.
|
|
32
|
+
* - SSE fast-path: collab events are received push-style from
|
|
33
|
+
* /_agent-native/events (the framework SSE stream). While SSE is
|
|
34
|
+
* healthy the poll loop relaxes to a slow cadence (10–15s). If SSE is
|
|
35
|
+
* unavailable the 2s poll resumes automatically.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
dedupeCollabUsersByEmail,
|
|
40
|
+
type CollabUser,
|
|
41
|
+
} from "@agent-native/toolkit/collab-ui";
|
|
42
|
+
import { useEffect, useMemo, useState } from "react";
|
|
43
|
+
import { Awareness } from "y-protocols/awareness";
|
|
44
|
+
import * as Y from "yjs";
|
|
45
|
+
|
|
46
|
+
import { agentNativePath } from "../client/api-path.js";
|
|
47
|
+
import { subscribeSyncEvents, type SyncEvent } from "../client/use-db-sync.js";
|
|
48
|
+
export {
|
|
49
|
+
dedupeCollabUsersByEmail,
|
|
50
|
+
emailToColor,
|
|
51
|
+
emailToName,
|
|
52
|
+
isReconcileLeadClient,
|
|
53
|
+
type CollabUser,
|
|
54
|
+
} from "@agent-native/toolkit/collab-ui";
|
|
55
|
+
|
|
56
|
+
export interface UseCollaborativeDocOptions {
|
|
57
|
+
/** Document ID to collaborate on. Pass null to disable. */
|
|
58
|
+
docId: string | null;
|
|
59
|
+
/** Poll interval in ms when SSE is unavailable. Default: 2000 */
|
|
60
|
+
pollInterval?: number;
|
|
61
|
+
/** Poll interval in ms while SSE is healthy. Default: 12000 */
|
|
62
|
+
pollIntervalWithSse?: number;
|
|
63
|
+
/** Pause remote update/presence polling while the tab is hidden. Default: true */
|
|
64
|
+
pauseWhenHidden?: boolean;
|
|
65
|
+
/** Base URL for collab endpoints. Default: "/_agent-native/collab" */
|
|
66
|
+
baseUrl?: string;
|
|
67
|
+
/** Request source ID for jitter prevention (e.g., tab ID). */
|
|
68
|
+
requestSource?: string;
|
|
69
|
+
/** Current user info for cursor labels. */
|
|
70
|
+
user?: CollabUser;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface UseCollaborativeDocResult {
|
|
74
|
+
/** The Yjs document instance. Stable per docId — never changes identity. */
|
|
75
|
+
ydoc: Y.Doc | null;
|
|
76
|
+
/** Yjs Awareness instance for cursor/presence sync. */
|
|
77
|
+
awareness: Awareness | null;
|
|
78
|
+
/** Whether the initial state is still loading from the server. */
|
|
79
|
+
isLoading: boolean;
|
|
80
|
+
/** Whether the doc is synced with the server. */
|
|
81
|
+
isSynced: boolean;
|
|
82
|
+
/** Active users on this document (from awareness). */
|
|
83
|
+
activeUsers: CollabUser[];
|
|
84
|
+
/** True briefly when the AI agent makes an edit (for presence indicator). */
|
|
85
|
+
agentActive: boolean;
|
|
86
|
+
/** True when the AI agent has an active awareness entry (durable presence). */
|
|
87
|
+
agentPresent: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isDocumentHidden(): boolean {
|
|
91
|
+
return (
|
|
92
|
+
typeof document !== "undefined" && document.visibilityState === "hidden"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Content equality for deduped active-user lists. `dedupeCollabUsersByEmail`
|
|
98
|
+
* always allocates a fresh array (and fresh per-user objects), so callers
|
|
99
|
+
* that only want to know "did the actual user set change" need this instead
|
|
100
|
+
* of an identity check. Order-sensitive: the dedupe helper iterates awareness
|
|
101
|
+
* states in a stable Map insertion order, so a reordering here does reflect
|
|
102
|
+
* a real change (a client joined/left and re-joined).
|
|
103
|
+
*/
|
|
104
|
+
function collabUsersEqual(a: CollabUser[], b: CollabUser[]): boolean {
|
|
105
|
+
if (a === b) return true;
|
|
106
|
+
if (a.length !== b.length) return false;
|
|
107
|
+
for (let i = 0; i < a.length; i++) {
|
|
108
|
+
const left = a[i]!;
|
|
109
|
+
const right = b[i]!;
|
|
110
|
+
if (
|
|
111
|
+
left.email !== right.email ||
|
|
112
|
+
left.name !== right.name ||
|
|
113
|
+
left.color !== right.color
|
|
114
|
+
) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface RemoteAwarenessSnapshot {
|
|
122
|
+
clientId: number;
|
|
123
|
+
state: unknown;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function reconcileRemoteAwarenessStates(
|
|
127
|
+
states: Map<number, unknown>,
|
|
128
|
+
localClientId: number,
|
|
129
|
+
remoteStates: RemoteAwarenessSnapshot[],
|
|
130
|
+
): { added: number[]; updated: number[]; removed: number[] } {
|
|
131
|
+
const incoming = new Set<number>();
|
|
132
|
+
const added: number[] = [];
|
|
133
|
+
const updated: number[] = [];
|
|
134
|
+
const removed: number[] = [];
|
|
135
|
+
|
|
136
|
+
for (const remote of remoteStates) {
|
|
137
|
+
if (
|
|
138
|
+
!Number.isFinite(remote.clientId) ||
|
|
139
|
+
remote.clientId === localClientId
|
|
140
|
+
) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
incoming.add(remote.clientId);
|
|
144
|
+
const hadState = states.has(remote.clientId);
|
|
145
|
+
states.set(remote.clientId, remote.state);
|
|
146
|
+
(hadState ? updated : added).push(remote.clientId);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (const clientId of Array.from(states.keys())) {
|
|
150
|
+
if (clientId === localClientId) continue;
|
|
151
|
+
if (incoming.has(clientId)) continue;
|
|
152
|
+
states.delete(clientId);
|
|
153
|
+
removed.push(clientId);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { added, updated, removed };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Base64 helpers
|
|
160
|
+
function uint8ArrayToBase64(arr: Uint8Array): string {
|
|
161
|
+
let binary = "";
|
|
162
|
+
for (let i = 0; i < arr.length; i++) {
|
|
163
|
+
binary += String.fromCharCode(arr[i]);
|
|
164
|
+
}
|
|
165
|
+
return btoa(binary);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function base64ToUint8Array(b64: string): Uint8Array {
|
|
169
|
+
const binary = atob(b64);
|
|
170
|
+
const arr = new Uint8Array(binary.length);
|
|
171
|
+
for (let i = 0; i < binary.length; i++) {
|
|
172
|
+
arr[i] = binary.charCodeAt(i);
|
|
173
|
+
}
|
|
174
|
+
return arr;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Debounce delay for coalescing local Yjs update POSTs (ms). */
|
|
178
|
+
const UPDATE_DEBOUNCE_MS = 80;
|
|
179
|
+
|
|
180
|
+
/** Fetch state-vector every N poll cycles as a low-frequency safety net. */
|
|
181
|
+
const STATE_VECTOR_FETCH_INTERVAL = 15;
|
|
182
|
+
|
|
183
|
+
/** Poll ring-buffer size on the server (MAX_BUFFER in poll.ts). */
|
|
184
|
+
const POLL_RING_BUFFER_SIZE = 200;
|
|
185
|
+
|
|
186
|
+
/** Exponential backoff: base delay (ms), multiplier, cap (ms). */
|
|
187
|
+
const BACKOFF_BASE_MS = 500;
|
|
188
|
+
const BACKOFF_MAX_MS = 15_000;
|
|
189
|
+
|
|
190
|
+
function calcBackoff(consecutiveErrors: number): number {
|
|
191
|
+
const exp = Math.min(consecutiveErrors, 10);
|
|
192
|
+
const delay = BACKOFF_BASE_MS * Math.pow(2, exp);
|
|
193
|
+
// Add jitter: ±25%
|
|
194
|
+
const jitter = delay * 0.25 * (Math.random() * 2 - 1);
|
|
195
|
+
return Math.min(delay + jitter, BACKOFF_MAX_MS);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
// Fast awareness helper — throttled per (docId, ydocId) pair so multiple
|
|
200
|
+
// setLocalStateField calls within a 150ms window are coalesced into one POST.
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
|
|
203
|
+
const _awarenessThrottleTimers = new Map<
|
|
204
|
+
string,
|
|
205
|
+
ReturnType<typeof setTimeout>
|
|
206
|
+
>();
|
|
207
|
+
|
|
208
|
+
function scheduleAwarenessPush(
|
|
209
|
+
baseUrl: string,
|
|
210
|
+
docId: string,
|
|
211
|
+
clientId: number,
|
|
212
|
+
getState: () => Record<string, unknown> | null,
|
|
213
|
+
): void {
|
|
214
|
+
if (typeof window === "undefined") return;
|
|
215
|
+
const key = `${docId}::${clientId}`;
|
|
216
|
+
if (_awarenessThrottleTimers.has(key)) return; // already scheduled
|
|
217
|
+
|
|
218
|
+
const timer = setTimeout(() => {
|
|
219
|
+
_awarenessThrottleTimers.delete(key);
|
|
220
|
+
const state = getState();
|
|
221
|
+
fetch(`${baseUrl}/${docId}/awareness`, {
|
|
222
|
+
method: "POST",
|
|
223
|
+
headers: { "Content-Type": "application/json" },
|
|
224
|
+
body: JSON.stringify({
|
|
225
|
+
clientId,
|
|
226
|
+
state: state ? JSON.stringify(state) : null,
|
|
227
|
+
}),
|
|
228
|
+
}).catch(() => {}); // best-effort; poll cycle is the baseline fallback
|
|
229
|
+
}, 150);
|
|
230
|
+
|
|
231
|
+
_awarenessThrottleTimers.set(key, timer);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Shared per-docId collab connection
|
|
236
|
+
//
|
|
237
|
+
// One CollabDocConnection per (baseUrl, docId) pair is held in a module-level
|
|
238
|
+
// registry (the same pattern as SyncTransport in use-db-sync.ts). Every
|
|
239
|
+
// `useCollaborativeDoc` mount for a docId subscribes to the shared connection,
|
|
240
|
+
// so a tab runs exactly ONE state fetch, ONE poll fallback loop, and ONE
|
|
241
|
+
// awareness POST cycle per document no matter how many components mount the
|
|
242
|
+
// hook (e.g. a presence bar + the editor for the same doc).
|
|
243
|
+
//
|
|
244
|
+
// Lifecycle: the connection is created on first render that needs it (the
|
|
245
|
+
// Y.Doc must exist during render so TipTap can bind on mount), starts its
|
|
246
|
+
// network activity when the first subscriber attaches, and is disposed a short
|
|
247
|
+
// linger after the last subscriber detaches. The linger keeps StrictMode's
|
|
248
|
+
// mount→unmount→mount and rapid route remounts from destroying and refetching
|
|
249
|
+
// the doc, and doubles as the cleanup path for connections created by a render
|
|
250
|
+
// that React later discarded (no subscriber ever attaches).
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Shared reactive state each subscriber mirrors into its own React state.
|
|
255
|
+
* Replaced immutably on every change so hooks can bail out on identity.
|
|
256
|
+
*/
|
|
257
|
+
interface CollabDocSnapshot {
|
|
258
|
+
isLoading: boolean;
|
|
259
|
+
isSynced: boolean;
|
|
260
|
+
activeUsers: CollabUser[];
|
|
261
|
+
agentActive: boolean;
|
|
262
|
+
agentPresent: boolean;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
interface CollabDocSubscription {
|
|
266
|
+
/** Requested poll interval; the connection uses the MIN across subscribers. */
|
|
267
|
+
pollInterval: number;
|
|
268
|
+
/** Requested relaxed interval while SSE is healthy (MIN across subscribers). */
|
|
269
|
+
pollIntervalWithSse: number;
|
|
270
|
+
/**
|
|
271
|
+
* Whether this subscriber wants polling paused while the tab is hidden.
|
|
272
|
+
* The connection pauses only when ALL subscribers request it.
|
|
273
|
+
*/
|
|
274
|
+
pauseWhenHidden: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Echo-suppression tag. The connection adopts the first defined value and
|
|
277
|
+
* uses it for BOTH tagging outgoing updates and filtering incoming echoes,
|
|
278
|
+
* so suppression stays self-consistent even when subscribers pass different
|
|
279
|
+
* per-tab IDs (all values identify the same tab).
|
|
280
|
+
*/
|
|
281
|
+
requestSource?: string;
|
|
282
|
+
onSnapshot: (snapshot: CollabDocSnapshot) => void;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const EMPTY_SNAPSHOT: CollabDocSnapshot = Object.freeze({
|
|
286
|
+
isLoading: false,
|
|
287
|
+
isSynced: false,
|
|
288
|
+
activeUsers: [],
|
|
289
|
+
agentActive: false,
|
|
290
|
+
agentPresent: false,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* How long a connection with zero subscribers lingers before disposal.
|
|
295
|
+
* Long enough to absorb StrictMode double-mounts and route-level remounts
|
|
296
|
+
* (which would otherwise destroy the Y.Doc, refetch server state, and lose
|
|
297
|
+
* echo-suppression context), short enough that navigating away stops the
|
|
298
|
+
* doc's traffic promptly.
|
|
299
|
+
*/
|
|
300
|
+
const DISPOSE_LINGER_MS = 1000;
|
|
301
|
+
|
|
302
|
+
class CollabDocConnection {
|
|
303
|
+
readonly ydoc: Y.Doc;
|
|
304
|
+
readonly awareness: Awareness;
|
|
305
|
+
/** Immutable snapshot of the shared reactive state (replaced on change). */
|
|
306
|
+
snapshot: CollabDocSnapshot;
|
|
307
|
+
disposed = false;
|
|
308
|
+
|
|
309
|
+
private subscribers = new Map<symbol, CollabDocSubscription>();
|
|
310
|
+
private disposeTimer: ReturnType<typeof setTimeout> | null = null;
|
|
311
|
+
private started = false;
|
|
312
|
+
private docMissing = false;
|
|
313
|
+
private requestSource: string | undefined;
|
|
314
|
+
private lastSetUser: CollabUser | null = null;
|
|
315
|
+
|
|
316
|
+
// Local-update batching (debounced + coalesced with Y.mergeUpdates).
|
|
317
|
+
private pendingUpdates: Uint8Array[] = [];
|
|
318
|
+
private flushTimer: ReturnType<typeof setTimeout> | null = null;
|
|
319
|
+
private updateHandlerAttached = false;
|
|
320
|
+
|
|
321
|
+
// Poll loop + SSE fast path.
|
|
322
|
+
private syncActive = false;
|
|
323
|
+
private pollTimer: ReturnType<typeof setTimeout> | null = null;
|
|
324
|
+
private consecutiveErrors = 0;
|
|
325
|
+
private pollCycleCount = 0;
|
|
326
|
+
private pollVersion = 0;
|
|
327
|
+
private lastPolledVersion = 0;
|
|
328
|
+
private sseActive = false;
|
|
329
|
+
private sseSubscribedWithPause: boolean | null = null;
|
|
330
|
+
private unsubscribeCollabEvents: (() => void) | null = null;
|
|
331
|
+
private unsubscribeAwarenessEvents: (() => void) | null = null;
|
|
332
|
+
private agentTimer: ReturnType<typeof setTimeout> | null = null;
|
|
333
|
+
|
|
334
|
+
constructor(
|
|
335
|
+
readonly docId: string,
|
|
336
|
+
private readonly baseUrl: string,
|
|
337
|
+
/**
|
|
338
|
+
* Detached connections are created for SSR renders only: a per-hook
|
|
339
|
+
* Y.Doc/Awareness with no registry entry and no network activity
|
|
340
|
+
* (matching the previous per-hook behavior on the server). They are
|
|
341
|
+
* never started and are reclaimed by GC with the render.
|
|
342
|
+
*/
|
|
343
|
+
readonly detached = false,
|
|
344
|
+
) {
|
|
345
|
+
this.ydoc = new Y.Doc();
|
|
346
|
+
this.awareness = new Awareness(this.ydoc);
|
|
347
|
+
this.snapshot = {
|
|
348
|
+
isLoading: true,
|
|
349
|
+
isSynced: false,
|
|
350
|
+
activeUsers: [],
|
|
351
|
+
agentActive: false,
|
|
352
|
+
agentPresent: false,
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Track active users / agent presence from awareness changes, and drive
|
|
356
|
+
// the fast (throttled) awareness push once a local user is published.
|
|
357
|
+
this.awareness.on("change", this.handleAwarenessChange);
|
|
358
|
+
|
|
359
|
+
// Orphan guard: the connection is created during render (the Y.Doc must
|
|
360
|
+
// exist before mount), so a discarded render can create one that never
|
|
361
|
+
// gets a subscriber. The linger timer disposes it; the first `add()`
|
|
362
|
+
// cancels the timer.
|
|
363
|
+
if (!detached) this.scheduleDispose();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private get registryKey(): string {
|
|
367
|
+
return collabRegistryKey(this.docId, this.baseUrl);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// -------------------------------------------------------------------------
|
|
371
|
+
// Subscriber management (ref-counting)
|
|
372
|
+
// -------------------------------------------------------------------------
|
|
373
|
+
|
|
374
|
+
add(id: symbol, sub: CollabDocSubscription): void {
|
|
375
|
+
this.subscribers.set(id, sub);
|
|
376
|
+
if (this.disposeTimer) {
|
|
377
|
+
clearTimeout(this.disposeTimer);
|
|
378
|
+
this.disposeTimer = null;
|
|
379
|
+
}
|
|
380
|
+
// Adopt the first defined echo-suppression tag for the connection's
|
|
381
|
+
// lifetime (see CollabDocSubscription.requestSource).
|
|
382
|
+
if (!this.requestSource && sub.requestSource) {
|
|
383
|
+
this.requestSource = sub.requestSource;
|
|
384
|
+
}
|
|
385
|
+
if (!this.started) {
|
|
386
|
+
this.started = true;
|
|
387
|
+
this.start();
|
|
388
|
+
} else {
|
|
389
|
+
// A joining subscriber can change the effective poll cadence or the
|
|
390
|
+
// pause-when-hidden aggregate; pick both up without waiting a cycle.
|
|
391
|
+
this.resubscribeCollabEventsIfPauseChanged();
|
|
392
|
+
this.reschedulePoll();
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
remove(id: symbol): void {
|
|
397
|
+
this.subscribers.delete(id);
|
|
398
|
+
if (this.subscribers.size === 0) {
|
|
399
|
+
this.scheduleDispose();
|
|
400
|
+
} else {
|
|
401
|
+
this.resubscribeCollabEventsIfPauseChanged();
|
|
402
|
+
this.reschedulePoll();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
private scheduleDispose(): void {
|
|
407
|
+
if (this.disposeTimer) clearTimeout(this.disposeTimer);
|
|
408
|
+
this.disposeTimer = setTimeout(() => {
|
|
409
|
+
this.disposeTimer = null;
|
|
410
|
+
this.dispose();
|
|
411
|
+
}, DISPOSE_LINGER_MS);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Tear the connection down: stop all loops and listeners, flush any pending
|
|
416
|
+
* local updates, clear awareness local state (via destroy), and destroy the
|
|
417
|
+
* Y.Doc. Also used by the test-only registry reset. @internal
|
|
418
|
+
*/
|
|
419
|
+
dispose(): void {
|
|
420
|
+
if (this.disposed) return;
|
|
421
|
+
this.disposed = true;
|
|
422
|
+
if (this.disposeTimer) {
|
|
423
|
+
clearTimeout(this.disposeTimer);
|
|
424
|
+
this.disposeTimer = null;
|
|
425
|
+
}
|
|
426
|
+
this.stopSync();
|
|
427
|
+
this.unsubscribeAwarenessEvents?.();
|
|
428
|
+
this.unsubscribeAwarenessEvents = null;
|
|
429
|
+
this.flushPendingUpdates(true);
|
|
430
|
+
this.detachUpdateHandler();
|
|
431
|
+
if (this.agentTimer) {
|
|
432
|
+
clearTimeout(this.agentTimer);
|
|
433
|
+
this.agentTimer = null;
|
|
434
|
+
}
|
|
435
|
+
// Detach our change listener BEFORE destroy so the destroy-time
|
|
436
|
+
// `setLocalState(null)` does not schedule a push (matches the previous
|
|
437
|
+
// per-hook effect cleanup ordering).
|
|
438
|
+
this.awareness.off("change", this.handleAwarenessChange);
|
|
439
|
+
this.awareness.destroy();
|
|
440
|
+
this.ydoc.destroy();
|
|
441
|
+
if (collabConnectionRegistry.get(this.registryKey) === this) {
|
|
442
|
+
collabConnectionRegistry.delete(this.registryKey);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// -------------------------------------------------------------------------
|
|
447
|
+
// Derived settings (aggregate over active subscribers)
|
|
448
|
+
// -------------------------------------------------------------------------
|
|
449
|
+
|
|
450
|
+
private get effectivePollInterval(): number {
|
|
451
|
+
let min = Infinity;
|
|
452
|
+
for (const sub of this.subscribers.values()) {
|
|
453
|
+
if (sub.pollInterval < min) min = sub.pollInterval;
|
|
454
|
+
}
|
|
455
|
+
return isFinite(min) ? min : 2000;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
private get effectivePollIntervalWithSse(): number {
|
|
459
|
+
let min = Infinity;
|
|
460
|
+
for (const sub of this.subscribers.values()) {
|
|
461
|
+
if (sub.pollIntervalWithSse < min) min = sub.pollIntervalWithSse;
|
|
462
|
+
}
|
|
463
|
+
return isFinite(min) ? min : 12_000;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
private get effectivePauseWhenHidden(): boolean {
|
|
467
|
+
// Pause only if every subscriber has opted in.
|
|
468
|
+
for (const sub of this.subscribers.values()) {
|
|
469
|
+
if (!sub.pauseWhenHidden) return false;
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// -------------------------------------------------------------------------
|
|
475
|
+
// Shared state fan-out
|
|
476
|
+
// -------------------------------------------------------------------------
|
|
477
|
+
|
|
478
|
+
private setSnapshot(patch: Partial<CollabDocSnapshot>): void {
|
|
479
|
+
this.snapshot = { ...this.snapshot, ...patch };
|
|
480
|
+
for (const sub of this.subscribers.values()) {
|
|
481
|
+
sub.onSnapshot(this.snapshot);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
private markAgentActive(): void {
|
|
486
|
+
this.setSnapshot({ agentActive: true });
|
|
487
|
+
if (this.agentTimer) clearTimeout(this.agentTimer);
|
|
488
|
+
this.agentTimer = setTimeout(() => {
|
|
489
|
+
this.agentTimer = null;
|
|
490
|
+
this.setSnapshot({ agentActive: false });
|
|
491
|
+
}, 3000);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// -------------------------------------------------------------------------
|
|
495
|
+
// Awareness: local identity, active-user tracking, fast push
|
|
496
|
+
// -------------------------------------------------------------------------
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Publish the local user identity (cursor label) and current visibility.
|
|
500
|
+
* Set once per tab — repeated calls with the same identity are no-ops so
|
|
501
|
+
* multiple subscribers for the same user don't re-emit awareness updates.
|
|
502
|
+
*/
|
|
503
|
+
setUser(user: CollabUser): void {
|
|
504
|
+
if (this.disposed) return;
|
|
505
|
+
const prev = this.lastSetUser;
|
|
506
|
+
if (
|
|
507
|
+
prev &&
|
|
508
|
+
prev.name === user.name &&
|
|
509
|
+
prev.email === user.email &&
|
|
510
|
+
prev.color === user.color
|
|
511
|
+
) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
this.lastSetUser = {
|
|
515
|
+
name: user.name,
|
|
516
|
+
email: user.email,
|
|
517
|
+
color: user.color,
|
|
518
|
+
};
|
|
519
|
+
this.awareness.setLocalStateField("user", {
|
|
520
|
+
name: user.name,
|
|
521
|
+
email: user.email,
|
|
522
|
+
color: user.color,
|
|
523
|
+
});
|
|
524
|
+
// Also publish this tab's visibility so peers can elect a VISIBLE client
|
|
525
|
+
// to apply external snapshots (see isReconcileLeadClient) — a backgrounded
|
|
526
|
+
// tab pauses its poll and must not hold that role.
|
|
527
|
+
this.awareness.setLocalStateField("visible", !isDocumentHidden());
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
private handleAwarenessChange = (
|
|
531
|
+
_changes?: { added: number[]; updated: number[]; removed: number[] },
|
|
532
|
+
origin?: unknown,
|
|
533
|
+
): void => {
|
|
534
|
+
const users: CollabUser[] = [];
|
|
535
|
+
let hasAgent = false;
|
|
536
|
+
this.awareness.getStates().forEach((state, clientId) => {
|
|
537
|
+
if (clientId === this.ydoc.clientID) return; // Skip self
|
|
538
|
+
if (state.user) {
|
|
539
|
+
users.push(state.user as CollabUser);
|
|
540
|
+
if ((state.user as CollabUser).email === "agent@system") {
|
|
541
|
+
hasAgent = true;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
const nextActiveUsers = dedupeCollabUsersByEmail(users);
|
|
546
|
+
// Awareness "change" fires for every remote broadcast — including cursor
|
|
547
|
+
// jiggles, re-published-but-unchanged heartbeat state, and edits to
|
|
548
|
+
// presence fields (recentEdits, selection) that don't affect who's
|
|
549
|
+
// active. dedupeCollabUsersByEmail always returns a fresh array, so
|
|
550
|
+
// without this comparison every one of those events would hand
|
|
551
|
+
// `activeUsers` a new identity and force every consumer (e.g. a
|
|
552
|
+
// full-page editor keying a useMemo/effect off it) to re-render even
|
|
553
|
+
// though the actual user list is unchanged. Reuse the previous
|
|
554
|
+
// reference when the deduped content is the same, matching the
|
|
555
|
+
// stable-ref discipline `usePresence`'s shallowEqualOthers already
|
|
556
|
+
// applies to `others`.
|
|
557
|
+
const activeUsers = collabUsersEqual(
|
|
558
|
+
this.snapshot.activeUsers,
|
|
559
|
+
nextActiveUsers,
|
|
560
|
+
)
|
|
561
|
+
? this.snapshot.activeUsers
|
|
562
|
+
: nextActiveUsers;
|
|
563
|
+
if (
|
|
564
|
+
activeUsers !== this.snapshot.activeUsers ||
|
|
565
|
+
hasAgent !== this.snapshot.agentPresent
|
|
566
|
+
) {
|
|
567
|
+
this.setSnapshot({ activeUsers, agentPresent: hasAgent });
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Fast awareness push: whenever OUR OWN awareness state changes (e.g.
|
|
571
|
+
// cursor moves, setPresence() calls), schedule a throttled POST so peers
|
|
572
|
+
// receive updates at ~150ms instead of waiting for the next poll cycle.
|
|
573
|
+
// Gated on origin === "local": this listener also fires for remote
|
|
574
|
+
// awareness changes (poll/SSE call `awareness.emit("change", [changes,
|
|
575
|
+
// "remote"])` after reconciling incoming states — see
|
|
576
|
+
// applyAwarenessEvent/poll above). Without the origin check, every
|
|
577
|
+
// peer's cursor move would also re-trigger THIS client to re-broadcast
|
|
578
|
+
// its own unchanged state, turning one person moving their mouse into
|
|
579
|
+
// O(n) redundant POSTs from every other connected client (an awareness
|
|
580
|
+
// storm that gets worse as more people join the doc). Only active once a
|
|
581
|
+
// local user identity has been published (matches the previous per-hook
|
|
582
|
+
// gating on `user`). The poll cycle remains the authoritative baseline.
|
|
583
|
+
if (this.lastSetUser && origin === "local" && !this.disposed) {
|
|
584
|
+
scheduleAwarenessPush(
|
|
585
|
+
this.baseUrl,
|
|
586
|
+
this.docId,
|
|
587
|
+
this.ydoc.clientID,
|
|
588
|
+
() => this.awareness.getLocalState() as Record<string, unknown> | null,
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
// -------------------------------------------------------------------------
|
|
594
|
+
// Startup: initial state fetch, update handler, sync loops
|
|
595
|
+
// -------------------------------------------------------------------------
|
|
596
|
+
|
|
597
|
+
private start(): void {
|
|
598
|
+
this.attachUpdateHandler();
|
|
599
|
+
this.fetchInitialState();
|
|
600
|
+
this.startSync();
|
|
601
|
+
|
|
602
|
+
// SSE fast-path for awareness: listen on the SHARED framework transport
|
|
603
|
+
// and apply awareness-change events immediately so peers receive cursor
|
|
604
|
+
// moves push-style without waiting for the next poll cycle. Kept alive
|
|
605
|
+
// even when the doc is missing (matches the previous per-hook behavior).
|
|
606
|
+
this.unsubscribeAwarenessEvents = subscribeSyncEvents({
|
|
607
|
+
onEvents: (events) => {
|
|
608
|
+
if (this.disposed) return;
|
|
609
|
+
for (const data of events) this.applyAwarenessEvent(data);
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
private fetchInitialState(): void {
|
|
615
|
+
fetch(`${this.baseUrl}/${this.docId}/state`)
|
|
616
|
+
.then(async (res) => {
|
|
617
|
+
if (this.disposed) return;
|
|
618
|
+
if (res.status === 404 || res.status === 403) {
|
|
619
|
+
this.markDocMissing();
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
const data = (await res.json().catch(() => null)) as {
|
|
623
|
+
state?: string;
|
|
624
|
+
} | null;
|
|
625
|
+
if (this.disposed) return;
|
|
626
|
+
if (data?.state) {
|
|
627
|
+
const binary = base64ToUint8Array(data.state);
|
|
628
|
+
if (binary.length > 4) {
|
|
629
|
+
Y.applyUpdate(this.ydoc, binary, "remote");
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
this.setSnapshot({ isLoading: false, isSynced: true });
|
|
633
|
+
})
|
|
634
|
+
.catch(() => {
|
|
635
|
+
if (this.disposed) return;
|
|
636
|
+
this.setSnapshot({ isLoading: false, isSynced: true });
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* The initial state fetch returned 404/403 — the doc doesn't exist or isn't
|
|
642
|
+
* accessible. Stop doc-update traffic (poll loop, update POSTs, collab SSE
|
|
643
|
+
* handling) so we don't spam the console with errors against it. The
|
|
644
|
+
* awareness SSE subscription stays (matches previous behavior).
|
|
645
|
+
*/
|
|
646
|
+
private markDocMissing(): void {
|
|
647
|
+
this.docMissing = true;
|
|
648
|
+
this.flushPendingUpdates(true);
|
|
649
|
+
this.detachUpdateHandler();
|
|
650
|
+
this.stopSync();
|
|
651
|
+
this.setSnapshot({ isLoading: false, isSynced: true });
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// -------------------------------------------------------------------------
|
|
655
|
+
// Local update batching
|
|
656
|
+
// -------------------------------------------------------------------------
|
|
657
|
+
|
|
658
|
+
private handleDocUpdate = (update: Uint8Array, origin: unknown): void => {
|
|
659
|
+
if (origin === "remote") return;
|
|
660
|
+
this.pendingUpdates.push(update);
|
|
661
|
+
if (this.flushTimer) clearTimeout(this.flushTimer);
|
|
662
|
+
this.flushTimer = setTimeout(
|
|
663
|
+
() => this.flushPendingUpdates(),
|
|
664
|
+
UPDATE_DEBOUNCE_MS,
|
|
665
|
+
);
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
private handlePageHide = (): void => {
|
|
669
|
+
this.flushPendingUpdates(true /* keepalive */);
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
private attachUpdateHandler(): void {
|
|
673
|
+
if (this.updateHandlerAttached || this.docMissing) return;
|
|
674
|
+
this.updateHandlerAttached = true;
|
|
675
|
+
this.ydoc.on("update", this.handleDocUpdate);
|
|
676
|
+
if (typeof window !== "undefined") {
|
|
677
|
+
window.addEventListener("pagehide", this.handlePageHide);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
private detachUpdateHandler(): void {
|
|
682
|
+
if (!this.updateHandlerAttached) return;
|
|
683
|
+
this.updateHandlerAttached = false;
|
|
684
|
+
this.ydoc.off("update", this.handleDocUpdate);
|
|
685
|
+
if (typeof window !== "undefined") {
|
|
686
|
+
window.removeEventListener("pagehide", this.handlePageHide);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
private flushPendingUpdates(keepalive = false): void {
|
|
691
|
+
if (this.flushTimer) {
|
|
692
|
+
clearTimeout(this.flushTimer);
|
|
693
|
+
this.flushTimer = null;
|
|
694
|
+
}
|
|
695
|
+
if (this.pendingUpdates.length === 0) return;
|
|
696
|
+
const toSend = this.pendingUpdates;
|
|
697
|
+
this.pendingUpdates = [];
|
|
698
|
+
|
|
699
|
+
const merged = toSend.length === 1 ? toSend[0] : Y.mergeUpdates(toSend);
|
|
700
|
+
fetch(`${this.baseUrl}/${this.docId}/update`, {
|
|
701
|
+
method: "POST",
|
|
702
|
+
headers: { "Content-Type": "application/json" },
|
|
703
|
+
body: JSON.stringify({
|
|
704
|
+
update: uint8ArrayToBase64(merged),
|
|
705
|
+
requestSource: this.requestSource,
|
|
706
|
+
}),
|
|
707
|
+
...(keepalive ? { keepalive: true } : {}),
|
|
708
|
+
}).catch(() => {});
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// -------------------------------------------------------------------------
|
|
712
|
+
// Remote sync: SSE fast path + poll fallback loop
|
|
713
|
+
// -------------------------------------------------------------------------
|
|
714
|
+
|
|
715
|
+
private startSync(): void {
|
|
716
|
+
if (this.syncActive || this.docMissing || this.disposed) return;
|
|
717
|
+
this.syncActive = true;
|
|
718
|
+
|
|
719
|
+
this.subscribeCollabEvents();
|
|
720
|
+
|
|
721
|
+
if (!this.effectivePauseWhenHidden || !isDocumentHidden()) {
|
|
722
|
+
void this.poll();
|
|
723
|
+
}
|
|
724
|
+
window.addEventListener("focus", this.handleFocus);
|
|
725
|
+
document.addEventListener("visibilitychange", this.handleVisibilityChange);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
private stopSync(): void {
|
|
729
|
+
if (!this.syncActive) return;
|
|
730
|
+
this.syncActive = false;
|
|
731
|
+
if (this.pollTimer) {
|
|
732
|
+
clearTimeout(this.pollTimer);
|
|
733
|
+
this.pollTimer = null;
|
|
734
|
+
}
|
|
735
|
+
this.unsubscribeCollabEvents?.();
|
|
736
|
+
this.unsubscribeCollabEvents = null;
|
|
737
|
+
this.sseSubscribedWithPause = null;
|
|
738
|
+
window.removeEventListener("focus", this.handleFocus);
|
|
739
|
+
document.removeEventListener(
|
|
740
|
+
"visibilitychange",
|
|
741
|
+
this.handleVisibilityChange,
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* SSE fast-path: subscribe to the SHARED framework transport for
|
|
747
|
+
* /_agent-native/events instead of opening a dedicated EventSource per
|
|
748
|
+
* collab doc. A tab holds exactly one SSE connection regardless of how many
|
|
749
|
+
* docs are mounted. Collab update events arrive push-style; we apply them
|
|
750
|
+
* immediately, avoiding ~2s polling latency for peer edits.
|
|
751
|
+
*
|
|
752
|
+
* NOTE: SSE events are subject to the same server-side access scoping as
|
|
753
|
+
* polling — the server only pushes events that canSeeChangeForUser allows.
|
|
754
|
+
*/
|
|
755
|
+
private subscribeCollabEvents(): void {
|
|
756
|
+
const pauseWhenHidden = this.effectivePauseWhenHidden;
|
|
757
|
+
this.sseSubscribedWithPause = pauseWhenHidden;
|
|
758
|
+
this.unsubscribeCollabEvents = subscribeSyncEvents({
|
|
759
|
+
onEvents: (events) => {
|
|
760
|
+
if (this.disposed || !this.syncActive) return;
|
|
761
|
+
for (const change of events) this.handleSharedEvent(change);
|
|
762
|
+
},
|
|
763
|
+
onSseStateChange: (connected) => {
|
|
764
|
+
this.sseActive = connected;
|
|
765
|
+
if (connected) this.consecutiveErrors = 0;
|
|
766
|
+
},
|
|
767
|
+
pauseWhenHidden,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* The pause-when-hidden aggregate can flip when subscribers join or leave;
|
|
773
|
+
* the shared-transport subscription captures it at subscribe time, so
|
|
774
|
+
* re-subscribe when it changes.
|
|
775
|
+
*/
|
|
776
|
+
private resubscribeCollabEventsIfPauseChanged(): void {
|
|
777
|
+
if (!this.syncActive) return;
|
|
778
|
+
if (this.sseSubscribedWithPause === this.effectivePauseWhenHidden) return;
|
|
779
|
+
this.unsubscribeCollabEvents?.();
|
|
780
|
+
this.subscribeCollabEvents();
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
private handleSharedEvent(change: SyncEvent): void {
|
|
784
|
+
if (
|
|
785
|
+
change.source === "collab" &&
|
|
786
|
+
change.docId === this.docId &&
|
|
787
|
+
typeof change.update === "string"
|
|
788
|
+
) {
|
|
789
|
+
// Own echo — skip entirely (including the version tracking below, so
|
|
790
|
+
// the next poll re-delivers and dedupe happens there; matches the
|
|
791
|
+
// previous per-hook behavior).
|
|
792
|
+
if (this.requestSource && change.requestSource === this.requestSource) {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
try {
|
|
796
|
+
Y.applyUpdate(this.ydoc, base64ToUint8Array(change.update), "remote");
|
|
797
|
+
} catch {
|
|
798
|
+
// Malformed update — trigger state-vector fetch on next poll
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (change.requestSource === "agent") {
|
|
802
|
+
this.markAgentActive();
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Keep the poll cursor updated from shared-transport events so the poll
|
|
807
|
+
// loop starts from the right version when SSE drops.
|
|
808
|
+
if (typeof change.version === "number") {
|
|
809
|
+
this.pollVersion = Math.max(this.pollVersion, change.version);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private getActivePollInterval(): number {
|
|
814
|
+
return this.sseActive
|
|
815
|
+
? this.effectivePollIntervalWithSse
|
|
816
|
+
: this.effectivePollInterval;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private schedulePoll(): void {
|
|
820
|
+
if (!this.syncActive || this.disposed) return;
|
|
821
|
+
if (this.effectivePauseWhenHidden && isDocumentHidden()) return;
|
|
822
|
+
this.pollTimer = setTimeout(() => {
|
|
823
|
+
this.pollTimer = null;
|
|
824
|
+
void this.poll();
|
|
825
|
+
}, this.getActivePollInterval());
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* A subscriber joined or left, potentially changing the effective interval.
|
|
830
|
+
* If a poll is already scheduled, reschedule with the new cadence (the next
|
|
831
|
+
* natural tick would pick it up anyway; this just avoids a stale long wait
|
|
832
|
+
* when a faster subscriber joins).
|
|
833
|
+
*/
|
|
834
|
+
private reschedulePoll(): void {
|
|
835
|
+
if (this.pollTimer === null) return;
|
|
836
|
+
clearTimeout(this.pollTimer);
|
|
837
|
+
this.pollTimer = null;
|
|
838
|
+
this.schedulePoll();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
private async fetchStateVector(): Promise<void> {
|
|
842
|
+
try {
|
|
843
|
+
const stateVector = uint8ArrayToBase64(Y.encodeStateVector(this.ydoc));
|
|
844
|
+
const stateRes = await fetch(
|
|
845
|
+
`${this.baseUrl}/${this.docId}/state?stateVector=${encodeURIComponent(stateVector)}`,
|
|
846
|
+
);
|
|
847
|
+
if (stateRes.ok) {
|
|
848
|
+
const stateData = (await stateRes.json().catch(() => null)) as {
|
|
849
|
+
state?: string;
|
|
850
|
+
} | null;
|
|
851
|
+
if (this.disposed) return;
|
|
852
|
+
if (stateData?.state) {
|
|
853
|
+
const binary = base64ToUint8Array(stateData.state);
|
|
854
|
+
if (binary.length > 2) {
|
|
855
|
+
Y.applyUpdate(this.ydoc, binary, "remote");
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
} catch {
|
|
860
|
+
// Non-fatal; the next poll cycle will retry
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
private async poll(): Promise<void> {
|
|
865
|
+
if (!this.syncActive || this.disposed) return;
|
|
866
|
+
|
|
867
|
+
// Flush any pending local updates before polling so the server has the
|
|
868
|
+
// latest state before we read remote changes.
|
|
869
|
+
this.flushPendingUpdates();
|
|
870
|
+
|
|
871
|
+
try {
|
|
872
|
+
const res = await fetch(
|
|
873
|
+
agentNativePath(`/_agent-native/poll?since=${this.pollVersion}`),
|
|
874
|
+
);
|
|
875
|
+
if (!res.ok) throw new Error("HTTP " + res.status);
|
|
876
|
+
|
|
877
|
+
const data = await res.json();
|
|
878
|
+
if (!this.syncActive || this.disposed) return;
|
|
879
|
+
const { version, events } = data as {
|
|
880
|
+
version: number;
|
|
881
|
+
events: Array<{
|
|
882
|
+
source: string;
|
|
883
|
+
docId?: string;
|
|
884
|
+
update?: string;
|
|
885
|
+
requestSource?: string;
|
|
886
|
+
}>;
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// Detect ring-buffer overflow: if the version jumped by more than the
|
|
890
|
+
// ring buffer size, some events were evicted and we need a state-vector
|
|
891
|
+
// fetch to reconcile the gap.
|
|
892
|
+
const versionGap = version - this.lastPolledVersion;
|
|
893
|
+
const hadGap = versionGap > POLL_RING_BUFFER_SIZE;
|
|
894
|
+
|
|
895
|
+
for (const evt of events) {
|
|
896
|
+
if (evt.source === "collab" && evt.docId === this.docId && evt.update) {
|
|
897
|
+
if (this.requestSource && evt.requestSource === this.requestSource) {
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
try {
|
|
901
|
+
Y.applyUpdate(this.ydoc, base64ToUint8Array(evt.update), "remote");
|
|
902
|
+
} catch {
|
|
903
|
+
// Failed to apply — fetch full state-vector below
|
|
904
|
+
await this.fetchStateVector();
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
if (evt.requestSource === "agent") {
|
|
908
|
+
this.markAgentActive();
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
this.pollVersion = version;
|
|
914
|
+
this.lastPolledVersion = version;
|
|
915
|
+
this.pollCycleCount++;
|
|
916
|
+
this.consecutiveErrors = 0;
|
|
917
|
+
|
|
918
|
+
// Fetch state-vector only when needed:
|
|
919
|
+
// 1. Ring-buffer overflow detected (missed events).
|
|
920
|
+
// 2. Low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL cycles.
|
|
921
|
+
// 3. NOT on every cycle (the previous behavior causing 3 requests/cycle).
|
|
922
|
+
const shouldFetchStateVector =
|
|
923
|
+
hadGap || this.pollCycleCount % STATE_VECTOR_FETCH_INTERVAL === 0;
|
|
924
|
+
|
|
925
|
+
if (shouldFetchStateVector) {
|
|
926
|
+
await this.fetchStateVector();
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Sync awareness (cursor positions)
|
|
930
|
+
const localState = this.awareness.getLocalState();
|
|
931
|
+
if (localState && !this.disposed) {
|
|
932
|
+
try {
|
|
933
|
+
const awarenessRes = await fetch(
|
|
934
|
+
`${this.baseUrl}/${this.docId}/awareness`,
|
|
935
|
+
{
|
|
936
|
+
method: "POST",
|
|
937
|
+
headers: { "Content-Type": "application/json" },
|
|
938
|
+
body: JSON.stringify({
|
|
939
|
+
clientId: this.ydoc.clientID,
|
|
940
|
+
state: JSON.stringify(localState),
|
|
941
|
+
}),
|
|
942
|
+
},
|
|
943
|
+
);
|
|
944
|
+
if (awarenessRes.ok && !this.disposed) {
|
|
945
|
+
const awarenessData = await awarenessRes.json();
|
|
946
|
+
const remoteStates: RemoteAwarenessSnapshot[] = [];
|
|
947
|
+
for (const remote of awarenessData.states || []) {
|
|
948
|
+
try {
|
|
949
|
+
const remoteState = JSON.parse(remote.state);
|
|
950
|
+
remoteStates.push({
|
|
951
|
+
clientId: Number(remote.clientId),
|
|
952
|
+
state: remoteState,
|
|
953
|
+
});
|
|
954
|
+
} catch {
|
|
955
|
+
// Invalid state — skip
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
if (this.disposed) return;
|
|
959
|
+
const changes = reconcileRemoteAwarenessStates(
|
|
960
|
+
this.awareness.getStates() as Map<number, unknown>,
|
|
961
|
+
this.ydoc.clientID,
|
|
962
|
+
remoteStates,
|
|
963
|
+
);
|
|
964
|
+
if (
|
|
965
|
+
changes.added.length ||
|
|
966
|
+
changes.updated.length ||
|
|
967
|
+
changes.removed.length
|
|
968
|
+
) {
|
|
969
|
+
this.awareness.emit("change", [changes, "remote"]);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
} catch {
|
|
973
|
+
// Awareness sync failure is non-fatal
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
} catch {
|
|
977
|
+
// Network error — exponential backoff
|
|
978
|
+
this.consecutiveErrors++;
|
|
979
|
+
const backoff = calcBackoff(this.consecutiveErrors);
|
|
980
|
+
if (this.syncActive && !this.disposed) {
|
|
981
|
+
this.pollTimer = setTimeout(() => {
|
|
982
|
+
this.pollTimer = null;
|
|
983
|
+
void this.poll();
|
|
984
|
+
}, backoff);
|
|
985
|
+
}
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
this.schedulePoll();
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
private pollNow(): void {
|
|
993
|
+
if (!this.syncActive || this.disposed) return;
|
|
994
|
+
if (this.effectivePauseWhenHidden && isDocumentHidden()) return;
|
|
995
|
+
if (this.pollTimer) {
|
|
996
|
+
clearTimeout(this.pollTimer);
|
|
997
|
+
this.pollTimer = null;
|
|
998
|
+
}
|
|
999
|
+
void this.poll();
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Publish this tab's visibility to peers. A hidden tab pauses its poll, so
|
|
1004
|
+
* we push the state immediately (keepalive) instead of waiting for the next
|
|
1005
|
+
* cycle — otherwise peers keep treating a backgrounded tab as the visible
|
|
1006
|
+
* lead and an agent edit never lands on the tab the user is actually viewing.
|
|
1007
|
+
*/
|
|
1008
|
+
private publishVisibility(visible: boolean): void {
|
|
1009
|
+
this.awareness.setLocalStateField("visible", visible);
|
|
1010
|
+
const localState = this.awareness.getLocalState();
|
|
1011
|
+
if (!localState) return;
|
|
1012
|
+
fetch(`${this.baseUrl}/${this.docId}/awareness`, {
|
|
1013
|
+
method: "POST",
|
|
1014
|
+
headers: { "Content-Type": "application/json" },
|
|
1015
|
+
body: JSON.stringify({
|
|
1016
|
+
clientId: this.ydoc.clientID,
|
|
1017
|
+
state: JSON.stringify(localState),
|
|
1018
|
+
}),
|
|
1019
|
+
keepalive: true,
|
|
1020
|
+
}).catch(() => {});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
private handleVisibilityChange = (): void => {
|
|
1024
|
+
const visible = document.visibilityState === "visible";
|
|
1025
|
+
this.publishVisibility(visible);
|
|
1026
|
+
if (visible) {
|
|
1027
|
+
// Also flush any pending updates when coming back into view
|
|
1028
|
+
this.flushPendingUpdates();
|
|
1029
|
+
this.pollNow();
|
|
1030
|
+
} else if (this.effectivePauseWhenHidden && this.pollTimer) {
|
|
1031
|
+
clearTimeout(this.pollTimer);
|
|
1032
|
+
this.pollTimer = null;
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
private handleFocus = (): void => {
|
|
1037
|
+
this.pollNow();
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
// -------------------------------------------------------------------------
|
|
1041
|
+
// Awareness SSE fast-path
|
|
1042
|
+
// -------------------------------------------------------------------------
|
|
1043
|
+
|
|
1044
|
+
private applyAwarenessEvent(data: SyncEvent): void {
|
|
1045
|
+
if (
|
|
1046
|
+
data.source !== "awareness" ||
|
|
1047
|
+
data.type !== "awareness-change" ||
|
|
1048
|
+
data.docId !== this.docId
|
|
1049
|
+
) {
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
const states = Array.isArray(data.states)
|
|
1053
|
+
? (data.states as Array<{ clientId: number; state: string }>)
|
|
1054
|
+
: [];
|
|
1055
|
+
const remoteStates: RemoteAwarenessSnapshot[] = [];
|
|
1056
|
+
for (const remote of states) {
|
|
1057
|
+
try {
|
|
1058
|
+
remoteStates.push({
|
|
1059
|
+
clientId: Number(remote.clientId),
|
|
1060
|
+
state: JSON.parse(remote.state),
|
|
1061
|
+
});
|
|
1062
|
+
} catch {
|
|
1063
|
+
// Invalid state entry — skip
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const changes = reconcileRemoteAwarenessStates(
|
|
1067
|
+
this.awareness.getStates() as Map<number, unknown>,
|
|
1068
|
+
this.ydoc.clientID,
|
|
1069
|
+
remoteStates,
|
|
1070
|
+
);
|
|
1071
|
+
if (
|
|
1072
|
+
changes.added.length ||
|
|
1073
|
+
changes.updated.length ||
|
|
1074
|
+
changes.removed.length
|
|
1075
|
+
) {
|
|
1076
|
+
this.awareness.emit("change", [changes, "remote"]);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Registry of active connections keyed by "<baseUrl>\0<docId>".
|
|
1083
|
+
* Module-level singleton: survives React render cycles, shared across all
|
|
1084
|
+
* hook instances in the same browser tab.
|
|
1085
|
+
*/
|
|
1086
|
+
const collabConnectionRegistry = new Map<string, CollabDocConnection>();
|
|
1087
|
+
|
|
1088
|
+
function collabRegistryKey(docId: string, baseUrl: string): string {
|
|
1089
|
+
return `${baseUrl}\0${docId}`;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
function getOrCreateCollabConnection(
|
|
1093
|
+
docId: string,
|
|
1094
|
+
baseUrl: string,
|
|
1095
|
+
): CollabDocConnection {
|
|
1096
|
+
const key = collabRegistryKey(docId, baseUrl);
|
|
1097
|
+
let conn = collabConnectionRegistry.get(key);
|
|
1098
|
+
if (!conn || conn.disposed) {
|
|
1099
|
+
conn = new CollabDocConnection(docId, baseUrl);
|
|
1100
|
+
collabConnectionRegistry.set(key, conn);
|
|
1101
|
+
}
|
|
1102
|
+
return conn;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// ---------------------------------------------------------------------------
|
|
1106
|
+
// Internal test helpers — reset/inspect the connection registry between tests.
|
|
1107
|
+
// ---------------------------------------------------------------------------
|
|
1108
|
+
/** @internal */
|
|
1109
|
+
export function _resetCollabDocRegistryForTests(): void {
|
|
1110
|
+
for (const conn of Array.from(collabConnectionRegistry.values())) {
|
|
1111
|
+
conn.dispose();
|
|
1112
|
+
}
|
|
1113
|
+
collabConnectionRegistry.clear();
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/** @internal — current registry size, for leak assertions in tests. */
|
|
1117
|
+
export function _collabDocRegistrySizeForTests(): number {
|
|
1118
|
+
return collabConnectionRegistry.size;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
export function useCollaborativeDoc(
|
|
1122
|
+
options: UseCollaborativeDocOptions,
|
|
1123
|
+
): UseCollaborativeDocResult {
|
|
1124
|
+
const {
|
|
1125
|
+
docId,
|
|
1126
|
+
pollInterval = 2000,
|
|
1127
|
+
pollIntervalWithSse = 12000,
|
|
1128
|
+
pauseWhenHidden = true,
|
|
1129
|
+
baseUrl = agentNativePath("/_agent-native/collab"),
|
|
1130
|
+
requestSource,
|
|
1131
|
+
user,
|
|
1132
|
+
} = options;
|
|
1133
|
+
|
|
1134
|
+
// Bumped when the effect finds the memoized connection was disposed in the
|
|
1135
|
+
// render→effect gap (rare: a suspended transition outliving the linger
|
|
1136
|
+
// window) so the memo below re-acquires a live one.
|
|
1137
|
+
const [generation, setGeneration] = useState(0);
|
|
1138
|
+
|
|
1139
|
+
// Shared connection per docId. Acquired during render so the Y.Doc identity
|
|
1140
|
+
// is available on first render (TipTap binds on mount); get-or-create is
|
|
1141
|
+
// idempotent, so StrictMode's double render returns the same instance.
|
|
1142
|
+
const conn = useMemo(() => {
|
|
1143
|
+
void generation;
|
|
1144
|
+
if (!docId) return null;
|
|
1145
|
+
if (typeof window === "undefined") {
|
|
1146
|
+
// SSR render: per-hook detached doc, never started (matches the
|
|
1147
|
+
// previous per-hook behavior on the server).
|
|
1148
|
+
return new CollabDocConnection(docId, baseUrl, true);
|
|
1149
|
+
}
|
|
1150
|
+
return getOrCreateCollabConnection(docId, baseUrl);
|
|
1151
|
+
}, [docId, baseUrl, generation]);
|
|
1152
|
+
|
|
1153
|
+
const [snapshot, setSnapshot] = useState<CollabDocSnapshot>(() =>
|
|
1154
|
+
conn ? conn.snapshot : EMPTY_SNAPSHOT,
|
|
1155
|
+
);
|
|
1156
|
+
|
|
1157
|
+
// Render-time reset when the connection identity changes (docId switch) so
|
|
1158
|
+
// consumers never see the previous doc's state for a frame.
|
|
1159
|
+
const [prevConn, setPrevConn] = useState(conn);
|
|
1160
|
+
if (prevConn !== conn) {
|
|
1161
|
+
setPrevConn(conn);
|
|
1162
|
+
setSnapshot(conn ? conn.snapshot : EMPTY_SNAPSHOT);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// Subscribe (ref-count) — the first subscriber starts the connection, the
|
|
1166
|
+
// last one leaving schedules its teardown.
|
|
1167
|
+
useEffect(() => {
|
|
1168
|
+
if (!conn || conn.detached) return;
|
|
1169
|
+
if (conn.disposed) {
|
|
1170
|
+
// Disposed between render and effect — re-acquire a live connection.
|
|
1171
|
+
setGeneration((g) => g + 1);
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const id = Symbol("useCollaborativeDoc");
|
|
1175
|
+
conn.add(id, {
|
|
1176
|
+
pollInterval,
|
|
1177
|
+
pollIntervalWithSse,
|
|
1178
|
+
pauseWhenHidden,
|
|
1179
|
+
requestSource,
|
|
1180
|
+
onSnapshot: setSnapshot,
|
|
1181
|
+
});
|
|
1182
|
+
// Re-sync in case the connection changed state between render and effect.
|
|
1183
|
+
setSnapshot(conn.snapshot);
|
|
1184
|
+
return () => {
|
|
1185
|
+
conn.remove(id);
|
|
1186
|
+
};
|
|
1187
|
+
}, [conn, pollInterval, pollIntervalWithSse, pauseWhenHidden, requestSource]);
|
|
1188
|
+
|
|
1189
|
+
// Publish local user identity for cursor labels (set once per tab; the
|
|
1190
|
+
// connection dedupes repeated identical identities across subscribers).
|
|
1191
|
+
useEffect(() => {
|
|
1192
|
+
if (!conn || conn.detached || !user) return;
|
|
1193
|
+
conn.setUser({ name: user.name, email: user.email, color: user.color });
|
|
1194
|
+
}, [conn, user?.name, user?.email, user?.color]);
|
|
1195
|
+
|
|
1196
|
+
return {
|
|
1197
|
+
ydoc: conn ? conn.ydoc : null,
|
|
1198
|
+
awareness: conn ? conn.awareness : null,
|
|
1199
|
+
isLoading: snapshot.isLoading,
|
|
1200
|
+
isSynced: snapshot.isSynced,
|
|
1201
|
+
activeUsers: snapshot.activeUsers,
|
|
1202
|
+
agentActive: snapshot.agentActive,
|
|
1203
|
+
agentPresent: snapshot.agentPresent,
|
|
1204
|
+
};
|
|
1205
|
+
}
|