@vellumai/assistant 0.6.1 → 0.6.3
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/bun.lock +40 -40
- package/bunfig.toml +3 -0
- package/docker-entrypoint.sh +12 -2
- package/docs/architecture/memory.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +184 -69
- package/package.json +41 -41
- package/scripts/generate-openapi.ts +1 -2
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/browser-fill-credential.test.ts +229 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/catalog-files.test.ts +862 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/checker.test.ts +104 -170
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +125 -48
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/context-overflow-approval.test.ts +21 -6
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +1 -1
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-queue.test.ts +45 -2
- package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +4 -4
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +2 -2
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/gemini-provider.test.ts +2 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +707 -371
- package/src/__tests__/headless-browser-navigate.test.ts +389 -47
- package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
- package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
- package/src/__tests__/host-bash-proxy.test.ts +150 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
- package/src/__tests__/host-cu-proxy.test.ts +171 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/log-export-workspace.test.ts +190 -0
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +61 -2
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +101 -1
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/oauth-apps-routes.test.ts +17 -12
- package/src/__tests__/oauth-cli.test.ts +707 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +50 -14
- package/src/__tests__/oauth-store.test.ts +1386 -182
- package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
- package/src/__tests__/onboarding-template-contract.test.ts +74 -55
- package/src/__tests__/openai-provider.test.ts +2 -2
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/require-fresh-approval.test.ts +40 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
- package/src/__tests__/slack-channel-config.test.ts +12 -15
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +72 -1
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +11 -5
- package/src/__tests__/test-preload.ts +14 -0
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +62 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/loop.ts +12 -35
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +55 -0
- package/src/cli/__tests__/run-assistant-command.ts +34 -7
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/browser-relay.ts +339 -409
- package/src/cli/commands/credentials.ts +3 -3
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +18 -13
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +16 -2
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/providers.ts +200 -36
- package/src/cli/commands/oauth/shared.ts +5 -5
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +10 -3
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/contacts/SKILL.md +3 -0
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +12 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/outlook/SKILL.md +7 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/env-registry.ts +14 -0
- package/src/config/env.ts +21 -0
- package/src/config/feature-flag-registry.json +46 -7
- package/src/config/loader.ts +56 -1
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +46 -5
- package/src/config/schemas/host-browser.ts +66 -0
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +16 -0
- package/src/config/types.ts +0 -1
- package/src/context/post-turn-tool-result-truncation.ts +176 -0
- package/src/context/window-manager.ts +19 -1
- package/src/credential-execution/approval-bridge.ts +49 -16
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +6 -2
- package/src/daemon/context-overflow-approval.ts +5 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
- package/src/daemon/conversation-agent-loop.ts +74 -19
- package/src/daemon/conversation-attachments.ts +40 -1
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +66 -3
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +159 -20
- package/src/daemon/conversation-surfaces.ts +78 -12
- package/src/daemon/conversation-tool-setup.ts +74 -11
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +227 -11
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/conversations.ts +9 -139
- package/src/daemon/handlers/shared.ts +65 -0
- package/src/daemon/handlers/skills.ts +232 -37
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +191 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +86 -12
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/conversations.ts +59 -13
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/messages.ts +5 -6
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/settings.ts +12 -0
- package/src/daemon/message-types/skills.ts +10 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/server.ts +112 -35
- package/src/daemon/tool-side-effects.ts +6 -0
- package/src/daemon/transport-hints.ts +14 -0
- package/src/inbound/platform-callback-registration.ts +18 -17
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +59 -24
- package/src/memory/app-store.ts +31 -1
- package/src/memory/conversation-crud.ts +38 -10
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +65 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +12 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +177 -18
- package/src/memory/graph/capability-seed.ts +3 -5
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/retriever.ts +40 -22
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/llm-usage-store.ts +45 -4
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +1 -0
- package/src/memory/schema/oauth.ts +18 -13
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +8 -8
- package/src/oauth/byo-connection.ts +7 -7
- package/src/oauth/connect-orchestrator.ts +23 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +16 -16
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +214 -100
- package/src/oauth/platform-connection.test.ts +5 -5
- package/src/oauth/platform-connection.ts +4 -4
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +127 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -21
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -96
- package/src/prompts/templates/SOUL.md +11 -11
- package/src/providers/anthropic/client.ts +1 -0
- package/src/providers/types.ts +1 -1
- package/src/runtime/AGENTS.md +23 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/assistant-event-hub.ts +24 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +6 -7
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/chrome-extension-registry.ts +332 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +425 -70
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +6 -0
- package/src/runtime/migrations/migration-wizard.ts +22 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
- package/src/runtime/migrations/vbundle-importer.ts +55 -5
- package/src/runtime/pending-interactions.ts +29 -13
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/browser-cdp-routes.ts +229 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
- package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
- package/src/runtime/routes/conversation-management-routes.ts +108 -0
- package/src/runtime/routes/conversation-routes.ts +308 -28
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/host-browser-routes.ts +279 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-routes.ts +259 -16
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +60 -25
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +87 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +9 -97
- package/src/runtime/routes/skills-routes.ts +52 -2
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/usage-routes.ts +8 -7
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/schedule/scheduler.ts +7 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +42 -25
- package/src/security/secure-keys.ts +118 -25
- package/src/security/token-manager.ts +23 -10
- package/src/skills/catalog-files.ts +492 -0
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/subagent/manager.ts +131 -26
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +645 -340
- package/src/tools/browser/browser-manager.ts +36 -12
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
- package/src/tools/browser/cdp-client/errors.ts +34 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
- package/src/tools/browser/cdp-client/factory.ts +204 -0
- package/src/tools/browser/cdp-client/index.ts +14 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +52 -0
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/permission-checker.ts +77 -100
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -1
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +24 -21
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/types.ts +2 -3
- package/src/util/platform.ts +14 -19
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/029-seed-pkb.ts +1 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/top-level-renderer.ts +19 -1
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Widget Component Library
|
|
2
|
+
|
|
3
|
+
A CSS/JS widget library is auto-injected alongside the design system. Use these for standard UI patterns - skip them when custom HTML serves the user better.
|
|
4
|
+
|
|
5
|
+
## Layout widgets
|
|
6
|
+
|
|
7
|
+
| Widget | Purpose |
|
|
8
|
+
| ------------------------------------------------------------ | -------------------------------------------------------------- |
|
|
9
|
+
| `.v-metric-card` (`.v-metric-grid`) | Big number with emoji icon, label, trend |
|
|
10
|
+
| `.v-data-table` | Sortable table with sticky header, `th[data-sortable]` |
|
|
11
|
+
| `.v-tabs` / `.v-tab-bar` / `.v-tab-panel` | Tab navigation with keyboard support |
|
|
12
|
+
| `.v-accordion` / `.v-accordion-item` | Collapsible sections |
|
|
13
|
+
| `.v-search-bar` | Search input with clear button |
|
|
14
|
+
| `.v-empty-state` | No-data placeholder with CTA |
|
|
15
|
+
| `.v-timeline` / `.v-timeline-entry` | Vertical timeline (`.active`/`.success`/`.error`) |
|
|
16
|
+
| `.v-action-list` / `.v-action-list-item` | Rows with per-item actions |
|
|
17
|
+
| `.v-card-grid` | Responsive card grid |
|
|
18
|
+
| `.v-progress-bar` / `.v-progress-track` / `.v-progress-fill` | Horizontal progress |
|
|
19
|
+
| `.v-status-badge` | Colored pill with dot (`.success`/`.error`/`.warning`/`.info`) |
|
|
20
|
+
| `.v-stat-row` / `.v-stat` | Horizontal label-value pairs |
|
|
21
|
+
| `.v-toast` | Notification banner - prefer `vellum.widgets.toast()` |
|
|
22
|
+
| `.v-avatar-row` | Contact/team display |
|
|
23
|
+
| `.v-tag-group` | Wrapping tag row |
|
|
24
|
+
|
|
25
|
+
## Domain-specific widgets
|
|
26
|
+
|
|
27
|
+
| Widget | Purpose |
|
|
28
|
+
| ------------------ | ---------------------- |
|
|
29
|
+
| `.v-weather-card` | Temperature + forecast |
|
|
30
|
+
| `.v-stock-ticker` | Price display + chart |
|
|
31
|
+
| `.v-flight-card` | Flight info with route |
|
|
32
|
+
| `.v-billing-chart` | Usage/billing display |
|
|
33
|
+
| `.v-boarding-pass` | Pass-styled layout |
|
|
34
|
+
| `.v-itinerary` | Day-by-day travel plan |
|
|
35
|
+
| `.v-receipt` | Receipt layout |
|
|
36
|
+
| `.v-invoice` | Formal invoice |
|
|
37
|
+
|
|
38
|
+
## Content & landing page components
|
|
39
|
+
|
|
40
|
+
| Widget | Purpose |
|
|
41
|
+
| ------------------------------------------------ | --------------------------------------------------- |
|
|
42
|
+
| `.v-hero` / `.v-hero-badge` / `.v-hero-subtitle` | Hero banner with gradient, trust badge, accent word |
|
|
43
|
+
| `.v-section-header` / `.v-section-label` | Section intro with label |
|
|
44
|
+
| `.v-feature-grid` / `.v-feature-card` | Feature showcase with hover lift |
|
|
45
|
+
| `.v-pullquote` | Blockquote with gradient accent border |
|
|
46
|
+
| `.v-comparison` | Before/after cards (`.before`/`.after`) |
|
|
47
|
+
| `.v-page` | Centered container (max-width 600px) |
|
|
48
|
+
| `.v-gradient-text` | Accent-colored gradient text |
|
|
49
|
+
| `.v-animate-in` | Staggered fade-in for children |
|
|
50
|
+
|
|
51
|
+
## Widget JavaScript utilities
|
|
52
|
+
|
|
53
|
+
Interactive utilities at `window.vellum.widgets.*`:
|
|
54
|
+
|
|
55
|
+
### Charts
|
|
56
|
+
|
|
57
|
+
Always use these instead of hand-coding SVG/CSS charts:
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
vellum.widgets.sparkline("container-id", [10, 25, 15, 30], {
|
|
61
|
+
width: 200,
|
|
62
|
+
height: 40,
|
|
63
|
+
color: "var(--v-success)",
|
|
64
|
+
strokeWidth: 2,
|
|
65
|
+
fill: true,
|
|
66
|
+
});
|
|
67
|
+
vellum.widgets.barChart(
|
|
68
|
+
"container-id",
|
|
69
|
+
[
|
|
70
|
+
{ label: "Jan", value: 120 },
|
|
71
|
+
{ label: "Feb", value: 180, color: "var(--v-success)" },
|
|
72
|
+
],
|
|
73
|
+
{
|
|
74
|
+
width: 400,
|
|
75
|
+
height: 200,
|
|
76
|
+
showLabels: true,
|
|
77
|
+
showValues: true,
|
|
78
|
+
horizontal: false,
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
vellum.widgets.lineChart(
|
|
82
|
+
"container-id",
|
|
83
|
+
[
|
|
84
|
+
{ label: "Mon", value: 42 },
|
|
85
|
+
{ label: "Tue", value: 58 },
|
|
86
|
+
],
|
|
87
|
+
{ width: 400, height: 200, showDots: true, showGrid: true, gridLines: 4 },
|
|
88
|
+
);
|
|
89
|
+
vellum.widgets.progressRing("container-id", 75, {
|
|
90
|
+
size: 100,
|
|
91
|
+
strokeWidth: 8,
|
|
92
|
+
color: "var(--v-success)",
|
|
93
|
+
label: "75%",
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Data Formatting
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
vellum.widgets.formatCurrency(1234.56, "USD"); // "$1,234.56"
|
|
101
|
+
vellum.widgets.formatDate("2025-01-15", "relative"); // "3d ago"
|
|
102
|
+
vellum.widgets.formatDate("2025-01-15", "short"); // "1/15/25"
|
|
103
|
+
vellum.widgets.formatNumber(1234567, { compact: true }); // "1.2M"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Interactive Behaviors
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
vellum.widgets.sortTable("table-id"); // Wire th[data-sortable] click-to-sort
|
|
110
|
+
vellum.widgets.filterTable("table-id", "input-id"); // Live text search
|
|
111
|
+
vellum.widgets.tabs("tabs-id"); // Tab switching + keyboard nav
|
|
112
|
+
vellum.widgets.accordion("accordion-id", { allowMultiple: true });
|
|
113
|
+
vellum.widgets.multiSelect("table-id"); // Checkboxes + select-all
|
|
114
|
+
vellum.widgets.toast("Saved!", "success", 4000); // Auto-dismiss notification
|
|
115
|
+
vellum.widgets.countdown("timer-el", "2025-12-31T00:00:00Z", {
|
|
116
|
+
onComplete: () => {},
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## When to use widgets vs custom HTML
|
|
121
|
+
|
|
122
|
+
- **Use widgets** for standard patterns - tables, metrics, timelines, notifications
|
|
123
|
+
- **Use custom HTML** for novel or creative UIs - games, art tools, unique dashboards
|
|
124
|
+
- **Mix freely** - widgets compose well together and with custom elements
|
|
125
|
+
- **ALWAYS use `vellum.widgets.*` chart functions** instead of hand-coding SVG/CSS charts. They handle overflow clipping, bounds, scaling, and dark mode. Hand-coded charts break layouts.
|
|
@@ -6,6 +6,9 @@ metadata:
|
|
|
6
6
|
emoji: "👥"
|
|
7
7
|
vellum:
|
|
8
8
|
display-name: "Contacts"
|
|
9
|
+
activation-hints:
|
|
10
|
+
- "Look up contact info before asking the user for email addresses or phone numbers"
|
|
11
|
+
- "User wants to manage who can message the assistant, or create/revoke invite links"
|
|
9
12
|
---
|
|
10
13
|
|
|
11
14
|
Manage the user's contacts, relationship graph, access control (trusted contacts), and invite links. This skill covers contact CRUD with multi-channel tracking, controlling who can message the assistant through external channels (Telegram, phone), and creating/managing invite links that grant access.
|
|
@@ -6,6 +6,10 @@ metadata:
|
|
|
6
6
|
emoji: "📄"
|
|
7
7
|
vellum:
|
|
8
8
|
display-name: "Document"
|
|
9
|
+
activation-hints:
|
|
10
|
+
- "User asks to write, draft, or collaborate on long-form content — use the document editor for a better editing experience"
|
|
11
|
+
- "When content will be iterated on, reviewed, or exported, prefer the document editor over inline markdown"
|
|
12
|
+
- "When a file attachment contains a draft or document the user wants to iterate on, open it in the editor"
|
|
9
13
|
---
|
|
10
14
|
|
|
11
15
|
Create and edit long-form documents using the built-in rich text editor. Documents open in workspace mode with chat docked to the side.
|
|
@@ -110,22 +110,27 @@ When a user asks to declutter, clean up, or organize their email - start scannin
|
|
|
110
110
|
|
|
111
111
|
### Workflow
|
|
112
112
|
|
|
113
|
-
1. **Scan**: Call `gmail_sender_digest`. Default query targets promotions from the last 90 days.
|
|
113
|
+
1. **Scan**: Call `gmail_sender_digest`. Default query targets promotions currently in the inbox from the last 90 days (`in:inbox category:promotions newer_than:90d`). Counts shown in the table reflect only what is currently in the inbox — these are the emails that will be archived.
|
|
114
114
|
2. **Present**: Show results as a `ui_show` table with `selectionMode: "multiple"`:
|
|
115
115
|
- **Columns (exactly 3)**: Sender, Emails Found, Unsub?
|
|
116
116
|
- **Unsub? cell values**: Use rich cell format: `{ "text": "Yes", "icon": "checkmark.circle.fill", "iconColor": "success" }` when `has_unsubscribe` is true, `{ "text": "No", "icon": "minus.circle", "iconColor": "muted" }` when false.
|
|
117
117
|
- **Pre-select all rows** (`selected: true`) - users deselect what they want to keep
|
|
118
118
|
- **Caption**: Include two parts separated by a newline: (1) data scope, e.g. "Newsletters, notifications, and outreach from last 90 days. Deselect anything you want to keep." (adjusted to match the query used), and (2) the Unsub? column legend: "Unsub? - \"Yes\" means these emails contain an unsubscribe link, so I can opt you out automatically. \"No\" means no unsubscribe link was found - these will be archived but you may continue receiving them."
|
|
119
119
|
- **Action buttons (exactly 2)**: "Archive & Unsubscribe" (primary), "Archive Only" (secondary). **NEVER offer Delete, Trash, or any destructive action.**
|
|
120
|
-
3. **
|
|
120
|
+
3. **Embed scan_id in button data**: When constructing the action buttons in `ui_show`, include the `scan_id` from the `gmail_sender_digest` result in each button's `data` field. This ensures `scan_id` is forwarded automatically when the user clicks — the LLM does not need to recall it from earlier context:
|
|
121
|
+
```json
|
|
122
|
+
{ "id": "archive_unsubscribe", "label": "Archive & Unsubscribe", "style": "primary", "data": { "scan_id": "<scan_id value here>" } }
|
|
123
|
+
```
|
|
124
|
+
4. **Wait for user action**: Stop and wait. Do NOT proceed to archiving or unsubscribing until the user clicks one of the action buttons on the table. When the user clicks an action button you will receive a surface action message containing `action data: { scan_id, selectedIds }`:
|
|
125
|
+
- `selectedIds` are **sender IDs** (the `id` values from the scan result rows, base64-encoded email addresses) — NOT Gmail message IDs. Always use them as `sender_ids` with `scan_id`, never as `message_ids`.
|
|
121
126
|
- **Dismiss the table immediately** with `ui_dismiss` - it collapses to a completion chip
|
|
122
127
|
- **Show a `task_progress` card** with steps for each phase (e.g., "Archiving 89 senders (2,400 emails)", "Unsubscribing from 72 senders"). Update each step from `in_progress` → `completed` as each phase finishes.
|
|
123
128
|
- When all senders are processed, set the progress card's `status: "completed"`.
|
|
124
|
-
|
|
125
|
-
- **Archive all at once**: Call `gmail_archive` **once** with `scan_id`
|
|
129
|
+
5. **Act on selection** - batch, don't loop:
|
|
130
|
+
- **Archive all at once**: Call `gmail_archive` **once** with `scan_id` (from action data) + `sender_ids` set to all `selectedIds` from the action data. The tool resolves message IDs server-side and batches the Gmail API calls internally - never loop sender-by-sender. **Never** pass `selectedIds` as `message_ids` — they are sender IDs, not Gmail message IDs.
|
|
126
131
|
- **Unsubscribe in bulk**: If the action is "Archive & Unsubscribe", call `gmail_unsubscribe` for each sender that has `has_unsubscribe: true` - but emit **all** unsubscribe tool calls in a **single assistant response** (parallel tool use) rather than one-at-a-time across separate turns.
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
6. **Accurate summary**: The scan counts are exact - the `message_count` shown in the table matches the number of messages archived. Format: "Cleaned up [total_archived] emails from [sender_count] senders. Unsubscribed from [unsub_count]."
|
|
133
|
+
7. **Ongoing protection offer**: After reporting results, offer auto-archive filters:
|
|
129
134
|
- "Want me to set up auto-archive filters so future emails from these senders skip your inbox?"
|
|
130
135
|
- If yes, call `gmail_filters` with `action: "create"` for each sender with `from` set to the sender's email and `remove_label_ids: ["INBOX"]`.
|
|
131
136
|
- Then offer a recurring declutter schedule: "Want me to scan for new clutter monthly?" If yes, use `schedule_create` to set up a monthly declutter check.
|
|
@@ -156,7 +161,7 @@ Scan tools (`gmail_sender_digest`, `gmail_outreach_scan`) return a `scan_id` tha
|
|
|
156
161
|
|
|
157
162
|
Before composing any email that references a date or time:
|
|
158
163
|
|
|
159
|
-
1. Check the `
|
|
164
|
+
1. Check the `current_time:` field in the `<turn_context>` block for today's date and timezone
|
|
160
165
|
2. Verify that "tomorrow" means the day after today's date, "next week" means the upcoming Monday–Friday, etc.
|
|
161
166
|
3. If the email references a date from another message, cross-check it against the turn context to ensure it's in the future
|
|
162
167
|
|
|
@@ -490,7 +490,7 @@
|
|
|
490
490
|
"properties": {
|
|
491
491
|
"query": {
|
|
492
492
|
"type": "string",
|
|
493
|
-
"description": "Gmail search query (default 'category:promotions newer_than:90d')"
|
|
493
|
+
"description": "Gmail search query (default 'in:inbox category:promotions newer_than:90d')"
|
|
494
494
|
},
|
|
495
495
|
"max_messages": {
|
|
496
496
|
"type": "number",
|
|
@@ -49,7 +49,8 @@ export async function run(
|
|
|
49
49
|
_context: ToolContext,
|
|
50
50
|
): Promise<ToolExecutionResult> {
|
|
51
51
|
const account = input.account as string | undefined;
|
|
52
|
-
const query =
|
|
52
|
+
const query =
|
|
53
|
+
(input.query as string) ?? "in:inbox category:promotions newer_than:90d";
|
|
53
54
|
const maxMessages = Math.min(
|
|
54
55
|
(input.max_messages as number) ?? 5000,
|
|
55
56
|
MAX_MESSAGES_CAP,
|
|
@@ -35,6 +35,13 @@ When the user mentions "email" - sending, reading, checking, decluttering, draft
|
|
|
35
35
|
|
|
36
36
|
Do not offer AgentMail as an option or mention it unless the user specifically asks. If Outlook is not connected, guide them through Outlook setup - do not suggest AgentMail as an alternative.
|
|
37
37
|
|
|
38
|
+
## Connection Setup
|
|
39
|
+
|
|
40
|
+
### Outlook
|
|
41
|
+
|
|
42
|
+
1. **Try connecting directly first.** Run `assistant oauth status outlook`. This will show whether or not the user had previously connected their Outlook/Microsoft account. If so, they are ready to go.
|
|
43
|
+
2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
|
|
44
|
+
|
|
38
45
|
## Communication Style
|
|
39
46
|
|
|
40
47
|
- **Be action-oriented.** When the user asks to do something ("declutter", "check my email"), start doing it immediately. Don't ask for permission to read their inbox - that's obviously what they want.
|
|
@@ -10,21 +10,26 @@ const SETTINGS_TABS = [
|
|
|
10
10
|
"Sounds",
|
|
11
11
|
"Permissions & Privacy",
|
|
12
12
|
"Billing",
|
|
13
|
-
"
|
|
13
|
+
"Archive",
|
|
14
14
|
"Schedules",
|
|
15
15
|
"Developer",
|
|
16
16
|
] as const;
|
|
17
17
|
|
|
18
18
|
type SettingsTab = (typeof SETTINGS_TABS)[number];
|
|
19
19
|
|
|
20
|
+
const LEGACY_TAB_ALIASES: Record<string, SettingsTab> = {
|
|
21
|
+
"Archived Conversations": "Archive",
|
|
22
|
+
};
|
|
23
|
+
|
|
20
24
|
export async function run(
|
|
21
25
|
input: Record<string, unknown>,
|
|
22
26
|
context: ToolContext,
|
|
23
27
|
): Promise<ToolExecutionResult> {
|
|
24
|
-
const
|
|
28
|
+
const rawTab = input.tab as string;
|
|
29
|
+
const tab = LEGACY_TAB_ALIASES[rawTab] ?? rawTab;
|
|
25
30
|
if (!SETTINGS_TABS.includes(tab as SettingsTab)) {
|
|
26
31
|
return {
|
|
27
|
-
content: `Error: unknown tab "${
|
|
32
|
+
content: `Error: unknown tab "${rawTab}". Valid tabs: ${SETTINGS_TABS.join(
|
|
28
33
|
", ",
|
|
29
34
|
)}`,
|
|
30
35
|
isError: true,
|
|
@@ -63,6 +63,24 @@ Only the parent conversation that spawned a subagent can interact with it (check
|
|
|
63
63
|
|
|
64
64
|
Set `send_result_to_user: false` when spawning a subagent whose result is for internal processing only. The parent will still be notified on completion, but the notification will instruct it to read the result without presenting it to the user.
|
|
65
65
|
|
|
66
|
+
## Fork Mode
|
|
67
|
+
|
|
68
|
+
Forks are sub-agents that inherit the parent's full context -- messages, system prompt, and memory -- sharing the KV cache for near-free context inheritance. Use forks when the task benefits from knowing what you've been discussing; use a regular sub-agent when the task is self-contained.
|
|
69
|
+
|
|
70
|
+
**Key behaviors:** Forks always run as `general` role (the `role` parameter is ignored). `send_result_to_user` defaults to `false`. Read fork output with `last_n: 1` to get only the final synthesis.
|
|
71
|
+
|
|
72
|
+
**When to fork vs regular sub-agent:**
|
|
73
|
+
|
|
74
|
+
| Task | Mode |
|
|
75
|
+
|---|---|
|
|
76
|
+
| Single tool call (one search, one file read) | Direct -- don't spawn at all |
|
|
77
|
+
| Multi-page web research needing conversation context | Fork |
|
|
78
|
+
| Exploratory file search informed by prior discussion | Fork |
|
|
79
|
+
| Comparing multiple sources against what was discussed | Parallel forks |
|
|
80
|
+
| Self-contained task with a clear objective | Regular sub-agent |
|
|
81
|
+
|
|
82
|
+
Rule of thumb: "Does this task need to know what we've been talking about?" If yes, fork. If the objective is fully self-describing, use a regular sub-agent with a scoped role.
|
|
83
|
+
|
|
66
84
|
## Tips
|
|
67
85
|
|
|
68
86
|
- Do NOT poll `subagent_status` in a loop. You will be notified automatically when a subagent completes.
|
|
@@ -71,3 +89,6 @@ Set `send_result_to_user: false` when spawning a subagent whose result is for in
|
|
|
71
89
|
- Use `notify_parent` for interim findings instead of waiting for completion. This lets the parent act on partial results early.
|
|
72
90
|
- Use `subagent_message` to send follow-up instructions to a running subagent.
|
|
73
91
|
- Use `subagent_abort` to cancel a subagent that is no longer needed.
|
|
92
|
+
- Default to spawning subagents for any task that involves web research, multi-file exploration, or independent coding work. Serial execution should be the exception, not the rule.
|
|
93
|
+
- When a user request has both an information-gathering component and an action component, spawn a researcher immediately rather than doing the research inline yourself.
|
|
94
|
+
- Prefer spawning 2-3 focused subagents over one large general-purpose subagent. Smaller scopes finish faster and fail more gracefully.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "subagent_spawn",
|
|
6
|
-
"description": "Spawn an independent subagent to work on a task in parallel. The subagent runs autonomously and its results are reported back when complete.",
|
|
6
|
+
"description": "Spawn an independent subagent to work on a task in parallel. The subagent runs autonomously and its results are reported back when complete.\n\nTwo modes:\n- **Regular sub-agent** (fork: false or omitted): Gets only the objective + context fields. Use for self-contained tasks with clear objectives. Can use scoped roles (researcher, coder, planner).\n- **Fork** (fork: true): Inherits full parent context (messages, system prompt, memory). Shares KV cache for near-free context inheritance. Use when the task benefits from knowing what you've been discussing. Always runs as general role. Results are internal by default (send_result_to_user: false). Read with last_n: 1 to get only the final synthesis.\n\nDecision heuristic: Does the task need to know what we've been talking about? Fork. Is it self-contained? Regular sub-agent.",
|
|
7
7
|
"category": "orchestration",
|
|
8
8
|
"risk": "low",
|
|
9
9
|
"input_schema": {
|
|
@@ -19,16 +19,20 @@
|
|
|
19
19
|
},
|
|
20
20
|
"context": {
|
|
21
21
|
"type": "string",
|
|
22
|
-
"description": "Optional additional context to pass to the subagent"
|
|
22
|
+
"description": "Optional additional context to pass to the subagent. Ignored when fork is true — forks inherit the parent's full context."
|
|
23
|
+
},
|
|
24
|
+
"fork": {
|
|
25
|
+
"type": "boolean",
|
|
26
|
+
"description": "When true, the subagent inherits the parent's full context (messages, system prompt, memory) instead of receiving only the objective + context fields. Fork mode always runs as 'general' role (the role parameter is ignored) and defaults send_result_to_user to false. Use for tasks that benefit from the full conversational context."
|
|
23
27
|
},
|
|
24
28
|
"send_result_to_user": {
|
|
25
29
|
"type": "boolean",
|
|
26
|
-
"description": "Whether to present the subagent's result to the user when it completes. Defaults to true
|
|
30
|
+
"description": "Whether to present the subagent's result to the user when it completes. Defaults to true for regular sub-agents, false for forks. Set explicitly to override."
|
|
27
31
|
},
|
|
28
32
|
"role": {
|
|
29
33
|
"type": "string",
|
|
30
34
|
"enum": ["general", "researcher", "coder", "planner"],
|
|
31
|
-
"description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'general': full access (default)."
|
|
35
|
+
"description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'general': full access (default). Ignored when fork: true (forks always use general)."
|
|
32
36
|
},
|
|
33
37
|
"activity": {
|
|
34
38
|
"type": "string",
|
|
@@ -6,6 +6,11 @@ metadata:
|
|
|
6
6
|
emoji: "✅"
|
|
7
7
|
vellum:
|
|
8
8
|
display-name: "Tasks"
|
|
9
|
+
activation-hints:
|
|
10
|
+
- "User wants to add, check, or manage items on their to-do list or task queue"
|
|
11
|
+
- "For one-off action items, not recurring automations (use schedule for those)"
|
|
12
|
+
avoid-when:
|
|
13
|
+
- "User wants recurring/scheduled automation — use the schedule skill instead"
|
|
9
14
|
---
|
|
10
15
|
|
|
11
16
|
Two-layer task system: **task templates** (reusable definitions with input placeholders) and **work items** (instances in the Task Queue with priority tiers and status tracking).
|
|
@@ -86,6 +86,17 @@ export function getWorkspaceDirOverride(): string | undefined {
|
|
|
86
86
|
// profiler mode. The runtime uses them to locate, scope, and budget-limit
|
|
87
87
|
// profiler output on the workspace volume.
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* VELLUM_CPU_LIMIT — string (K8s resource format), default: undefined
|
|
91
|
+
* The CPU resource limit for the container (e.g. "2000m", "2").
|
|
92
|
+
* Set by the platform StatefulSet template to the exact K8s CPU limit.
|
|
93
|
+
* Used by the health endpoint to report accurate CPU core count inside
|
|
94
|
+
* gVisor sandboxes where cgroup files may expose the host node's CPUs.
|
|
95
|
+
*/
|
|
96
|
+
export function getCpuLimit(): string | undefined {
|
|
97
|
+
return str("VELLUM_CPU_LIMIT");
|
|
98
|
+
}
|
|
99
|
+
|
|
89
100
|
/**
|
|
90
101
|
* VELLUM_PROFILER_RUN_ID — string, default: undefined
|
|
91
102
|
* Unique identifier for the current profiler run. When set, the profiler
|
|
@@ -148,6 +159,7 @@ const KNOWN_VELLUM_VARS = new Set([
|
|
|
148
159
|
"VELLUM_DATA_DIR",
|
|
149
160
|
"VELLUM_DESKTOP_APP",
|
|
150
161
|
"VELLUM_DEV",
|
|
162
|
+
"VELLUM_DOCS_BASE_URL",
|
|
151
163
|
"VELLUM_ENABLE_INSECURE_LAN_PAIRING",
|
|
152
164
|
"VELLUM_HATCHED_BY",
|
|
153
165
|
"VELLUM_HOOK_EVENT",
|
|
@@ -164,6 +176,8 @@ const KNOWN_VELLUM_VARS = new Set([
|
|
|
164
176
|
"VELLUM_SSH_USER",
|
|
165
177
|
"VELLUM_UNSAFE_AUTH_BYPASS",
|
|
166
178
|
"VELLUM_WORKSPACE_DIR",
|
|
179
|
+
"VELLUM_CPU_LIMIT",
|
|
180
|
+
"VELLUM_MEMORY_LIMIT",
|
|
167
181
|
]);
|
|
168
182
|
|
|
169
183
|
/**
|
package/src/config/env.ts
CHANGED
|
@@ -164,6 +164,27 @@ export function getPlatformBaseUrl(): string {
|
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Derive the assistant service domain from the platform base URL.
|
|
169
|
+
*
|
|
170
|
+
* - `dev-platform.vellum.ai` → `dev.vellum.me`
|
|
171
|
+
* - `platform.vellum.ai` → `vellum.me`
|
|
172
|
+
* - anything else → `vellum.me` (safe default)
|
|
173
|
+
*/
|
|
174
|
+
export function getAssistantDomain(): string {
|
|
175
|
+
try {
|
|
176
|
+
const url = getPlatformBaseUrl();
|
|
177
|
+
const host = new URL(url).hostname;
|
|
178
|
+
const prefix = host.replace(/[-.]?platform\.vellum\.ai$/, "");
|
|
179
|
+
if (prefix) {
|
|
180
|
+
return `${prefix}.vellum.me`;
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
// Fall through to default
|
|
184
|
+
}
|
|
185
|
+
return "vellum.me";
|
|
186
|
+
}
|
|
187
|
+
|
|
167
188
|
let _platformAssistantIdOverride: string | undefined;
|
|
168
189
|
|
|
169
190
|
export function setPlatformAssistantId(value: string | undefined): void {
|
|
@@ -126,8 +126,8 @@
|
|
|
126
126
|
"scope": "macos",
|
|
127
127
|
"key": "referral-codes",
|
|
128
128
|
"label": "Referral Codes",
|
|
129
|
-
"description": "
|
|
130
|
-
"defaultEnabled":
|
|
129
|
+
"description": "Surface the Earn Credits referral entry points (sidebar drawer row and Billing tab button) that open the referral modal",
|
|
130
|
+
"defaultEnabled": true
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"id": "managed-sign-in",
|
|
@@ -178,11 +178,11 @@
|
|
|
178
178
|
"defaultEnabled": false
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
|
-
"id": "
|
|
181
|
+
"id": "multi-platform-assistant",
|
|
182
182
|
"scope": "assistant",
|
|
183
|
-
"key": "
|
|
184
|
-
"label": "
|
|
185
|
-
"description": "
|
|
183
|
+
"key": "multi-platform-assistant",
|
|
184
|
+
"label": "Multi-Platform Assistant Switcher",
|
|
185
|
+
"description": "Enable the menu-bar assistant switcher for managing multiple platform-hosted assistants (new/switch/retire)",
|
|
186
186
|
"defaultEnabled": false
|
|
187
187
|
},
|
|
188
188
|
{
|
|
@@ -288,7 +288,46 @@
|
|
|
288
288
|
"label": "Permission Controls V2",
|
|
289
289
|
"description": "Replace risk-level permission system with two independent controls: 'Ask before acting' (LLM behavior toggle) and 'Host access' (system-enforced gate)",
|
|
290
290
|
"defaultEnabled": false
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"id": "apple-container",
|
|
294
|
+
"scope": "macos",
|
|
295
|
+
"key": "apple-container",
|
|
296
|
+
"label": "Apple Container",
|
|
297
|
+
"description": "Enable assistant sandboxing via Apple Containers on macOS 26+, providing a lightweight native sandbox without third-party dependencies",
|
|
298
|
+
"defaultEnabled": false
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"id": "tool-result-truncation",
|
|
302
|
+
"scope": "assistant",
|
|
303
|
+
"key": "tool-result-truncation",
|
|
304
|
+
"label": "Post-Turn Tool Result Truncation",
|
|
305
|
+
"description": "Truncate large tool results after each assistant turn, persisting full content to disk for on-demand re-reads",
|
|
306
|
+
"defaultEnabled": false
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"id": "managed-gemini-embeddings-enabled",
|
|
310
|
+
"scope": "assistant",
|
|
311
|
+
"key": "managed-gemini-embeddings-enabled",
|
|
312
|
+
"label": "Managed Gemini Embeddings Enabled",
|
|
313
|
+
"description": "Route embedding requests through the platform runtime proxy using Vellum-managed Gemini credentials when available",
|
|
314
|
+
"defaultEnabled": false
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"id": "fork-from-message",
|
|
318
|
+
"scope": "macos",
|
|
319
|
+
"key": "fork-from-message",
|
|
320
|
+
"label": "Fork from Message",
|
|
321
|
+
"description": "Show the 'Fork from here' option in message overflow menus",
|
|
322
|
+
"defaultEnabled": false
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"id": "fork-from-message",
|
|
326
|
+
"scope": "macos",
|
|
327
|
+
"key": "fork-from-message",
|
|
328
|
+
"label": "Fork from Message",
|
|
329
|
+
"description": "Show the Fork from here option in message overflow menus",
|
|
330
|
+
"defaultEnabled": false
|
|
291
331
|
}
|
|
292
332
|
]
|
|
293
333
|
}
|
|
294
|
-
|
package/src/config/loader.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { dirname, join } from "node:path";
|
|
|
11
11
|
import { ConfigError } from "../util/errors.js";
|
|
12
12
|
import { getLogger } from "../util/logger.js";
|
|
13
13
|
import { ensureDataDir, getWorkspaceConfigPath } from "../util/platform.js";
|
|
14
|
+
import { isAssistantFeatureFlagEnabled } from "./assistant-feature-flags.js";
|
|
14
15
|
import { AssistantConfigSchema } from "./schema.js";
|
|
15
16
|
import type { AssistantConfig } from "./types.js";
|
|
16
17
|
|
|
@@ -385,7 +386,46 @@ export function loadConfig(): AssistantConfig {
|
|
|
385
386
|
warnAndStripDeprecatedFields(fileConfig, configPath);
|
|
386
387
|
|
|
387
388
|
// Validate and apply defaults via Zod schema
|
|
388
|
-
|
|
389
|
+
let config = validateWithSchema(fileConfig);
|
|
390
|
+
|
|
391
|
+
// Managed Gemini embedding defaults migration.
|
|
392
|
+
// When on a managed platform (IS_PLATFORM=true) with the feature flag
|
|
393
|
+
// enabled and no explicit embedding provider chosen (provider=auto),
|
|
394
|
+
// persist Gemini embedding defaults into the raw config file.
|
|
395
|
+
// Idempotent: once provider=gemini is written, subsequent loads skip this.
|
|
396
|
+
if (config.memory.embeddings.provider === "auto") {
|
|
397
|
+
try {
|
|
398
|
+
if (
|
|
399
|
+
(process.env.IS_PLATFORM === "true" ||
|
|
400
|
+
process.env.IS_PLATFORM === "1") &&
|
|
401
|
+
isManagedGeminiFFEnabled(config)
|
|
402
|
+
) {
|
|
403
|
+
setNestedValue(fileConfig, "memory.embeddings.provider", "gemini");
|
|
404
|
+
setNestedValue(
|
|
405
|
+
fileConfig,
|
|
406
|
+
"memory.embeddings.geminiModel",
|
|
407
|
+
"gemini-embedding-2-preview",
|
|
408
|
+
);
|
|
409
|
+
setNestedValue(
|
|
410
|
+
fileConfig,
|
|
411
|
+
"memory.embeddings.geminiDimensions",
|
|
412
|
+
3072,
|
|
413
|
+
);
|
|
414
|
+
setNestedValue(fileConfig, "memory.qdrant.vectorSize", 3072);
|
|
415
|
+
writeFileSync(configPath, JSON.stringify(fileConfig, null, 2) + "\n");
|
|
416
|
+
log.info(
|
|
417
|
+
"Applied managed Gemini embedding defaults (provider=gemini, model=gemini-embedding-2-preview, dimensions=3072, vectorSize=3072)",
|
|
418
|
+
);
|
|
419
|
+
// Re-validate so the returned config reflects the migration.
|
|
420
|
+
config = validateWithSchema(fileConfig);
|
|
421
|
+
}
|
|
422
|
+
} catch (err) {
|
|
423
|
+
log.warn(
|
|
424
|
+
{ err },
|
|
425
|
+
"Managed Gemini defaults migration failed — continuing with existing config",
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
389
429
|
|
|
390
430
|
// If the config file didn't exist, write the full defaults to disk so
|
|
391
431
|
// users can discover and edit all available options.
|
|
@@ -421,6 +461,21 @@ export function loadConfig(): AssistantConfig {
|
|
|
421
461
|
}
|
|
422
462
|
}
|
|
423
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Check whether the managed-gemini-embeddings-enabled feature flag is on.
|
|
466
|
+
* Wrapped in a try/catch so a flag-resolver failure never breaks config loading.
|
|
467
|
+
*/
|
|
468
|
+
function isManagedGeminiFFEnabled(config: AssistantConfig): boolean {
|
|
469
|
+
try {
|
|
470
|
+
return isAssistantFeatureFlagEnabled(
|
|
471
|
+
"managed-gemini-embeddings-enabled",
|
|
472
|
+
config,
|
|
473
|
+
);
|
|
474
|
+
} catch {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
424
479
|
export function saveConfig(config: AssistantConfig): void {
|
|
425
480
|
ensureMigratedDataDir();
|
|
426
481
|
const configPath = getConfigPath();
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips environment-specific fields from config JSON before transferring
|
|
3
|
+
* between local and platform environments (teleport/restore).
|
|
4
|
+
*
|
|
5
|
+
* Fields removed or reset:
|
|
6
|
+
* - `ingress.publicBaseUrl` → set to `""`
|
|
7
|
+
* - `ingress.enabled` → deleted
|
|
8
|
+
* - `daemon` → deleted entirely
|
|
9
|
+
* - `skills.load.extraDirs` → set to `[]`
|
|
10
|
+
*/
|
|
11
|
+
export function sanitizeConfigForTransfer(configJson: string): string {
|
|
12
|
+
let config: Record<string, unknown>;
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(configJson);
|
|
15
|
+
if (
|
|
16
|
+
typeof parsed !== "object" ||
|
|
17
|
+
parsed === null ||
|
|
18
|
+
Array.isArray(parsed)
|
|
19
|
+
) {
|
|
20
|
+
return configJson;
|
|
21
|
+
}
|
|
22
|
+
config = parsed;
|
|
23
|
+
} catch {
|
|
24
|
+
return configJson;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Strip ingress environment-specific fields
|
|
28
|
+
if (config.ingress && typeof config.ingress === "object") {
|
|
29
|
+
const ingress = config.ingress as Record<string, unknown>;
|
|
30
|
+
ingress.publicBaseUrl = "";
|
|
31
|
+
delete ingress.enabled;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Strip daemon entirely
|
|
35
|
+
delete config.daemon;
|
|
36
|
+
|
|
37
|
+
// Strip skills.load.extraDirs
|
|
38
|
+
if (config.skills && typeof config.skills === "object") {
|
|
39
|
+
const skills = config.skills as Record<string, unknown>;
|
|
40
|
+
if (skills.load && typeof skills.load === "object") {
|
|
41
|
+
const load = skills.load as Record<string, unknown>;
|
|
42
|
+
load.extraDirs = [];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return JSON.stringify(config, null, 2) + "\n";
|
|
47
|
+
}
|