@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
|
@@ -54,6 +54,7 @@ mock.module("node:fs", () => ({
|
|
|
54
54
|
// Import after mocking
|
|
55
55
|
import {
|
|
56
56
|
loadCheckpoints,
|
|
57
|
+
rollbackWorkspaceMigrations,
|
|
57
58
|
runWorkspaceMigrations,
|
|
58
59
|
} from "../workspace/migrations/runner.js";
|
|
59
60
|
|
|
@@ -68,6 +69,7 @@ function makeMigration(id: string): WorkspaceMigration {
|
|
|
68
69
|
id,
|
|
69
70
|
description: `Migration ${id}`,
|
|
70
71
|
run: mock(() => {}),
|
|
72
|
+
down: mock(() => {}),
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -244,6 +246,7 @@ describe("runWorkspaceMigrations", () => {
|
|
|
244
246
|
// Simulate async work
|
|
245
247
|
await Promise.resolve();
|
|
246
248
|
}),
|
|
249
|
+
down: mock(() => {}),
|
|
247
250
|
};
|
|
248
251
|
|
|
249
252
|
await runWorkspaceMigrations(WORKSPACE_DIR, [asyncMigration]);
|
|
@@ -291,3 +294,114 @@ describe("runWorkspaceMigrations", () => {
|
|
|
291
294
|
);
|
|
292
295
|
});
|
|
293
296
|
});
|
|
297
|
+
|
|
298
|
+
describe("rollbackWorkspaceMigrations", () => {
|
|
299
|
+
beforeEach(() => {
|
|
300
|
+
mockCheckpointContents = null;
|
|
301
|
+
readTextFileSyncFn.mockClear();
|
|
302
|
+
ensureDirFn.mockClear();
|
|
303
|
+
writeFileSyncFn.mockClear();
|
|
304
|
+
renameSyncFn.mockClear();
|
|
305
|
+
logWarnFn.mockClear();
|
|
306
|
+
logInfoFn.mockClear();
|
|
307
|
+
logErrorFn.mockClear();
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test("rolls back migrations in reverse order", async () => {
|
|
311
|
+
const m1 = makeMigration("001");
|
|
312
|
+
const m2 = makeMigration("002");
|
|
313
|
+
const m3 = makeMigration("003");
|
|
314
|
+
|
|
315
|
+
// All three migrations are marked as completed in checkpoints
|
|
316
|
+
mockCheckpointContents = JSON.stringify({
|
|
317
|
+
applied: {
|
|
318
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "completed" },
|
|
319
|
+
"002": { appliedAt: "2025-01-02T00:00:00.000Z", status: "completed" },
|
|
320
|
+
"003": { appliedAt: "2025-01-03T00:00:00.000Z", status: "completed" },
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const callOrder: string[] = [];
|
|
325
|
+
(m2.down as ReturnType<typeof mock>).mockImplementation(() => {
|
|
326
|
+
callOrder.push("002");
|
|
327
|
+
});
|
|
328
|
+
(m3.down as ReturnType<typeof mock>).mockImplementation(() => {
|
|
329
|
+
callOrder.push("003");
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Roll back to m1 — should reverse m3 then m2, but not m1
|
|
333
|
+
await rollbackWorkspaceMigrations(WORKSPACE_DIR, [m1, m2, m3], "001");
|
|
334
|
+
|
|
335
|
+
expect(m3.down).toHaveBeenCalledTimes(1);
|
|
336
|
+
expect(m2.down).toHaveBeenCalledTimes(1);
|
|
337
|
+
expect(m1.down).not.toHaveBeenCalled();
|
|
338
|
+
expect(callOrder).toEqual(["003", "002"]);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test("handles crash during rollback (rolling_back status)", async () => {
|
|
342
|
+
const m1 = makeMigration("001");
|
|
343
|
+
|
|
344
|
+
// Simulate a crash during a previous rollback — m1 is left in rolling_back state
|
|
345
|
+
mockCheckpointContents = JSON.stringify({
|
|
346
|
+
applied: {
|
|
347
|
+
"001": {
|
|
348
|
+
appliedAt: "2025-01-01T00:00:00.000Z",
|
|
349
|
+
status: "rolling_back",
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// runWorkspaceMigrations should clear the rolling_back status and re-run forward
|
|
355
|
+
await runWorkspaceMigrations(WORKSPACE_DIR, [m1]);
|
|
356
|
+
|
|
357
|
+
// The runner treats "rolling_back" like "started" — it clears the entry and re-runs
|
|
358
|
+
expect(m1.run).toHaveBeenCalledTimes(1);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
test("removes checkpoints for rolled-back migrations", async () => {
|
|
362
|
+
const m1 = makeMigration("001");
|
|
363
|
+
const m2 = makeMigration("002");
|
|
364
|
+
const m3 = makeMigration("003");
|
|
365
|
+
|
|
366
|
+
mockCheckpointContents = JSON.stringify({
|
|
367
|
+
applied: {
|
|
368
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "completed" },
|
|
369
|
+
"002": { appliedAt: "2025-01-02T00:00:00.000Z", status: "completed" },
|
|
370
|
+
"003": { appliedAt: "2025-01-03T00:00:00.000Z", status: "completed" },
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await rollbackWorkspaceMigrations(WORKSPACE_DIR, [m1, m2, m3], "001");
|
|
375
|
+
|
|
376
|
+
// The last checkpoint write should only contain m1 (002 and 003 were rolled back)
|
|
377
|
+
const lastWriteCall = writeFileSyncFn.mock.calls.at(-1) as unknown[];
|
|
378
|
+
const finalCheckpoint = JSON.parse(lastWriteCall[1] as string);
|
|
379
|
+
expect(finalCheckpoint.applied["001"]).toBeDefined();
|
|
380
|
+
expect(finalCheckpoint.applied["002"]).toBeUndefined();
|
|
381
|
+
expect(finalCheckpoint.applied["003"]).toBeUndefined();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("no-op when already at target", async () => {
|
|
385
|
+
const m1 = makeMigration("001");
|
|
386
|
+
const m2 = makeMigration("002");
|
|
387
|
+
const m3 = makeMigration("003");
|
|
388
|
+
|
|
389
|
+
mockCheckpointContents = JSON.stringify({
|
|
390
|
+
applied: {
|
|
391
|
+
"001": { appliedAt: "2025-01-01T00:00:00.000Z", status: "completed" },
|
|
392
|
+
"002": { appliedAt: "2025-01-02T00:00:00.000Z", status: "completed" },
|
|
393
|
+
"003": { appliedAt: "2025-01-03T00:00:00.000Z", status: "completed" },
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Target is the last migration — nothing to roll back
|
|
398
|
+
await rollbackWorkspaceMigrations(WORKSPACE_DIR, [m1, m2, m3], "003");
|
|
399
|
+
|
|
400
|
+
expect(m1.down).not.toHaveBeenCalled();
|
|
401
|
+
expect(m2.down).not.toHaveBeenCalled();
|
|
402
|
+
expect(m3.down).not.toHaveBeenCalled();
|
|
403
|
+
|
|
404
|
+
// No checkpoint writes should have occurred (no rollback happened)
|
|
405
|
+
expect(writeFileSyncFn).not.toHaveBeenCalled();
|
|
406
|
+
});
|
|
407
|
+
});
|
package/src/acp/agent-process.ts
CHANGED
|
@@ -52,7 +52,7 @@ export class AcpAgentProcess {
|
|
|
52
52
|
|
|
53
53
|
this.proc = spawn(this.config.command, this.config.args, {
|
|
54
54
|
cwd,
|
|
55
|
-
stdio: ["pipe", "pipe", "
|
|
55
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
56
56
|
env: { ...process.env, ...this.config.env },
|
|
57
57
|
});
|
|
58
58
|
|
|
@@ -68,6 +68,14 @@ export class AcpAgentProcess {
|
|
|
68
68
|
stream,
|
|
69
69
|
);
|
|
70
70
|
|
|
71
|
+
// Capture stderr so agent crash details appear in logs
|
|
72
|
+
this.proc.stderr?.on("data", (chunk: Buffer) => {
|
|
73
|
+
const text = chunk.toString().trim();
|
|
74
|
+
if (text) {
|
|
75
|
+
log.error({ agentId: this.agentId, stderr: text }, "ACP agent stderr");
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
71
79
|
// Handle process exit
|
|
72
80
|
this.proc.on("exit", (code) => {
|
|
73
81
|
this.handleProcessExit(code);
|
package/src/agent/loop.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface AgentLoopConfig {
|
|
|
23
23
|
maxTokens: number;
|
|
24
24
|
maxInputTokens?: number; // context window size for tool result truncation
|
|
25
25
|
thinking?: { enabled: boolean };
|
|
26
|
-
effort: "low" | "medium" | "high";
|
|
26
|
+
effort: "low" | "medium" | "high" | "max";
|
|
27
27
|
toolChoice?:
|
|
28
28
|
| { type: "auto" }
|
|
29
29
|
| { type: "any" }
|
|
@@ -40,6 +40,22 @@ const log = getLogger("guardian-request-resolvers");
|
|
|
40
40
|
// Helpers
|
|
41
41
|
// ---------------------------------------------------------------------------
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Determines whether a Slack delivery should use ephemeral mode.
|
|
45
|
+
*
|
|
46
|
+
* Ephemeral messages (`chat.postEphemeral`) require a real channel ID
|
|
47
|
+
* (starts with `C` for public/private channels, or `D` for DM conversations).
|
|
48
|
+
* When the chat ID is a user ID (starts with `U`), `chat.postEphemeral` fails
|
|
49
|
+
* with `channel_not_found`. In that case the message is already going to a DM
|
|
50
|
+
* opened by `chat.postMessage`, so ephemeral isn't needed.
|
|
51
|
+
*
|
|
52
|
+
* Returns `true` only when the source channel is Slack AND the chatId is a
|
|
53
|
+
* shared channel (starts with `C`), meaning other users could see the message.
|
|
54
|
+
*/
|
|
55
|
+
function shouldUseEphemeral(sourceChannel: string, chatId: string): boolean {
|
|
56
|
+
return sourceChannel === "slack" && chatId.startsWith("C");
|
|
57
|
+
}
|
|
58
|
+
|
|
43
59
|
// ---------------------------------------------------------------------------
|
|
44
60
|
// Types
|
|
45
61
|
// ---------------------------------------------------------------------------
|
|
@@ -372,13 +388,22 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
372
388
|
// Deliver denial notification and lifecycle signals when channel context is available
|
|
373
389
|
if (channelDeliveryContext) {
|
|
374
390
|
try {
|
|
391
|
+
const denialPayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
392
|
+
chatId: requesterChatId,
|
|
393
|
+
text: "Your access request has been denied.",
|
|
394
|
+
assistantId,
|
|
395
|
+
};
|
|
396
|
+
// On Slack shared channels, deliver as ephemeral so only the requester sees the denial
|
|
397
|
+
if (
|
|
398
|
+
shouldUseEphemeral(channel, requesterChatId) &&
|
|
399
|
+
requesterExternalUserId
|
|
400
|
+
) {
|
|
401
|
+
denialPayload.ephemeral = true;
|
|
402
|
+
denialPayload.user = requesterExternalUserId;
|
|
403
|
+
}
|
|
375
404
|
await deliverChannelReply(
|
|
376
405
|
channelDeliveryContext.replyCallbackUrl,
|
|
377
|
-
|
|
378
|
-
chatId: requesterChatId,
|
|
379
|
-
text: "Your access request has been denied by the guardian.",
|
|
380
|
-
assistantId,
|
|
381
|
-
},
|
|
406
|
+
denialPayload,
|
|
382
407
|
channelDeliveryContext.bearerToken,
|
|
383
408
|
);
|
|
384
409
|
} catch (err) {
|
|
@@ -435,7 +460,7 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
435
460
|
desktopDeliverUrl,
|
|
436
461
|
{
|
|
437
462
|
chatId: targetChatId,
|
|
438
|
-
text: "Your access request has been denied
|
|
463
|
+
text: "Your access request has been denied.",
|
|
439
464
|
assistantId,
|
|
440
465
|
},
|
|
441
466
|
desktopBearerToken,
|
|
@@ -520,18 +545,28 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
520
545
|
let codeDelivered = true;
|
|
521
546
|
|
|
522
547
|
// Deliver verification code to guardian
|
|
548
|
+
const codeText =
|
|
549
|
+
`You approved access for ${requesterExternalUserId}. ` +
|
|
550
|
+
`Give them this verification code: \`${session.secret}\`. ` +
|
|
551
|
+
`The code expires in 10 minutes.`;
|
|
523
552
|
try {
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
553
|
+
const codePayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
554
|
+
chatId: channelDeliveryContext.guardianChatId,
|
|
555
|
+
text: codeText,
|
|
556
|
+
assistantId,
|
|
557
|
+
};
|
|
558
|
+
// On Slack shared channels, deliver the verification code as ephemeral
|
|
559
|
+
// so only the guardian sees the secret — not all channel members.
|
|
560
|
+
if (
|
|
561
|
+
shouldUseEphemeral(channel, channelDeliveryContext.guardianChatId) &&
|
|
562
|
+
ctx.actor.actorExternalUserId
|
|
563
|
+
) {
|
|
564
|
+
codePayload.ephemeral = true;
|
|
565
|
+
codePayload.user = ctx.actor.actorExternalUserId;
|
|
566
|
+
}
|
|
528
567
|
await deliverChannelReply(
|
|
529
568
|
channelDeliveryContext.replyCallbackUrl,
|
|
530
|
-
|
|
531
|
-
chatId: channelDeliveryContext.guardianChatId,
|
|
532
|
-
text: codeText,
|
|
533
|
-
assistantId,
|
|
534
|
-
},
|
|
569
|
+
codePayload,
|
|
535
570
|
channelDeliveryContext.bearerToken,
|
|
536
571
|
);
|
|
537
572
|
} catch (err) {
|
|
@@ -542,20 +577,85 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
542
577
|
codeDelivered = false;
|
|
543
578
|
}
|
|
544
579
|
|
|
545
|
-
//
|
|
546
|
-
|
|
580
|
+
// If the guardian approved in a shared channel (not a DM), also send
|
|
581
|
+
// them a DM with the verification code for better privacy and
|
|
582
|
+
// discoverability. On Slack, posting to a user ID opens a DM.
|
|
583
|
+
const guardianUserId = ctx.actor.actorExternalUserId;
|
|
584
|
+
if (
|
|
585
|
+
codeDelivered &&
|
|
586
|
+
channel === "slack" &&
|
|
587
|
+
guardianUserId &&
|
|
588
|
+
!channelDeliveryContext.guardianChatId.startsWith("D")
|
|
589
|
+
) {
|
|
590
|
+
// Strip threadTs from the callback URL — it belongs to the shared
|
|
591
|
+
// channel thread and would cause thread_not_found errors in the DM.
|
|
592
|
+
let dmCallbackUrl = channelDeliveryContext.replyCallbackUrl;
|
|
593
|
+
try {
|
|
594
|
+
const url = new URL(channelDeliveryContext.replyCallbackUrl);
|
|
595
|
+
url.searchParams.delete("threadTs");
|
|
596
|
+
dmCallbackUrl = url.toString();
|
|
597
|
+
} catch {
|
|
598
|
+
// Malformed URL — use as-is
|
|
599
|
+
}
|
|
600
|
+
|
|
547
601
|
try {
|
|
548
602
|
await deliverChannelReply(
|
|
549
|
-
|
|
603
|
+
dmCallbackUrl,
|
|
550
604
|
{
|
|
551
|
-
chatId:
|
|
552
|
-
text:
|
|
553
|
-
"Your access request has been approved! " +
|
|
554
|
-
"Please enter the 6-digit verification code you receive from the guardian.",
|
|
605
|
+
chatId: guardianUserId,
|
|
606
|
+
text: codeText,
|
|
555
607
|
assistantId,
|
|
556
608
|
},
|
|
557
609
|
channelDeliveryContext.bearerToken,
|
|
558
610
|
);
|
|
611
|
+
} catch (err) {
|
|
612
|
+
// Best-effort: the code was already delivered in the shared channel
|
|
613
|
+
log.warn(
|
|
614
|
+
{ err, guardianUserId },
|
|
615
|
+
"Failed to send guardian DM confirmation with verification code",
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// Notify the requester. For Slack, route to DM via the user ID and
|
|
621
|
+
// strip threadTs (which belongs to the guardian's channel thread).
|
|
622
|
+
const requesterTargetChatId =
|
|
623
|
+
channel === "slack" && requesterExternalUserId
|
|
624
|
+
? requesterExternalUserId
|
|
625
|
+
: requesterChatId;
|
|
626
|
+
let requesterCallbackUrl = channelDeliveryContext.replyCallbackUrl;
|
|
627
|
+
if (channel === "slack" && requesterExternalUserId) {
|
|
628
|
+
try {
|
|
629
|
+
const url = new URL(channelDeliveryContext.replyCallbackUrl);
|
|
630
|
+
url.searchParams.delete("threadTs");
|
|
631
|
+
requesterCallbackUrl = url.toString();
|
|
632
|
+
} catch {
|
|
633
|
+
// Malformed URL — use as-is
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (codeDelivered) {
|
|
638
|
+
try {
|
|
639
|
+
const approvalPayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
640
|
+
chatId: requesterTargetChatId,
|
|
641
|
+
text:
|
|
642
|
+
"Your access request has been approved! " +
|
|
643
|
+
"Please enter the 6-digit verification code you receive from the guardian.",
|
|
644
|
+
assistantId,
|
|
645
|
+
};
|
|
646
|
+
// On Slack shared channels, deliver as ephemeral so only the requester sees
|
|
647
|
+
if (
|
|
648
|
+
shouldUseEphemeral(channel, requesterChatId) &&
|
|
649
|
+
requesterExternalUserId
|
|
650
|
+
) {
|
|
651
|
+
approvalPayload.ephemeral = true;
|
|
652
|
+
approvalPayload.user = requesterExternalUserId;
|
|
653
|
+
}
|
|
654
|
+
await deliverChannelReply(
|
|
655
|
+
requesterCallbackUrl,
|
|
656
|
+
approvalPayload,
|
|
657
|
+
channelDeliveryContext.bearerToken,
|
|
658
|
+
);
|
|
559
659
|
requesterNotified = true;
|
|
560
660
|
} catch (err) {
|
|
561
661
|
log.error(
|
|
@@ -565,15 +665,23 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
565
665
|
}
|
|
566
666
|
} else {
|
|
567
667
|
try {
|
|
668
|
+
const failurePayload: Parameters<typeof deliverChannelReply>[1] = {
|
|
669
|
+
chatId: requesterTargetChatId,
|
|
670
|
+
text:
|
|
671
|
+
"Your access request was approved, but we were unable to " +
|
|
672
|
+
"deliver the verification code. Please try again later.",
|
|
673
|
+
assistantId,
|
|
674
|
+
};
|
|
675
|
+
if (
|
|
676
|
+
shouldUseEphemeral(channel, requesterChatId) &&
|
|
677
|
+
requesterExternalUserId
|
|
678
|
+
) {
|
|
679
|
+
failurePayload.ephemeral = true;
|
|
680
|
+
failurePayload.user = requesterExternalUserId;
|
|
681
|
+
}
|
|
568
682
|
await deliverChannelReply(
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
chatId: requesterChatId,
|
|
572
|
-
text:
|
|
573
|
-
"Your access request was approved, but we were unable to " +
|
|
574
|
-
"deliver the verification code. Please try again later.",
|
|
575
|
-
assistantId,
|
|
576
|
-
},
|
|
683
|
+
requesterCallbackUrl,
|
|
684
|
+
failurePayload,
|
|
577
685
|
channelDeliveryContext.bearerToken,
|
|
578
686
|
);
|
|
579
687
|
} catch (err) {
|
|
@@ -635,8 +743,8 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
635
743
|
}
|
|
636
744
|
|
|
637
745
|
const verificationReplyText = requesterNotified
|
|
638
|
-
? `Access approved for ${requesterLabel}. Give them this verification code:
|
|
639
|
-
: `Access approved for ${requesterLabel}. Give them this verification code:
|
|
746
|
+
? `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes.`
|
|
747
|
+
: `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes. I could not notify them automatically, so please tell them to send the code manually.`;
|
|
640
748
|
|
|
641
749
|
return {
|
|
642
750
|
ok: true,
|
|
@@ -686,13 +794,22 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
|
|
|
686
794
|
|
|
687
795
|
if (channelDeliveryContext && requesterChatId) {
|
|
688
796
|
try {
|
|
689
|
-
|
|
690
|
-
channelDeliveryContext.replyCallbackUrl,
|
|
797
|
+
const grantDenialPayload: Parameters<typeof deliverChannelReply>[1] =
|
|
691
798
|
{
|
|
692
799
|
chatId: requesterChatId,
|
|
693
800
|
text: `Your request to use "${request.toolName}" has been denied by the guardian.`,
|
|
694
801
|
assistantId,
|
|
695
|
-
}
|
|
802
|
+
};
|
|
803
|
+
if (
|
|
804
|
+
shouldUseEphemeral(request.sourceChannel ?? "", requesterChatId) &&
|
|
805
|
+
request.requesterExternalUserId
|
|
806
|
+
) {
|
|
807
|
+
grantDenialPayload.ephemeral = true;
|
|
808
|
+
grantDenialPayload.user = request.requesterExternalUserId;
|
|
809
|
+
}
|
|
810
|
+
await deliverChannelReply(
|
|
811
|
+
channelDeliveryContext.replyCallbackUrl,
|
|
812
|
+
grantDenialPayload,
|
|
696
813
|
channelDeliveryContext.bearerToken,
|
|
697
814
|
);
|
|
698
815
|
} catch (err) {
|
|
@@ -775,13 +892,22 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
|
|
|
775
892
|
);
|
|
776
893
|
} else if (channelDeliveryContext && requesterChatId) {
|
|
777
894
|
try {
|
|
778
|
-
|
|
779
|
-
channelDeliveryContext.replyCallbackUrl,
|
|
895
|
+
const grantApprovalPayload: Parameters<typeof deliverChannelReply>[1] =
|
|
780
896
|
{
|
|
781
897
|
chatId: requesterChatId,
|
|
782
898
|
text: `Your request to use "${request.toolName}" has been approved. Please retry your request.`,
|
|
783
899
|
assistantId,
|
|
784
|
-
}
|
|
900
|
+
};
|
|
901
|
+
if (
|
|
902
|
+
shouldUseEphemeral(request.sourceChannel ?? "", requesterChatId) &&
|
|
903
|
+
request.requesterExternalUserId
|
|
904
|
+
) {
|
|
905
|
+
grantApprovalPayload.ephemeral = true;
|
|
906
|
+
grantApprovalPayload.user = request.requesterExternalUserId;
|
|
907
|
+
}
|
|
908
|
+
await deliverChannelReply(
|
|
909
|
+
channelDeliveryContext.replyCallbackUrl,
|
|
910
|
+
grantApprovalPayload,
|
|
785
911
|
channelDeliveryContext.bearerToken,
|
|
786
912
|
);
|
|
787
913
|
} catch (err) {
|