@vellumai/assistant 0.5.6 → 0.5.8
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/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +3 -2
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docker-entrypoint.sh +9 -0
- package/docs/architecture/keychain-broker.md +45 -240
- package/docs/architecture/memory.md +13 -11
- package/docs/architecture/security.md +0 -17
- package/docs/credential-execution-service.md +2 -2
- package/node_modules/@vellumai/ces-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
- package/node_modules/@vellumai/credential-storage/package.json +1 -0
- package/node_modules/@vellumai/egress-proxy/package.json +1 -0
- package/package.json +2 -3
- package/src/__tests__/actor-token-service.test.ts +0 -114
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
- package/src/__tests__/ces-startup-timeout.test.ts +40 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -5
- package/src/__tests__/channel-readiness-service.test.ts +1 -60
- package/src/__tests__/checker.test.ts +4 -2
- package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -2
- package/src/__tests__/config-schema.test.ts +3 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +2 -4
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/conversation-queue.test.ts +0 -1
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-slash-queue.test.ts +0 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
- package/src/__tests__/conversation-title-service.test.ts +87 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/credential-execution-client.test.ts +5 -2
- package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
- package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
- package/src/__tests__/credential-security-e2e.test.ts +1 -67
- package/src/__tests__/credential-security-invariants.test.ts +6 -50
- package/src/__tests__/credentials-cli.test.ts +82 -3
- package/src/__tests__/daemon-credential-client.test.ts +123 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -7
- package/src/__tests__/http-user-message-parity.test.ts +3 -103
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
- package/src/__tests__/intent-routing.test.ts +0 -13
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
- package/src/__tests__/journal-context.test.ts +335 -0
- package/src/__tests__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
- package/src/__tests__/memory-recall-quality.test.ts +48 -17
- package/src/__tests__/memory-regressions.test.ts +408 -363
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
- package/src/__tests__/migration-export-http.test.ts +2 -2
- package/src/__tests__/migration-import-commit-http.test.ts +2 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
- package/src/__tests__/migration-validate-http.test.ts +2 -2
- package/src/__tests__/non-member-access-request.test.ts +2 -7
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/notification-decision-strategy.test.ts +71 -0
- package/src/__tests__/oauth-cli.test.ts +5 -1
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
- package/src/__tests__/provider-error-scenarios.test.ts +0 -267
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/relay-server.test.ts +1 -2
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -1
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +95 -272
- package/src/__tests__/shell-identity.test.ts +96 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
- package/src/__tests__/skill-feature-flags.test.ts +46 -45
- package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
- package/src/__tests__/skill-load-inline-command.test.ts +8 -12
- package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
- package/src/__tests__/skill-load-tool.test.ts +0 -2
- package/src/__tests__/skill-memory.test.ts +17 -3
- package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
- package/src/__tests__/skills.test.ts +0 -2
- package/src/__tests__/slack-inbound-verification.test.ts +0 -4
- package/src/__tests__/stale-approval-dedup.test.ts +171 -0
- package/src/__tests__/stt-hints.test.ts +437 -0
- package/src/__tests__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/task-memory-cleanup.test.ts +14 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
- package/src/__tests__/voice-quality.test.ts +58 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/acp/agent-process.ts +9 -1
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +164 -38
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +90 -8
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +129 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/stt-hints.ts +189 -0
- package/src/calls/tts-text-sanitizer.ts +61 -0
- package/src/calls/twilio-routes.ts +34 -5
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +38 -5
- package/src/calls/voice-session-bridge.ts +7 -12
- package/src/cli/commands/avatar.ts +2 -2
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/credentials.ts +128 -82
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/keys.ts +7 -7
- package/src/cli/commands/memory.ts +1 -1
- package/src/cli/commands/oauth/connections.ts +11 -29
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +525 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/cli/lib/daemon-credential-client.ts +284 -0
- package/src/cli.ts +1 -1
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/AGENTS.md +34 -0
- package/src/config/bundled-skills/acp/SKILL.md +10 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +15 -2
- package/src/config/bundled-skills/settings/TOOLS.json +47 -2
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-skills/slack/SKILL.md +1 -1
- package/src/config/bundled-tool-registry.ts +5 -11
- package/src/config/defaults.ts +0 -2
- package/src/config/env-registry.ts +5 -5
- package/src/config/env.ts +21 -14
- package/src/config/feature-flag-registry.json +49 -9
- package/src/config/loader.ts +106 -42
- package/src/config/schema.ts +9 -29
- package/src/config/schemas/calls.ts +30 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/inference.ts +2 -2
- package/src/config/schemas/journal.ts +16 -0
- package/src/config/schemas/memory-processing.ts +2 -2
- package/src/config/schemas/security.ts +0 -4
- package/src/config/types.ts +1 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/credential-execution/approval-bridge.ts +1 -0
- package/src/credential-execution/executable-discovery.ts +28 -4
- package/src/credential-execution/feature-gates.ts +16 -0
- package/src/credential-execution/process-manager.ts +38 -0
- package/src/credential-execution/startup-timeout.ts +36 -0
- package/src/daemon/approval-generators.ts +3 -9
- package/src/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +5 -0
- package/src/daemon/conversation-error.ts +13 -1
- package/src/daemon/conversation-memory.ts +1 -2
- package/src/daemon/conversation-process.ts +18 -1
- package/src/daemon/conversation-surfaces.ts +30 -1
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +21 -1
- package/src/daemon/guardian-action-generators.ts +3 -9
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +234 -51
- package/src/daemon/message-types/conversations.ts +4 -4
- package/src/daemon/message-types/diagnostics.ts +3 -22
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/message-types/upgrades.ts +8 -0
- package/src/daemon/server.ts +32 -95
- package/src/events/domain-events.ts +2 -1
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/app-store.ts +31 -0
- package/src/memory/conversation-title-service.ts +50 -1
- package/src/memory/db-init.ts +16 -0
- package/src/memory/indexer.ts +19 -10
- package/src/memory/items-extractor.ts +328 -321
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/summarization.ts +26 -16
- package/src/memory/jobs-store.ts +63 -6
- package/src/memory/jobs-worker.ts +31 -7
- package/src/memory/journal-memory.ts +214 -0
- package/src/memory/migrations/001-job-deferrals.ts +19 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
- package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
- package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
- package/src/memory/migrations/116-messages-fts.ts +106 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
- package/src/memory/migrations/141-rename-verification-table.ts +54 -0
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
- package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
- package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
- package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
- package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
- package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
- package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
- package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
- package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +98 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/retriever.test.ts +37 -25
- package/src/memory/retriever.ts +24 -49
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/memory-core.ts +2 -0
- package/src/memory/search/formatting.ts +7 -44
- package/src/memory/search/staleness.ts +4 -0
- package/src/memory/search/tier-classifier.ts +10 -2
- package/src/memory/search/types.ts +2 -5
- package/src/memory/task-memory-cleanup.ts +4 -3
- package/src/notifications/adapters/slack.ts +168 -6
- package/src/notifications/broadcaster.ts +1 -0
- package/src/notifications/copy-composer.ts +59 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/notifications/signal.ts +2 -0
- package/src/notifications/types.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/journal-context.ts +133 -0
- package/src/prompts/persona-resolver.ts +194 -0
- package/src/prompts/system-prompt.ts +44 -4
- package/src/prompts/templates/SOUL.md +10 -0
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/provider-send-message.ts +3 -32
- package/src/providers/registry.ts +29 -179
- package/src/providers/types.ts +1 -1
- package/src/runtime/access-request-helper.ts +4 -0
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
- package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
- package/src/runtime/auth/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +17 -1
- package/src/runtime/auth/token-service.ts +43 -138
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/gateway-client.ts +47 -4
- package/src/runtime/guardian-decision-types.ts +45 -4
- package/src/runtime/http-server.ts +31 -3
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/access-request-decision.ts +2 -2
- package/src/runtime/routes/app-management-routes.ts +2 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/channel-readiness-routes.ts +9 -4
- package/src/runtime/routes/conversation-query-routes.ts +63 -1
- package/src/runtime/routes/conversation-routes.ts +4 -44
- package/src/runtime/routes/debug-routes.ts +12 -9
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/guardian-approval-interception.ts +168 -11
- package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
- package/src/runtime/routes/identity-routes.ts +19 -30
- package/src/runtime/routes/inbound-message-handler.ts +31 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
- package/src/runtime/routes/integrations/twilio.ts +52 -10
- package/src/runtime/routes/integrations/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -3
- package/src/runtime/routes/memory-item-routes.ts +46 -14
- package/src/runtime/routes/migration-rollback-routes.ts +209 -0
- package/src/runtime/routes/migration-routes.ts +17 -1
- package/src/runtime/routes/notification-routes.ts +58 -0
- package/src/runtime/routes/schedule-routes.ts +65 -0
- package/src/runtime/routes/secret-routes.ts +141 -10
- package/src/runtime/routes/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +96 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
- package/src/runtime/routes/workspace-commit-routes.ts +62 -0
- package/src/runtime/routes/workspace-routes.test.ts +22 -1
- package/src/runtime/routes/workspace-routes.ts +1 -1
- package/src/runtime/routes/workspace-utils.ts +86 -2
- package/src/security/ces-credential-client.ts +75 -29
- package/src/security/ces-rpc-credential-backend.ts +86 -0
- package/src/security/credential-backend.ts +22 -92
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +113 -115
- package/src/skills/catalog-install.ts +6 -32
- package/src/skills/skill-memory.ts +1 -0
- package/src/subagent/manager.ts +2 -5
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/acp/spawn.ts +78 -1
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/credentials/vault.ts +5 -3
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/definitions.ts +3 -2
- package/src/tools/memory/handlers.ts +10 -7
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/types.ts +0 -8
- package/src/util/browser.ts +15 -0
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +4 -51
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/migrations/001-avatar-rename.ts +15 -0
- package/src/workspace/migrations/003-seed-device-id.ts +17 -1
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
- package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
- package/src/workspace/migrations/006-services-config.ts +49 -0
- package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
- package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
- package/src/workspace/migrations/registry.ts +12 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/workspace/provider-commit-message-generator.ts +12 -21
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
- package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
- package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
- package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
- package/src/__tests__/swarm-orchestrator.test.ts +0 -463
- package/src/__tests__/swarm-plan-validator.test.ts +0 -384
- package/src/__tests__/swarm-recursion.test.ts +0 -197
- package/src/__tests__/swarm-router-planner.test.ts +0 -234
- package/src/__tests__/swarm-tool.test.ts +0 -185
- package/src/__tests__/swarm-worker-backend.test.ts +0 -144
- package/src/__tests__/swarm-worker-runner.test.ts +0 -288
- package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
- package/src/commands/cc-command-registry.ts +0 -248
- package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
- package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
- package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
- package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/search/lexical.ts +0 -48
- package/src/providers/failover.ts +0 -186
- package/src/runtime/local-gateway-health.ts +0 -275
- package/src/security/secret-ingress.ts +0 -68
- package/src/swarm/backend-claude-code.ts +0 -225
- package/src/swarm/checkpoint.ts +0 -137
- package/src/swarm/graph-utils.ts +0 -53
- package/src/swarm/index.ts +0 -55
- package/src/swarm/limits.ts +0 -66
- package/src/swarm/orchestrator.ts +0 -424
- package/src/swarm/plan-validator.ts +0 -117
- package/src/swarm/router-planner.ts +0 -162
- package/src/swarm/router-prompts.ts +0 -39
- package/src/swarm/synthesizer.ts +0 -81
- package/src/swarm/types.ts +0 -72
- package/src/swarm/worker-backend.ts +0 -131
- package/src/swarm/worker-prompts.ts +0 -80
- package/src/swarm/worker-runner.ts +0 -170
- package/src/tools/claude-code/claude-code.ts +0 -610
- package/src/tools/swarm/delegate.ts +0 -205
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { isInviteCodeRedemptionEnabled } from "../../../channels/config.js";
|
|
10
10
|
import type { ChannelId } from "../../../channels/types.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
findContactChannel,
|
|
13
|
+
findGuardianForChannel,
|
|
14
|
+
} from "../../../contacts/contact-store.js";
|
|
12
15
|
import { touchChannelLastSeen } from "../../../contacts/contacts-write.js";
|
|
13
16
|
import type {
|
|
14
17
|
ChannelStatus,
|
|
@@ -21,7 +24,10 @@ import {
|
|
|
21
24
|
findByInviteCodeHash,
|
|
22
25
|
findByInviteCodeHashAnyChannel,
|
|
23
26
|
} from "../../../memory/invite-store.js";
|
|
27
|
+
import { MESSAGE_PREVIEW_MAX_LENGTH } from "../../../notifications/copy-composer.js";
|
|
28
|
+
import { resolveGuardianName } from "../../../prompts/user-reference.js";
|
|
24
29
|
import { getLogger } from "../../../util/logger.js";
|
|
30
|
+
import { truncate } from "../../../util/truncate.js";
|
|
25
31
|
import { hashVoiceCode } from "../../../util/voice-code.js";
|
|
26
32
|
import { notifyGuardianOfAccessRequest } from "../../access-request-helper.js";
|
|
27
33
|
import { getInviteAdapterRegistry } from "../../channel-invite-transport.js";
|
|
@@ -32,6 +38,7 @@ import {
|
|
|
32
38
|
resolveBootstrapToken,
|
|
33
39
|
} from "../../channel-verification-service.js";
|
|
34
40
|
import { deliverChannelReply } from "../../gateway-client.js";
|
|
41
|
+
import { ensureVellumGuardianBinding } from "../../guardian-vellum-migration.js";
|
|
35
42
|
import {
|
|
36
43
|
redeemInvite,
|
|
37
44
|
redeemInviteByCode,
|
|
@@ -40,6 +47,42 @@ import { getInviteRedemptionReply } from "../../invite-redemption-templates.js";
|
|
|
40
47
|
|
|
41
48
|
const log = getLogger("runtime-http");
|
|
42
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the guardian's display name for use in requester-facing messages.
|
|
52
|
+
*
|
|
53
|
+
* Uses the assistant's anchored vellum principal to validate the guardian
|
|
54
|
+
* contact, matching the same strategy used by `notifyGuardianOfAccessRequest`.
|
|
55
|
+
* This prevents stale or cross-assistant contacts from leaking a wrong name.
|
|
56
|
+
*/
|
|
57
|
+
function resolveGuardianLabel(
|
|
58
|
+
sourceChannel: ChannelId,
|
|
59
|
+
canonicalAssistantId: string,
|
|
60
|
+
): string {
|
|
61
|
+
const anchoredPrincipalId = ensureVellumGuardianBinding(canonicalAssistantId);
|
|
62
|
+
|
|
63
|
+
// Try source-channel guardian, but only accept it when the principal
|
|
64
|
+
// matches the assistant's anchor.
|
|
65
|
+
const sourceGuardian = findGuardianForChannel(sourceChannel);
|
|
66
|
+
if (
|
|
67
|
+
sourceGuardian &&
|
|
68
|
+
sourceGuardian.contact.principalId === anchoredPrincipalId
|
|
69
|
+
) {
|
|
70
|
+
return resolveGuardianName(sourceGuardian.contact.displayName);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Fall back to the vellum-channel guardian with the same anchor check.
|
|
74
|
+
const vellumGuardian = findGuardianForChannel("vellum");
|
|
75
|
+
if (
|
|
76
|
+
vellumGuardian &&
|
|
77
|
+
vellumGuardian.contact.principalId === anchoredPrincipalId
|
|
78
|
+
) {
|
|
79
|
+
return resolveGuardianName(vellumGuardian.contact.displayName);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// No anchored guardian found — use generic fallback.
|
|
83
|
+
return resolveGuardianName(undefined);
|
|
84
|
+
}
|
|
85
|
+
|
|
43
86
|
// ---------------------------------------------------------------------------
|
|
44
87
|
// Public API
|
|
45
88
|
// ---------------------------------------------------------------------------
|
|
@@ -321,6 +364,10 @@ export async function enforceIngressAcl(
|
|
|
321
364
|
actorExternalId: canonicalSenderId ?? rawSenderId,
|
|
322
365
|
actorDisplayName,
|
|
323
366
|
actorUsername,
|
|
367
|
+
messagePreview: truncate(
|
|
368
|
+
trimmedContent,
|
|
369
|
+
MESSAGE_PREVIEW_MAX_LENGTH,
|
|
370
|
+
),
|
|
324
371
|
});
|
|
325
372
|
} catch (err) {
|
|
326
373
|
log.error(
|
|
@@ -349,7 +396,7 @@ export async function enforceIngressAcl(
|
|
|
349
396
|
dmCallbackUrl,
|
|
350
397
|
{
|
|
351
398
|
chatId: senderUserId,
|
|
352
|
-
text:
|
|
399
|
+
text: `I don't recognize you yet! I've let ${resolveGuardianLabel(sourceChannel, canonicalAssistantId)} know you're trying to reach me. They'll need to share a 6-digit verification code with you — ask them directly if you know them. Once you have the code, reply here with it.`,
|
|
353
400
|
assistantId,
|
|
354
401
|
},
|
|
355
402
|
mintBearerToken(),
|
|
@@ -387,6 +434,10 @@ export async function enforceIngressAcl(
|
|
|
387
434
|
actorExternalId: canonicalSenderId ?? rawSenderId,
|
|
388
435
|
actorDisplayName,
|
|
389
436
|
actorUsername,
|
|
437
|
+
messagePreview: truncate(
|
|
438
|
+
trimmedContent,
|
|
439
|
+
MESSAGE_PREVIEW_MAX_LENGTH,
|
|
440
|
+
),
|
|
390
441
|
});
|
|
391
442
|
guardianNotified = accessResult.notified;
|
|
392
443
|
} catch (err) {
|
|
@@ -398,7 +449,7 @@ export async function enforceIngressAcl(
|
|
|
398
449
|
|
|
399
450
|
if (replyCallbackUrl) {
|
|
400
451
|
const replyText = guardianNotified
|
|
401
|
-
?
|
|
452
|
+
? `Hmm looks like you don't have access to talk to me. I'll let ${resolveGuardianLabel(sourceChannel, canonicalAssistantId)} know you tried talking to me and get back to you.`
|
|
402
453
|
: "Sorry, you haven't been approved to message this assistant.";
|
|
403
454
|
const replyPayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
404
455
|
chatId: conversationExternalId,
|
|
@@ -579,6 +630,10 @@ export async function enforceIngressAcl(
|
|
|
579
630
|
previousMemberStatus: channelStatusToMemberStatus(
|
|
580
631
|
resolvedMember.channel.status,
|
|
581
632
|
),
|
|
633
|
+
messagePreview: truncate(
|
|
634
|
+
trimmedContent,
|
|
635
|
+
MESSAGE_PREVIEW_MAX_LENGTH,
|
|
636
|
+
),
|
|
582
637
|
});
|
|
583
638
|
} catch (err) {
|
|
584
639
|
log.error(
|
|
@@ -603,7 +658,7 @@ export async function enforceIngressAcl(
|
|
|
603
658
|
dmCallbackUrl,
|
|
604
659
|
{
|
|
605
660
|
chatId: senderUserId,
|
|
606
|
-
text:
|
|
661
|
+
text: `I don't recognize you yet! I've let ${resolveGuardianLabel(sourceChannel, canonicalAssistantId)} know you're trying to reach me. They'll need to share a 6-digit verification code with you — ask them directly if you know them. Once you have the code, reply here with it.`,
|
|
607
662
|
assistantId,
|
|
608
663
|
},
|
|
609
664
|
mintBearerToken(),
|
|
@@ -645,6 +700,10 @@ export async function enforceIngressAcl(
|
|
|
645
700
|
previousMemberStatus: channelStatusToMemberStatus(
|
|
646
701
|
resolvedMember.channel.status,
|
|
647
702
|
),
|
|
703
|
+
messagePreview: truncate(
|
|
704
|
+
trimmedContent,
|
|
705
|
+
MESSAGE_PREVIEW_MAX_LENGTH,
|
|
706
|
+
),
|
|
648
707
|
});
|
|
649
708
|
guardianNotified = accessResult.notified;
|
|
650
709
|
} catch (err) {
|
|
@@ -657,7 +716,7 @@ export async function enforceIngressAcl(
|
|
|
657
716
|
|
|
658
717
|
if (replyCallbackUrl) {
|
|
659
718
|
const replyText = guardianNotified
|
|
660
|
-
?
|
|
719
|
+
? `Hmm looks like you don't have access to talk to me. I'll let ${resolveGuardianLabel(sourceChannel, canonicalAssistantId)} know you tried talking to me and get back to you.`
|
|
661
720
|
: "Sorry, you haven't been approved to message this assistant.";
|
|
662
721
|
const inactiveReplyPayload: Parameters<
|
|
663
722
|
typeof deliverChannelReply
|
|
@@ -75,8 +75,6 @@ export interface BackgroundProcessingParams {
|
|
|
75
75
|
approvalCopyGenerator?: ApprovalCopyGenerator;
|
|
76
76
|
commandIntent?: Record<string, unknown>;
|
|
77
77
|
sourceLanguageCode?: string;
|
|
78
|
-
/** External message ID (e.g. Slack message ts) used for reaction indicators. */
|
|
79
|
-
externalMessageId?: string;
|
|
80
78
|
/** Chat type from the gateway (e.g. "private", "group", "supergroup"). */
|
|
81
79
|
chatType?: string;
|
|
82
80
|
}
|
|
@@ -106,7 +104,6 @@ export function processChannelMessageInBackground(
|
|
|
106
104
|
approvalCopyGenerator,
|
|
107
105
|
commandIntent,
|
|
108
106
|
sourceLanguageCode,
|
|
109
|
-
externalMessageId,
|
|
110
107
|
chatType,
|
|
111
108
|
} = params;
|
|
112
109
|
|
|
@@ -126,18 +123,18 @@ export function processChannelMessageInBackground(
|
|
|
126
123
|
)
|
|
127
124
|
: undefined;
|
|
128
125
|
|
|
129
|
-
//
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
126
|
+
// Set Slack Assistants API "is thinking..." status indicator
|
|
127
|
+
const clearSlackThinkingStatus = shouldEmitSlackReaction(
|
|
128
|
+
sourceChannel,
|
|
129
|
+
replyCallbackUrl,
|
|
130
|
+
)
|
|
131
|
+
? setSlackThinkingStatus(
|
|
132
|
+
replyCallbackUrl!,
|
|
133
|
+
externalChatId,
|
|
134
|
+
mintBearerToken,
|
|
135
|
+
assistantId,
|
|
136
|
+
)
|
|
137
|
+
: undefined;
|
|
141
138
|
const stopApprovalWatcher = replyCallbackUrl
|
|
142
139
|
? startPendingApprovalPromptWatcher({
|
|
143
140
|
conversationId,
|
|
@@ -230,7 +227,7 @@ export function processChannelMessageInBackground(
|
|
|
230
227
|
deliveryStatus.recordProcessingFailure(eventId, err);
|
|
231
228
|
} finally {
|
|
232
229
|
stopTypingHeartbeat?.();
|
|
233
|
-
|
|
230
|
+
clearSlackThinkingStatus?.();
|
|
234
231
|
stopApprovalWatcher?.();
|
|
235
232
|
stopTcApprovalNotifier?.();
|
|
236
233
|
}
|
|
@@ -295,7 +292,7 @@ export function startTelegramTypingHeartbeat(
|
|
|
295
292
|
}
|
|
296
293
|
|
|
297
294
|
// ---------------------------------------------------------------------------
|
|
298
|
-
// Slack
|
|
295
|
+
// Slack Assistants API thinking status indicator
|
|
299
296
|
// ---------------------------------------------------------------------------
|
|
300
297
|
|
|
301
298
|
export function shouldEmitSlackReaction(
|
|
@@ -310,65 +307,80 @@ export function shouldEmitSlackReaction(
|
|
|
310
307
|
}
|
|
311
308
|
}
|
|
312
309
|
|
|
313
|
-
const
|
|
310
|
+
const SLACK_THINKING_MAX_DURATION_MS = 120_000;
|
|
314
311
|
|
|
315
312
|
/**
|
|
316
|
-
*
|
|
317
|
-
* function that
|
|
313
|
+
* Set the Slack Assistants API "is thinking..." status on the thread and
|
|
314
|
+
* return a cleanup function that clears it. Both operations are fire-and-forget.
|
|
318
315
|
*
|
|
319
|
-
* A safety timer auto-
|
|
320
|
-
* to prevent stuck
|
|
321
|
-
* an active session turn that never completes for this message).
|
|
316
|
+
* A safety timer auto-clears the status after {@link SLACK_THINKING_MAX_DURATION_MS}
|
|
317
|
+
* to prevent a stuck indicator when `processMessage` hangs.
|
|
322
318
|
*/
|
|
323
|
-
export function
|
|
319
|
+
export function setSlackThinkingStatus(
|
|
324
320
|
callbackUrl: string,
|
|
325
321
|
chatId: string,
|
|
326
|
-
messageTs: string,
|
|
327
322
|
mintBearerToken: () => string,
|
|
328
323
|
assistantId?: string,
|
|
329
324
|
): () => void {
|
|
330
|
-
let
|
|
325
|
+
let cleared = false;
|
|
326
|
+
|
|
327
|
+
// Extract the thread timestamp from the callback URL so we can target
|
|
328
|
+
// the correct thread for the Assistants API status.
|
|
329
|
+
const threadTs = extractThreadTsFromCallbackUrl(callbackUrl);
|
|
330
|
+
|
|
331
|
+
// If there's no thread context, we can't set a thread status — bail.
|
|
332
|
+
if (!threadTs) {
|
|
333
|
+
return () => {};
|
|
334
|
+
}
|
|
331
335
|
|
|
332
|
-
// Track the
|
|
333
|
-
// preventing a race where
|
|
334
|
-
const
|
|
336
|
+
// Track the set promise so clear waits for it to settle first,
|
|
337
|
+
// preventing a race where clear arrives at Slack before set.
|
|
338
|
+
const setPromise = deliverChannelReply(
|
|
335
339
|
callbackUrl,
|
|
336
340
|
{
|
|
337
341
|
chatId,
|
|
338
342
|
assistantId,
|
|
339
|
-
|
|
343
|
+
assistantThreadStatus: {
|
|
344
|
+
channel: chatId,
|
|
345
|
+
threadTs,
|
|
346
|
+
status: "is thinking...",
|
|
347
|
+
},
|
|
340
348
|
},
|
|
341
349
|
mintBearerToken(),
|
|
342
350
|
).catch((err) => {
|
|
343
|
-
log.debug({ err, chatId,
|
|
351
|
+
log.debug({ err, chatId, threadTs }, "Failed to set Slack thinking status");
|
|
344
352
|
});
|
|
345
353
|
|
|
346
|
-
const
|
|
347
|
-
if (
|
|
348
|
-
|
|
354
|
+
const clearStatus = () => {
|
|
355
|
+
if (cleared) return;
|
|
356
|
+
cleared = true;
|
|
349
357
|
clearTimeout(safetyTimer);
|
|
350
|
-
void
|
|
358
|
+
void setPromise.then(() =>
|
|
351
359
|
deliverChannelReply(
|
|
352
360
|
callbackUrl,
|
|
353
361
|
{
|
|
354
362
|
chatId,
|
|
355
363
|
assistantId,
|
|
356
|
-
|
|
364
|
+
assistantThreadStatus: {
|
|
365
|
+
channel: chatId,
|
|
366
|
+
threadTs,
|
|
367
|
+
status: "",
|
|
368
|
+
},
|
|
357
369
|
},
|
|
358
370
|
mintBearerToken(),
|
|
359
371
|
).catch((err) => {
|
|
360
372
|
log.debug(
|
|
361
|
-
{ err, chatId,
|
|
362
|
-
"Failed to
|
|
373
|
+
{ err, chatId, threadTs },
|
|
374
|
+
"Failed to clear Slack thinking status",
|
|
363
375
|
);
|
|
364
376
|
}),
|
|
365
377
|
);
|
|
366
378
|
};
|
|
367
379
|
|
|
368
|
-
const safetyTimer = setTimeout(
|
|
380
|
+
const safetyTimer = setTimeout(clearStatus, SLACK_THINKING_MAX_DURATION_MS);
|
|
369
381
|
(safetyTimer as { unref?: () => void }).unref?.();
|
|
370
382
|
|
|
371
|
-
return
|
|
383
|
+
return clearStatus;
|
|
372
384
|
}
|
|
373
385
|
|
|
374
386
|
// ---------------------------------------------------------------------------
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Telegram messages.
|
|
5
|
-
*
|
|
6
|
-
* The payload is stored before the scan so dead-lettered events can be
|
|
7
|
-
* replayed. If the scan detects embedded secrets the stored payload is
|
|
8
|
-
* cleared before the IngressBlockedError propagates, ensuring
|
|
9
|
-
* secret-bearing content is never left on disk.
|
|
2
|
+
* Inbound payload persistence stage: persists the raw inbound payload and
|
|
3
|
+
* records a conversation-seen signal for Telegram messages.
|
|
10
4
|
*
|
|
11
5
|
* Extracted from inbound-message-handler.ts to keep the top-level handler
|
|
12
6
|
* focused on orchestration.
|
|
@@ -15,8 +9,6 @@ import type { ChannelId } from "../../../channels/types.js";
|
|
|
15
9
|
import type { TrustContext } from "../../../daemon/conversation-runtime-assembly.js";
|
|
16
10
|
import { recordConversationSeenSignal } from "../../../memory/conversation-attention-store.js";
|
|
17
11
|
import * as deliveryCrud from "../../../memory/delivery-crud.js";
|
|
18
|
-
import { checkIngressForSecrets } from "../../../security/secret-ingress.js";
|
|
19
|
-
import { IngressBlockedError } from "../../../util/errors.js";
|
|
20
12
|
import { getLogger } from "../../../util/logger.js";
|
|
21
13
|
|
|
22
14
|
const log = getLogger("runtime-http");
|
|
@@ -44,10 +36,7 @@ export interface SecretIngressCheckParams {
|
|
|
44
36
|
}
|
|
45
37
|
|
|
46
38
|
/**
|
|
47
|
-
* Persist the raw payload
|
|
48
|
-
* Telegram seen signal.
|
|
49
|
-
*
|
|
50
|
-
* Throws IngressBlockedError if the content contains secrets.
|
|
39
|
+
* Persist the raw payload and record a Telegram seen signal.
|
|
51
40
|
*/
|
|
52
41
|
export function runSecretIngressCheck(params: SecretIngressCheckParams): void {
|
|
53
42
|
const {
|
|
@@ -68,9 +57,7 @@ export function runSecretIngressCheck(params: SecretIngressCheckParams): void {
|
|
|
68
57
|
canonicalAssistantId,
|
|
69
58
|
} = params;
|
|
70
59
|
|
|
71
|
-
// Persist the raw payload
|
|
72
|
-
// replayed. If the ingress check later detects secrets we clear it
|
|
73
|
-
// before throwing, so secret-bearing content is never left on disk.
|
|
60
|
+
// Persist the raw payload so dead-lettered events can always be replayed.
|
|
74
61
|
deliveryCrud.storePayload(eventId, {
|
|
75
62
|
sourceChannel,
|
|
76
63
|
externalChatId: conversationExternalId,
|
|
@@ -86,22 +73,6 @@ export function runSecretIngressCheck(params: SecretIngressCheckParams): void {
|
|
|
86
73
|
assistantId: canonicalAssistantId,
|
|
87
74
|
});
|
|
88
75
|
|
|
89
|
-
const contentToCheck = content ?? "";
|
|
90
|
-
let ingressCheck: ReturnType<typeof checkIngressForSecrets>;
|
|
91
|
-
try {
|
|
92
|
-
ingressCheck = checkIngressForSecrets(contentToCheck);
|
|
93
|
-
} catch (checkErr) {
|
|
94
|
-
deliveryCrud.clearPayload(eventId);
|
|
95
|
-
throw checkErr;
|
|
96
|
-
}
|
|
97
|
-
if (ingressCheck.blocked) {
|
|
98
|
-
deliveryCrud.clearPayload(eventId);
|
|
99
|
-
throw new IngressBlockedError(
|
|
100
|
-
ingressCheck.userNotice!,
|
|
101
|
-
ingressCheck.detectedTypes,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
76
|
// Record inferred seen signal for non-duplicate Telegram inbound messages
|
|
106
77
|
if (sourceChannel === "telegram") {
|
|
107
78
|
try {
|
|
@@ -24,7 +24,7 @@ mock.module("../../../config/assistant-feature-flags.js", () => ({
|
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
26
|
mock.module("../../../config/loader.js", () => ({
|
|
27
|
-
getConfig: () => ({
|
|
27
|
+
getConfig: () => ({}),
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
30
|
mock.module("../../../memory/attachments-store.js", () => ({
|
|
@@ -91,10 +91,19 @@ export async function handleGetTwilioConfig(): Promise<Response> {
|
|
|
91
91
|
export async function handleSetTwilioCredentials(
|
|
92
92
|
req: Request,
|
|
93
93
|
): Promise<Response> {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
94
|
+
let body: { accountSid?: string; authToken?: string };
|
|
95
|
+
try {
|
|
96
|
+
body = (await req.json()) as typeof body;
|
|
97
|
+
} catch {
|
|
98
|
+
return Response.json(
|
|
99
|
+
{
|
|
100
|
+
success: false,
|
|
101
|
+
hasCredentials: await hasTwilioCredentials(),
|
|
102
|
+
error: "Invalid JSON in request body",
|
|
103
|
+
},
|
|
104
|
+
{ status: 400 },
|
|
105
|
+
);
|
|
106
|
+
}
|
|
98
107
|
|
|
99
108
|
if (!body.accountSid || !body.authToken) {
|
|
100
109
|
return Response.json(
|
|
@@ -261,10 +270,19 @@ export async function handleProvisionTwilioNumber(
|
|
|
261
270
|
});
|
|
262
271
|
}
|
|
263
272
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
273
|
+
let body: { country?: string; areaCode?: string };
|
|
274
|
+
try {
|
|
275
|
+
body = (await req.json()) as typeof body;
|
|
276
|
+
} catch {
|
|
277
|
+
return Response.json(
|
|
278
|
+
{
|
|
279
|
+
success: false,
|
|
280
|
+
hasCredentials: await hasTwilioCredentials(),
|
|
281
|
+
error: "Invalid JSON in request body",
|
|
282
|
+
},
|
|
283
|
+
{ status: 400 },
|
|
284
|
+
);
|
|
285
|
+
}
|
|
268
286
|
const { accountSid, authToken } = await getTwilioCredentials();
|
|
269
287
|
const country = body.country ?? "US";
|
|
270
288
|
|
|
@@ -318,7 +336,19 @@ export async function handleProvisionTwilioNumber(
|
|
|
318
336
|
export async function handleAssignTwilioNumber(
|
|
319
337
|
req: Request,
|
|
320
338
|
): Promise<Response> {
|
|
321
|
-
|
|
339
|
+
let body: { phoneNumber?: string };
|
|
340
|
+
try {
|
|
341
|
+
body = (await req.json()) as typeof body;
|
|
342
|
+
} catch {
|
|
343
|
+
return Response.json(
|
|
344
|
+
{
|
|
345
|
+
success: false,
|
|
346
|
+
hasCredentials: await hasTwilioCredentials(),
|
|
347
|
+
error: "Invalid JSON in request body",
|
|
348
|
+
},
|
|
349
|
+
{ status: 400 },
|
|
350
|
+
);
|
|
351
|
+
}
|
|
322
352
|
|
|
323
353
|
if (!body.phoneNumber) {
|
|
324
354
|
return Response.json(
|
|
@@ -375,7 +405,19 @@ export async function handleReleaseTwilioNumber(
|
|
|
375
405
|
});
|
|
376
406
|
}
|
|
377
407
|
|
|
378
|
-
|
|
408
|
+
let body: { phoneNumber?: string };
|
|
409
|
+
try {
|
|
410
|
+
body = (await req.json()) as typeof body;
|
|
411
|
+
} catch {
|
|
412
|
+
return Response.json(
|
|
413
|
+
{
|
|
414
|
+
success: false,
|
|
415
|
+
hasCredentials: await hasTwilioCredentials(),
|
|
416
|
+
error: "Invalid JSON in request body",
|
|
417
|
+
},
|
|
418
|
+
{ status: 400 },
|
|
419
|
+
);
|
|
420
|
+
}
|
|
379
421
|
const raw = loadRawConfig();
|
|
380
422
|
const twilio = (raw?.twilio ?? {}) as Record<string, unknown>;
|
|
381
423
|
const phoneNumber = body.phoneNumber || (twilio.phoneNumber as string) || "";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handlers for Vercel integration config endpoints.
|
|
3
|
+
*
|
|
4
|
+
* GET /v1/integrations/vercel/config — check if a Vercel API token is stored
|
|
5
|
+
* POST /v1/integrations/vercel/config — set or delete token (dispatched via action field)
|
|
6
|
+
* DELETE /v1/integrations/vercel/config — delete the stored Vercel API token
|
|
7
|
+
*
|
|
8
|
+
* The Swift client sends all mutations as POST with an `action` field
|
|
9
|
+
* ("set" or "delete") rather than using HTTP verbs directly.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
deleteVercelConfig,
|
|
14
|
+
getVercelConfig,
|
|
15
|
+
setVercelConfig,
|
|
16
|
+
} from "../../../daemon/handlers/config-vercel.js";
|
|
17
|
+
import type { RouteDefinition } from "../../http-router.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* GET /v1/integrations/vercel/config
|
|
21
|
+
*/
|
|
22
|
+
export async function handleGetVercelConfig(): Promise<Response> {
|
|
23
|
+
const result = await getVercelConfig();
|
|
24
|
+
return Response.json(result);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* POST /v1/integrations/vercel/config
|
|
29
|
+
*
|
|
30
|
+
* Body: { action: "set" | "delete"; apiToken?: string }
|
|
31
|
+
*
|
|
32
|
+
* The Swift client uses POST for both set and delete operations,
|
|
33
|
+
* distinguished by the `action` field.
|
|
34
|
+
*/
|
|
35
|
+
export async function handlePostVercelConfig(req: Request): Promise<Response> {
|
|
36
|
+
const body = (await req.json()) as {
|
|
37
|
+
action?: "get" | "set" | "delete";
|
|
38
|
+
apiToken?: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
switch (body.action) {
|
|
42
|
+
case "delete": {
|
|
43
|
+
const result = await deleteVercelConfig();
|
|
44
|
+
return Response.json(result);
|
|
45
|
+
}
|
|
46
|
+
case "get": {
|
|
47
|
+
const result = await getVercelConfig();
|
|
48
|
+
return Response.json(result);
|
|
49
|
+
}
|
|
50
|
+
case "set":
|
|
51
|
+
default: {
|
|
52
|
+
const result = await setVercelConfig(body.apiToken);
|
|
53
|
+
const status = result.success ? 200 : 400;
|
|
54
|
+
return Response.json(result, { status });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* DELETE /v1/integrations/vercel/config
|
|
61
|
+
*/
|
|
62
|
+
export async function handleDeleteVercelConfig(): Promise<Response> {
|
|
63
|
+
const result = await deleteVercelConfig();
|
|
64
|
+
return Response.json(result);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Route definitions
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
export function vercelRouteDefinitions(): RouteDefinition[] {
|
|
72
|
+
return [
|
|
73
|
+
{
|
|
74
|
+
endpoint: "integrations/vercel/config",
|
|
75
|
+
method: "GET",
|
|
76
|
+
handler: () => handleGetVercelConfig(),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
endpoint: "integrations/vercel/config",
|
|
80
|
+
method: "POST",
|
|
81
|
+
handler: async ({ req }) => handlePostVercelConfig(req),
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
endpoint: "integrations/vercel/config",
|
|
85
|
+
method: "DELETE",
|
|
86
|
+
handler: async () => handleDeleteVercelConfig(),
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
}
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
getWorkspaceConfigPath,
|
|
38
38
|
getWorkspaceDir,
|
|
39
39
|
} from "../../util/platform.js";
|
|
40
|
+
import { APP_VERSION, COMMIT_SHA } from "../../version.js";
|
|
40
41
|
import { httpError } from "../http-errors.js";
|
|
41
42
|
import type { RouteDefinition } from "../http-router.js";
|
|
42
43
|
|
|
@@ -264,12 +265,16 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
|
|
|
264
265
|
? {
|
|
265
266
|
type: "conversation-export" as const,
|
|
266
267
|
conversationId,
|
|
268
|
+
assistantVersion: APP_VERSION,
|
|
269
|
+
commitSha: COMMIT_SHA,
|
|
267
270
|
...(startTime !== undefined ? { startTime } : {}),
|
|
268
271
|
...(endTime !== undefined ? { endTime } : {}),
|
|
269
272
|
exportedAt: new Date().toISOString(),
|
|
270
273
|
}
|
|
271
274
|
: {
|
|
272
275
|
type: "global-export" as const,
|
|
276
|
+
assistantVersion: APP_VERSION,
|
|
277
|
+
commitSha: COMMIT_SHA,
|
|
273
278
|
exportedAt: new Date().toISOString(),
|
|
274
279
|
};
|
|
275
280
|
writeFileSync(
|
|
@@ -754,7 +754,7 @@ describe("Memory Item Routes", () => {
|
|
|
754
754
|
expect(res.status).toBe(400);
|
|
755
755
|
});
|
|
756
756
|
|
|
757
|
-
test("
|
|
757
|
+
test("preserves long subject and statement without truncation", async () => {
|
|
758
758
|
const longSubject = "a".repeat(200);
|
|
759
759
|
const longStatement = "b".repeat(1000);
|
|
760
760
|
const ctx = makeJsonCtx("memory-items", "POST", {
|
|
@@ -767,8 +767,8 @@ describe("Memory Item Routes", () => {
|
|
|
767
767
|
const body = (await res.json()) as {
|
|
768
768
|
item: { subject: string; statement: string };
|
|
769
769
|
};
|
|
770
|
-
expect(body.item.subject
|
|
771
|
-
expect(body.item.statement
|
|
770
|
+
expect(body.item.subject).toBe(longSubject);
|
|
771
|
+
expect(body.item.statement).toBe(longStatement);
|
|
772
772
|
});
|
|
773
773
|
|
|
774
774
|
test("enqueues embed job on create", async () => {
|