@vellumai/assistant 0.9.0 → 0.10.0-staging.2
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/ARCHITECTURE.md +18 -34
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +976 -63
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/skill-execute-input.test.ts +51 -1
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +49 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +197 -4
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +105 -17
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +27 -14
- package/src/daemon/conversation.ts +66 -14
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +181 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +52 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +202 -3
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +2 -3
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +33 -0
- package/src/tools/subagent/spawn.ts +61 -12
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +9 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -58,6 +58,7 @@ import { resolveEffectiveContextWindow } from "../config/llm-context-resolution.
|
|
|
58
58
|
import { getConfig } from "../config/loader.js";
|
|
59
59
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
60
60
|
import type { Conversation } from "../daemon/conversation.js";
|
|
61
|
+
import { recordUsage } from "../daemon/conversation-usage.js";
|
|
61
62
|
import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
|
|
62
63
|
import {
|
|
63
64
|
classifyDiskPressureTurnPolicy,
|
|
@@ -195,6 +196,14 @@ export interface WakeOptions {
|
|
|
195
196
|
* retrospectives whose conversation title already says "(Retrospective)").
|
|
196
197
|
*/
|
|
197
198
|
suppressWakeSurface?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Run the wake's turn as non-interactive (no client present). Threads to the
|
|
201
|
+
* agent loop's `isNonInteractive`, which gates the `<non_interactive_context>`
|
|
202
|
+
* and `<background_turn>` injectors. Fork-based memory retrospectives set this
|
|
203
|
+
* to the source conversation's background-turn state so the fork reproduces
|
|
204
|
+
* the source's injected turn block (prompt-cache prefix parity). Default false.
|
|
205
|
+
*/
|
|
206
|
+
isNonInteractive?: boolean;
|
|
198
207
|
/**
|
|
199
208
|
* Optional exact tool allowlist for this wake. Used by internal maintenance
|
|
200
209
|
* jobs that need the assistant's judgment but must not execute arbitrary
|
|
@@ -587,6 +596,7 @@ export async function wakeAgentForOpportunity(
|
|
|
587
596
|
opts.forceOverrideProfile ??
|
|
588
597
|
getConversationOverrideProfile(conversationId);
|
|
589
598
|
const callSite = opts.callSite ?? "mainAgent";
|
|
599
|
+
const isNonInteractive = opts.isNonInteractive ?? false;
|
|
590
600
|
const config = getConfig();
|
|
591
601
|
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
592
602
|
llm: config.llm,
|
|
@@ -784,6 +794,47 @@ export async function wakeAgentForOpportunity(
|
|
|
784
794
|
if (event.type === "compaction_completed") {
|
|
785
795
|
recordCompactionEndBestEffort(conversationId, event);
|
|
786
796
|
}
|
|
797
|
+
// Normal user turns record usage via the `dispatchAgentEvent` event handler)
|
|
798
|
+
// Wakes run their own onEvent and bypass it, so record here.
|
|
799
|
+
if (event.type === "usage") {
|
|
800
|
+
try {
|
|
801
|
+
recordUsage(
|
|
802
|
+
{
|
|
803
|
+
conversationId,
|
|
804
|
+
providerName: event.actualProvider ?? conversation.provider.name,
|
|
805
|
+
usageStats: conversation.usageStats,
|
|
806
|
+
},
|
|
807
|
+
event.inputTokens,
|
|
808
|
+
event.outputTokens,
|
|
809
|
+
event.model,
|
|
810
|
+
() => {},
|
|
811
|
+
"main_agent",
|
|
812
|
+
`wake:${source}`,
|
|
813
|
+
event.cacheCreationInputTokens ?? 0,
|
|
814
|
+
event.cacheReadInputTokens ?? 0,
|
|
815
|
+
event.rawResponse,
|
|
816
|
+
1,
|
|
817
|
+
undefined,
|
|
818
|
+
// Mirror the profile state the request actually ran under:
|
|
819
|
+
// `forceOverrideProfile` floats the override above the call-site
|
|
820
|
+
// profile (fork retrospectives with matchConversationProfile), and
|
|
821
|
+
// the conversation-id seed resolves the same mix arm the dispatch
|
|
822
|
+
// path chose. Without these, attribution credits the call-site
|
|
823
|
+
// profile/arm instead of the one that ran.
|
|
824
|
+
{
|
|
825
|
+
callSite,
|
|
826
|
+
overrideProfile: overrideProfile ?? null,
|
|
827
|
+
forceOverrideProfile,
|
|
828
|
+
selectionSeed: conversationId,
|
|
829
|
+
},
|
|
830
|
+
);
|
|
831
|
+
} catch (err) {
|
|
832
|
+
log.warn(
|
|
833
|
+
{ conversationId, source, err },
|
|
834
|
+
"agent-wake: usage recording failed (non-fatal)",
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
787
838
|
// Replicates the recordRequestLog side-effect in `handleUsage` because
|
|
788
839
|
// wakes own their own onEvent and never reach `dispatchAgentEvent`.
|
|
789
840
|
// Defer persistence while buffering — see `pendingLogs` above.
|
|
@@ -1080,6 +1131,7 @@ export async function wakeAgentForOpportunity(
|
|
|
1080
1131
|
trust: wakeTrust,
|
|
1081
1132
|
overrideProfile,
|
|
1082
1133
|
forceOverrideProfile,
|
|
1134
|
+
isNonInteractive,
|
|
1083
1135
|
// The wake's compaction lives in the pre-run gate above
|
|
1084
1136
|
// (`conversation.maybeCompact()`), never in the loop: the in-loop
|
|
1085
1137
|
// budget gate and overflow-recovery ladder stay disabled because
|
|
@@ -40,6 +40,7 @@ export function capabilityForMessageType(
|
|
|
40
40
|
return HOST_PREFIX_TO_CAPABILITY[stem];
|
|
41
41
|
}
|
|
42
42
|
import { appendEventToStream } from "../signals/event-stream.js";
|
|
43
|
+
import { IntegrityError } from "../util/errors.js";
|
|
43
44
|
import { getLogger } from "../util/logger.js";
|
|
44
45
|
import type { AssistantEvent } from "./assistant-event.js";
|
|
45
46
|
import { buildAssistantEvent } from "./assistant-event.js";
|
|
@@ -757,9 +758,22 @@ async function createCanonicalRequestForConfirmation(
|
|
|
757
758
|
});
|
|
758
759
|
}
|
|
759
760
|
} catch (err) {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
761
|
+
if (err instanceof IntegrityError) {
|
|
762
|
+
// The confirmation could not be promoted to a canonical guardian request
|
|
763
|
+
// (e.g. its trust context resolved no guardianPrincipalId). Channel
|
|
764
|
+
// guardian decisions — reactions, buttons, and text — all route through
|
|
765
|
+
// the canonical pipeline, so without this record none of them can resolve
|
|
766
|
+
// the confirmation. Surface it rather than swallowing: for a guardian's
|
|
767
|
+
// own confirmation a bound principal should always be present.
|
|
768
|
+
log.warn(
|
|
769
|
+
{ err, conversationId, requestId: msg.requestId },
|
|
770
|
+
"Could not create canonical guardian request for confirmation; channel guardian decisions will not work for it",
|
|
771
|
+
);
|
|
772
|
+
} else {
|
|
773
|
+
log.debug(
|
|
774
|
+
{ err, conversationId },
|
|
775
|
+
"Failed to create canonical request from broadcast",
|
|
776
|
+
);
|
|
777
|
+
}
|
|
764
778
|
}
|
|
765
779
|
}
|
|
@@ -210,6 +210,18 @@ describe("ROUTES policy declarations", () => {
|
|
|
210
210
|
expect(route!.policy!.requiredScopes).toContain("chat.write");
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
+
test("platform/status is readable by browser actors", async () => {
|
|
214
|
+
const { ROUTES } = await import("../../routes/index.js");
|
|
215
|
+
const route = ROUTES.find(
|
|
216
|
+
(r) => r.endpoint === "platform/status" && r.method === "GET",
|
|
217
|
+
);
|
|
218
|
+
expect(route).toBeDefined();
|
|
219
|
+
expect(route!.policy).not.toBeNull();
|
|
220
|
+
expect(route!.policy!.allowedPrincipalTypes).toContain("actor");
|
|
221
|
+
expect(route!.policy!.allowedPrincipalTypes).toContain("local");
|
|
222
|
+
expect(route!.policy!.requiredScopes).toContain("settings.read");
|
|
223
|
+
});
|
|
224
|
+
|
|
213
225
|
test("confirm declares an approval-write policy", async () => {
|
|
214
226
|
const { ROUTES } = await import("../../routes/index.js");
|
|
215
227
|
const route = ROUTES.find((r) => r.endpoint === "confirm");
|
|
@@ -27,10 +27,7 @@ export function requireBoundGuardian(
|
|
|
27
27
|
// No guardian yet — in pre-bootstrap state, allow through
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
|
-
if (
|
|
31
|
-
(guardianResult.channel.externalUserId ??
|
|
32
|
-
guardianResult.contact.principalId) !== authContext.actorPrincipalId
|
|
33
|
-
) {
|
|
30
|
+
if (guardianResult.channel.address !== authContext.actorPrincipalId) {
|
|
34
31
|
return httpError(
|
|
35
32
|
"FORBIDDEN",
|
|
36
33
|
"Actor is not the bound guardian for this channel",
|
|
@@ -31,10 +31,9 @@ export interface RunBtwSidechainParams {
|
|
|
31
31
|
/**
|
|
32
32
|
* Unified call-site identifier. The provider layer resolves
|
|
33
33
|
* provider/model/maxTokens/effort/speed/temperature/thinking/contextWindow
|
|
34
|
-
* via `resolveCallSiteConfig(callSite, config.llm)`.
|
|
35
|
-
* `
|
|
36
|
-
*
|
|
37
|
-
* override it with their own call-site ID.
|
|
34
|
+
* via `resolveCallSiteConfig(callSite, config.llm)`. Generic BTW traffic
|
|
35
|
+
* uses `identityIntro`; callers with a narrower purpose override it with
|
|
36
|
+
* their own call-site ID.
|
|
38
37
|
*/
|
|
39
38
|
callSite?: LLMCallSite;
|
|
40
39
|
signal?: AbortSignal;
|
|
@@ -95,8 +94,6 @@ export async function runBtwSidechain(
|
|
|
95
94
|
config: {
|
|
96
95
|
max_tokens: params.maxTokens ?? 1024,
|
|
97
96
|
tool_choice: { type: "none" },
|
|
98
|
-
// Default call site is "identityIntro" — the original purpose of
|
|
99
|
-
// this side-chain runner. Callers may override per invocation.
|
|
100
97
|
callSite: params.callSite ?? ("identityIntro" as LLMCallSite),
|
|
101
98
|
},
|
|
102
99
|
onEvent: (event) => {
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { TrustClass } from "./actor-trust-resolver.js";
|
|
4
|
+
import { type CapabilitySet, resolveCapabilities } from "./capabilities.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The capability matrix — the single source of truth for what each trust class
|
|
8
|
+
* may do. If a call site's behavior changes during migration, it changes here
|
|
9
|
+
* (reviewed in one diff) instead of across the ~40 inline conditionals.
|
|
10
|
+
*/
|
|
11
|
+
const MATRIX: Record<TrustClass, CapabilitySet> = {
|
|
12
|
+
guardian: {
|
|
13
|
+
canSelfApproveTools: true,
|
|
14
|
+
sensitiveToolApproval: "self",
|
|
15
|
+
canManageSchedules: true,
|
|
16
|
+
canUseVerificationControlPlane: true,
|
|
17
|
+
canSelfAuthorizeArchiveBySender: true,
|
|
18
|
+
canAccessMemory: true,
|
|
19
|
+
canAccessPrivilegedDocuments: true,
|
|
20
|
+
canRunUnsandboxedShell: true,
|
|
21
|
+
mayBeInteractive: true,
|
|
22
|
+
canActUnderDiskPressureCleanup: true,
|
|
23
|
+
promptTrustGuidance: "none",
|
|
24
|
+
},
|
|
25
|
+
trusted_contact: {
|
|
26
|
+
canSelfApproveTools: false,
|
|
27
|
+
sensitiveToolApproval: "escalate-and-wait",
|
|
28
|
+
canManageSchedules: false,
|
|
29
|
+
canUseVerificationControlPlane: false,
|
|
30
|
+
canSelfAuthorizeArchiveBySender: false,
|
|
31
|
+
canAccessMemory: false,
|
|
32
|
+
canAccessPrivilegedDocuments: false,
|
|
33
|
+
canRunUnsandboxedShell: false,
|
|
34
|
+
mayBeInteractive: true,
|
|
35
|
+
canActUnderDiskPressureCleanup: false,
|
|
36
|
+
promptTrustGuidance: "social-engineering-defense",
|
|
37
|
+
},
|
|
38
|
+
unverified_contact: {
|
|
39
|
+
canSelfApproveTools: false,
|
|
40
|
+
sensitiveToolApproval: "escalate-and-wait",
|
|
41
|
+
canManageSchedules: false,
|
|
42
|
+
canUseVerificationControlPlane: false,
|
|
43
|
+
canSelfAuthorizeArchiveBySender: false,
|
|
44
|
+
canAccessMemory: false,
|
|
45
|
+
canAccessPrivilegedDocuments: false,
|
|
46
|
+
canRunUnsandboxedShell: false,
|
|
47
|
+
mayBeInteractive: true,
|
|
48
|
+
canActUnderDiskPressureCleanup: false,
|
|
49
|
+
promptTrustGuidance: "social-engineering-defense",
|
|
50
|
+
},
|
|
51
|
+
unknown: {
|
|
52
|
+
canSelfApproveTools: false,
|
|
53
|
+
sensitiveToolApproval: "deny",
|
|
54
|
+
canManageSchedules: false,
|
|
55
|
+
canUseVerificationControlPlane: false,
|
|
56
|
+
canSelfAuthorizeArchiveBySender: false,
|
|
57
|
+
canAccessMemory: false,
|
|
58
|
+
canAccessPrivilegedDocuments: false,
|
|
59
|
+
canRunUnsandboxedShell: false,
|
|
60
|
+
mayBeInteractive: false,
|
|
61
|
+
canActUnderDiskPressureCleanup: false,
|
|
62
|
+
promptTrustGuidance: "stranger-warning",
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
describe("resolveCapabilities", () => {
|
|
67
|
+
for (const trustClass of Object.keys(MATRIX) as TrustClass[]) {
|
|
68
|
+
test(`resolves the full capability set for "${trustClass}"`, () => {
|
|
69
|
+
expect(resolveCapabilities(trustClass)).toEqual(MATRIX[trustClass]);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("undefined fail-closes to the `unknown` capability set", () => {
|
|
74
|
+
expect(resolveCapabilities(undefined)).toEqual(MATRIX.unknown);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("an unrecognized/legacy string fail-closes to the `unknown` capability set", () => {
|
|
78
|
+
expect(resolveCapabilities("non_guardian")).toEqual(MATRIX.unknown);
|
|
79
|
+
expect(resolveCapabilities("some_future_role")).toEqual(MATRIX.unknown);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("inherited Object.prototype keys fail-closed (no prototype read)", () => {
|
|
83
|
+
for (const key of [
|
|
84
|
+
"__proto__",
|
|
85
|
+
"constructor",
|
|
86
|
+
"toString",
|
|
87
|
+
"hasOwnProperty",
|
|
88
|
+
]) {
|
|
89
|
+
expect(resolveCapabilities(key)).toEqual(MATRIX.unknown);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("unverified_contact is byte-for-byte identical to trusted_contact (admission-only distinction)", () => {
|
|
94
|
+
expect(resolveCapabilities("unverified_contact")).toEqual(
|
|
95
|
+
resolveCapabilities("trusted_contact"),
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("only guardian self-approves; only guardian/contacts may be interactive", () => {
|
|
100
|
+
expect(resolveCapabilities("guardian").canSelfApproveTools).toBe(true);
|
|
101
|
+
expect(resolveCapabilities("trusted_contact").canSelfApproveTools).toBe(
|
|
102
|
+
false,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(resolveCapabilities("guardian").mayBeInteractive).toBe(true);
|
|
106
|
+
expect(resolveCapabilities("trusted_contact").mayBeInteractive).toBe(true);
|
|
107
|
+
expect(resolveCapabilities("unverified_contact").mayBeInteractive).toBe(
|
|
108
|
+
true,
|
|
109
|
+
);
|
|
110
|
+
expect(resolveCapabilities("unknown").mayBeInteractive).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("sensitive tool approval is graded across the three tiers", () => {
|
|
114
|
+
expect(resolveCapabilities("guardian").sensitiveToolApproval).toBe("self");
|
|
115
|
+
expect(resolveCapabilities("trusted_contact").sensitiveToolApproval).toBe(
|
|
116
|
+
"escalate-and-wait",
|
|
117
|
+
);
|
|
118
|
+
expect(resolveCapabilities("unknown").sensitiveToolApproval).toBe("deny");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trust capabilities — what an actor may do once admitted.
|
|
3
|
+
*
|
|
4
|
+
* Separates *what an actor can do* (capabilities/permissions) from *who the
|
|
5
|
+
* actor is* (`TrustClass`, their role/level). The ~40+ decision sites
|
|
6
|
+
* read a named capability instead of re-deriving permissions inline from the
|
|
7
|
+
* This resolves the class to a named capability set in one place so call sites
|
|
8
|
+
* read a capability instead of re-deriving it.
|
|
9
|
+
*
|
|
10
|
+
* Stateless / derive-on-read: capabilities are derived from the already-resolved
|
|
11
|
+
* (and already-persisted) `trustClass` at point of use. Nothing here is stored;
|
|
12
|
+
* `trustClass` remains the persisted field in retry payloads, the journal store,
|
|
13
|
+
* and conversation CRUD.
|
|
14
|
+
*
|
|
15
|
+
* Admission is a SEPARATE axis: `TRUST_CLASS_RANK` vs `ADMISSION_FLOOR`
|
|
16
|
+
* ("who gets in the door") is intentionally not modeled here. `CapabilitySet`
|
|
17
|
+
* is the "what they may do once inside" axis.
|
|
18
|
+
*
|
|
19
|
+
* Context-dependent decisions (interactivity routing, self-approval races,
|
|
20
|
+
* channel-specific overrides) COMPOSE these primitives with runtime context.
|
|
21
|
+
* They are not encoded in the table; named composition helpers live in
|
|
22
|
+
* `effective-capabilities.ts` (and `resolveRoutingState` in
|
|
23
|
+
* `trust-context-resolver.ts`).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { TrustClass } from "./actor-trust-resolver.js";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Outcome when an actor invokes a tool that requires guardian approval.
|
|
30
|
+
* - `self`: the actor self-approves (guardian).
|
|
31
|
+
* - `escalate-and-wait`: route to the guardian and wait inline for a grant.
|
|
32
|
+
* - `deny`: fail-closed, no escalation or wait.
|
|
33
|
+
*/
|
|
34
|
+
export type SensitiveToolApproval = "self" | "escalate-and-wait" | "deny";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Which trust-guidance block to inject into the model prompt. The capability
|
|
38
|
+
* layer owns the *selector*; the prompt layer owns the copy for each value.
|
|
39
|
+
*/
|
|
40
|
+
export type PromptTrustGuidance =
|
|
41
|
+
| "none"
|
|
42
|
+
| "social-engineering-defense"
|
|
43
|
+
| "stranger-warning";
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* What an actor may do once admitted, derived purely from their trust class.
|
|
47
|
+
*/
|
|
48
|
+
export interface CapabilitySet {
|
|
49
|
+
// --- Tool approval mechanism ---
|
|
50
|
+
/**
|
|
51
|
+
* Auto-approves *ordinary* tool calls (e.g. background/platform-hosted bash)
|
|
52
|
+
* and honors the actor's own pending-confirmation callback. The
|
|
53
|
+
* sensitive/guardian-required tool path is governed separately by
|
|
54
|
+
* `sensitiveToolApproval`; the two are independent levers.
|
|
55
|
+
*/
|
|
56
|
+
canSelfApproveTools: boolean;
|
|
57
|
+
/** Outcome when a guardian-approval-required (sensitive) tool is invoked. */
|
|
58
|
+
sensitiveToolApproval: SensitiveToolApproval;
|
|
59
|
+
|
|
60
|
+
// --- Privileged tool gates ---
|
|
61
|
+
/** May create/update schedules. */
|
|
62
|
+
canManageSchedules: boolean;
|
|
63
|
+
/** May use verification control-plane tools. */
|
|
64
|
+
canUseVerificationControlPlane: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* May treat its own `user_approved` flag as sufficient authorization to
|
|
67
|
+
* archive-by-sender. Non-guardians can still archive by sender, but must be
|
|
68
|
+
* authorized via surface action, task, or explicit prompt approval instead.
|
|
69
|
+
*/
|
|
70
|
+
canSelfAuthorizeArchiveBySender: boolean;
|
|
71
|
+
|
|
72
|
+
// --- Data & memory ---
|
|
73
|
+
/**
|
|
74
|
+
* May access long-term / cross-conversation memory — both the memory *tools*
|
|
75
|
+
* (recall, auto-analysis, retrospection, graph extraction) and *visibility*
|
|
76
|
+
* of cross-conversation history in assembled context. Untrusted actors are
|
|
77
|
+
* walled off from both.
|
|
78
|
+
*/
|
|
79
|
+
canAccessMemory: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* May perform privileged (non-conversation-scoped) document operations from
|
|
82
|
+
* trust class alone. The effective decision also honors privileged channels —
|
|
83
|
+
* see `canActOnPrivilegedDocuments` in `effective-capabilities.ts`.
|
|
84
|
+
*/
|
|
85
|
+
canAccessPrivilegedDocuments: boolean;
|
|
86
|
+
|
|
87
|
+
// --- Execution environment ---
|
|
88
|
+
/**
|
|
89
|
+
* May run the shell WITHOUT the untrusted sandbox / CES lockdown (no
|
|
90
|
+
* `VELLUM_UNTRUSTED_SHELL`, no credential-secrecy confinement).
|
|
91
|
+
*/
|
|
92
|
+
canRunUnsandboxedShell: boolean;
|
|
93
|
+
|
|
94
|
+
// --- Interactivity & resource ---
|
|
95
|
+
/**
|
|
96
|
+
* Trust class alone permits interactive guardian-approval waits. Composed
|
|
97
|
+
* downstream with `guardianRouteResolvable` to derive `promptWaitingAllowed`
|
|
98
|
+
* (see `resolveRoutingState`).
|
|
99
|
+
*/
|
|
100
|
+
mayBeInteractive: boolean;
|
|
101
|
+
/** May trigger cleanup-mode operations under disk pressure. */
|
|
102
|
+
canActUnderDiskPressureCleanup: boolean;
|
|
103
|
+
|
|
104
|
+
// --- Prompt shaping ---
|
|
105
|
+
/** Which trust-guidance block to inject into the model prompt. */
|
|
106
|
+
promptTrustGuidance: PromptTrustGuidance;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Guardian: full control-plane access, self-approves tools.
|
|
111
|
+
*/
|
|
112
|
+
const GUARDIAN_CAPABILITIES: CapabilitySet = {
|
|
113
|
+
canSelfApproveTools: true,
|
|
114
|
+
sensitiveToolApproval: "self",
|
|
115
|
+
canManageSchedules: true,
|
|
116
|
+
canUseVerificationControlPlane: true,
|
|
117
|
+
canSelfAuthorizeArchiveBySender: true,
|
|
118
|
+
canAccessMemory: true,
|
|
119
|
+
canAccessPrivilegedDocuments: true,
|
|
120
|
+
canRunUnsandboxedShell: true,
|
|
121
|
+
mayBeInteractive: true,
|
|
122
|
+
canActUnderDiskPressureCleanup: true,
|
|
123
|
+
promptTrustGuidance: "none",
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Trusted / unverified contacts: may invoke tools but escalate sensitive ones
|
|
128
|
+
* to the guardian; no privileged data access; sandboxed execution.
|
|
129
|
+
*
|
|
130
|
+
* `trusted_contact` and `unverified_contact` are deliberately identical here —
|
|
131
|
+
* the distinction is admission-only (see `actor-trust-resolver.ts`). The matrix
|
|
132
|
+
* test pins this invariant.
|
|
133
|
+
*/
|
|
134
|
+
const CONTACT_CAPABILITIES: CapabilitySet = {
|
|
135
|
+
canSelfApproveTools: false,
|
|
136
|
+
sensitiveToolApproval: "escalate-and-wait",
|
|
137
|
+
canManageSchedules: false,
|
|
138
|
+
canUseVerificationControlPlane: false,
|
|
139
|
+
canSelfAuthorizeArchiveBySender: false,
|
|
140
|
+
canAccessMemory: false,
|
|
141
|
+
canAccessPrivilegedDocuments: false,
|
|
142
|
+
canRunUnsandboxedShell: false,
|
|
143
|
+
mayBeInteractive: true,
|
|
144
|
+
canActUnderDiskPressureCleanup: false,
|
|
145
|
+
promptTrustGuidance: "social-engineering-defense",
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Unknown actors: fail-closed. No escalation, no interactivity, treated as a
|
|
150
|
+
* potential stranger in the prompt.
|
|
151
|
+
*/
|
|
152
|
+
const UNKNOWN_CAPABILITIES: CapabilitySet = {
|
|
153
|
+
canSelfApproveTools: false,
|
|
154
|
+
sensitiveToolApproval: "deny",
|
|
155
|
+
canManageSchedules: false,
|
|
156
|
+
canUseVerificationControlPlane: false,
|
|
157
|
+
canSelfAuthorizeArchiveBySender: false,
|
|
158
|
+
canAccessMemory: false,
|
|
159
|
+
canAccessPrivilegedDocuments: false,
|
|
160
|
+
canRunUnsandboxedShell: false,
|
|
161
|
+
mayBeInteractive: false,
|
|
162
|
+
canActUnderDiskPressureCleanup: false,
|
|
163
|
+
promptTrustGuidance: "stranger-warning",
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const CAPABILITIES_BY_CLASS: Record<TrustClass, CapabilitySet> = {
|
|
167
|
+
guardian: GUARDIAN_CAPABILITIES,
|
|
168
|
+
trusted_contact: CONTACT_CAPABILITIES,
|
|
169
|
+
unverified_contact: CONTACT_CAPABILITIES,
|
|
170
|
+
unknown: UNKNOWN_CAPABILITIES,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Resolve the capability set for a trust class. Pure and stateless.
|
|
175
|
+
*
|
|
176
|
+
* This is the single fail-closed trust boundary: any value that is not a
|
|
177
|
+
* recognized `TrustClass` — including `undefined` and legacy/persisted strings
|
|
178
|
+
* (e.g. `"non_guardian"`) — resolves to the `unknown` capability set. Callers
|
|
179
|
+
* pass their raw trust value directly; they never re-derive "is this a known
|
|
180
|
+
* class?" at the call site. The `(string & {})` member keeps autocomplete for
|
|
181
|
+
* the known classes while still accepting an arbitrary string.
|
|
182
|
+
*
|
|
183
|
+
* The lookup uses an own-property check so raw values that name inherited
|
|
184
|
+
* members (`"__proto__"`, `"constructor"`, `"toString"`) fail closed to the
|
|
185
|
+
* `unknown` set rather than reading off `Object.prototype`.
|
|
186
|
+
*/
|
|
187
|
+
export function resolveCapabilities(
|
|
188
|
+
trustClass: TrustClass | (string & {}) | undefined,
|
|
189
|
+
): CapabilitySet {
|
|
190
|
+
if (
|
|
191
|
+
trustClass != null &&
|
|
192
|
+
Object.prototype.hasOwnProperty.call(CAPABILITIES_BY_CLASS, trustClass)
|
|
193
|
+
) {
|
|
194
|
+
return CAPABILITIES_BY_CLASS[trustClass as TrustClass];
|
|
195
|
+
}
|
|
196
|
+
return UNKNOWN_CAPABILITIES;
|
|
197
|
+
}
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Channel-agnostic approval flow types.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Wire-format types (`ApprovalUIMetadata`, `PermissionRequestDetails`,
|
|
5
|
+
* `ApprovalActionOption`) are defined as Zod schemas in
|
|
6
|
+
* `@vellumai/gateway-client/outbound-contract` and re-exported here for
|
|
7
|
+
* convenience. Daemon-internal types that do not cross a wire boundary
|
|
8
|
+
* are defined locally.
|
|
8
9
|
*/
|
|
9
10
|
|
|
11
|
+
import type { ApprovalActionOption } from "@vellumai/gateway-client";
|
|
12
|
+
|
|
10
13
|
import type { GuardianDecisionAction } from "./guardian-decision-types.js";
|
|
11
14
|
|
|
15
|
+
export type {
|
|
16
|
+
ApprovalActionOption,
|
|
17
|
+
ApprovalUIMetadata,
|
|
18
|
+
PermissionRequestDetails,
|
|
19
|
+
} from "@vellumai/gateway-client";
|
|
20
|
+
// Re-export shared wire types + schemas so existing daemon imports keep working.
|
|
21
|
+
export {
|
|
22
|
+
ApprovalUIMetadataSchema,
|
|
23
|
+
PermissionRequestDetailsSchema,
|
|
24
|
+
} from "@vellumai/gateway-client";
|
|
25
|
+
|
|
12
26
|
// ---------------------------------------------------------------------------
|
|
13
|
-
// Approval actions
|
|
27
|
+
// Approval actions (daemon-internal)
|
|
14
28
|
// ---------------------------------------------------------------------------
|
|
15
29
|
|
|
16
30
|
/** The set of actions a user can take on an approval prompt. */
|
|
17
31
|
export type ApprovalAction = "approve_once" | "reject";
|
|
18
32
|
|
|
19
|
-
/** An action presented to the user as a tappable button or text option. */
|
|
20
|
-
export interface ApprovalActionOption {
|
|
21
|
-
id: ApprovalAction;
|
|
22
|
-
label: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
33
|
/**
|
|
26
34
|
* Map `GuardianDecisionAction[]` to `ApprovalActionOption[]` so channel
|
|
27
35
|
* prompt payloads can be derived from the unified decision action set.
|
|
@@ -32,13 +40,13 @@ export function toApprovalActionOptions(
|
|
|
32
40
|
actions: GuardianDecisionAction[],
|
|
33
41
|
): ApprovalActionOption[] {
|
|
34
42
|
return actions.map((a) => ({
|
|
35
|
-
id: a.action
|
|
43
|
+
id: a.action,
|
|
36
44
|
label: a.label,
|
|
37
45
|
}));
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
// ---------------------------------------------------------------------------
|
|
41
|
-
// Approval prompt
|
|
49
|
+
// Approval prompt (daemon-internal)
|
|
42
50
|
// ---------------------------------------------------------------------------
|
|
43
51
|
|
|
44
52
|
/** The approval prompt model sent to users via a channel. */
|
|
@@ -52,38 +60,7 @@ export interface ChannelApprovalPrompt {
|
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
// ---------------------------------------------------------------------------
|
|
55
|
-
//
|
|
56
|
-
// ---------------------------------------------------------------------------
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Tool-permission-specific details carried alongside the approval payload.
|
|
60
|
-
* Channels that support rich UI (e.g. Slack Block Kit) use these fields
|
|
61
|
-
* to render a detailed permission request card with risk indicators,
|
|
62
|
-
* tool arguments, and requester identity.
|
|
63
|
-
*/
|
|
64
|
-
export interface PermissionRequestDetails {
|
|
65
|
-
toolName: string;
|
|
66
|
-
riskLevel: string;
|
|
67
|
-
toolInput: Record<string, unknown>;
|
|
68
|
-
/** Present for guardian-escalated requests to identify who is asking. */
|
|
69
|
-
requesterIdentifier?: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Metadata attached to gateway callback payloads so the channel adapter
|
|
74
|
-
* can render approval UI and route the user's decision back to the
|
|
75
|
-
* correct pending interaction.
|
|
76
|
-
*/
|
|
77
|
-
export interface ApprovalUIMetadata {
|
|
78
|
-
requestId: string;
|
|
79
|
-
actions: ApprovalActionOption[];
|
|
80
|
-
plainTextFallback: string;
|
|
81
|
-
/** When present, the approval is a tool permission request with extra context. */
|
|
82
|
-
permissionDetails?: PermissionRequestDetails;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
// Decision result
|
|
63
|
+
// Decision result (daemon-internal)
|
|
87
64
|
// ---------------------------------------------------------------------------
|
|
88
65
|
|
|
89
66
|
/** How the user communicated their decision. */
|
|
@@ -36,10 +36,10 @@ import type {
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Ensure the Telegram bot username is resolved and cached in config.
|
|
39
|
-
* When the bot token was configured via
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
39
|
+
* When the bot token was configured via the `assistant credentials set` CLI
|
|
40
|
+
* or ingress secret redirect, the `getMe` API call that populates the config
|
|
41
|
+
* is skipped — this function fills that gap so that invite share links can be
|
|
42
|
+
* generated.
|
|
43
43
|
*/
|
|
44
44
|
export async function ensureTelegramBotUsernameResolved(): Promise<void> {
|
|
45
45
|
if (getTelegramBotUsername() && getTelegramBotId()) {
|
|
@@ -333,7 +333,7 @@ export function getGuardianBinding(
|
|
|
333
333
|
id: result.channel.id,
|
|
334
334
|
assistantId,
|
|
335
335
|
channel,
|
|
336
|
-
guardianExternalUserId: result.channel.
|
|
336
|
+
guardianExternalUserId: result.channel.address,
|
|
337
337
|
guardianDeliveryChatId: result.channel.externalChatId ?? "",
|
|
338
338
|
guardianPrincipalId: result.contact.principalId ?? "",
|
|
339
339
|
status: "active" as const,
|
|
@@ -355,11 +355,11 @@ export function getGuardianBinding(
|
|
|
355
355
|
export function isGuardian(
|
|
356
356
|
assistantId: string,
|
|
357
357
|
channel: string,
|
|
358
|
-
|
|
358
|
+
address: string,
|
|
359
359
|
): boolean {
|
|
360
360
|
const result = findGuardianForChannel(channel);
|
|
361
361
|
if (result) {
|
|
362
|
-
return result.channel.
|
|
362
|
+
return result.channel.address.toLowerCase() === address.toLowerCase();
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
return false;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health heuristics for connected SSE clients.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Keep-alive comment sent to idle clients every 7 s by default. */
|
|
6
|
+
export const DEFAULT_HEARTBEAT_INTERVAL_MS = 7_000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Whether a client looks degraded: its last heartbeat (`lastActiveAt`) is
|
|
10
|
+
* stale by more than two heartbeat intervals. This surfaces a
|
|
11
|
+
* registered-but-not-heartbeating connection — the symptom of a flapping
|
|
12
|
+
* extension SSE stream — whether it never heartbeated or heartbeated and
|
|
13
|
+
* then froze. A healthy client (fresh or actively heartbeating) has a
|
|
14
|
+
* recent `lastActiveAt` and is not flagged.
|
|
15
|
+
*
|
|
16
|
+
* Limitation: a just-reconnected flapping client has a fresh
|
|
17
|
+
* `lastActiveAt` and looks healthy in a single snapshot — this is
|
|
18
|
+
* best-effort visibility, not a liveness guarantee.
|
|
19
|
+
*/
|
|
20
|
+
export function isClientDegraded(
|
|
21
|
+
lastActiveAt: Date,
|
|
22
|
+
now: Date,
|
|
23
|
+
heartbeatIntervalMs: number,
|
|
24
|
+
): boolean {
|
|
25
|
+
return now.getTime() - lastActiveAt.getTime() > 2 * heartbeatIntervalMs;
|
|
26
|
+
}
|