@vellumai/assistant 0.7.0 → 0.7.1
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 +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +0 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
package/ARCHITECTURE.md
CHANGED
|
@@ -1606,11 +1606,11 @@ graph TB
|
|
|
1606
1606
|
Auto-approve thresholds are **gateway-owned** — they live in the gateway's SQLite database and are read by the assistant via IPC (`get_global_thresholds`, `get_conversation_threshold`). Users control thresholds via the **Settings UI** (Permissions & Privacy tab) or the **per-conversation risk tolerance picker**. When the gateway is unreachable, the assistant defaults to `"none"` (Strict) — fail-closed with no local fallback.
|
|
1607
1607
|
|
|
1608
1608
|
| `autoApproveUpTo` | Low-risk tools | Medium-risk tools | High-risk tools |
|
|
1609
|
-
|
|
|
1610
|
-
| `"none"`
|
|
1611
|
-
| `"low"` (default)
|
|
1612
|
-
| `"medium"`
|
|
1613
|
-
| `"high"`
|
|
1609
|
+
| ----------------- | -------------- | ----------------- | --------------- |
|
|
1610
|
+
| `"none"` | Prompted | Prompted | Prompted |
|
|
1611
|
+
| `"low"` (default) | Auto-allowed | Prompted | Prompted |
|
|
1612
|
+
| `"medium"` | Auto-allowed | Auto-allowed | Prompted |
|
|
1613
|
+
| `"high"` | Auto-allowed | Auto-allowed | Auto-allowed |
|
|
1614
1614
|
|
|
1615
1615
|
When set to `"none"`, every tool invocation requires explicit approval. Explicit deny and ask rules always take precedence over the threshold.
|
|
1616
1616
|
|
|
@@ -1867,7 +1867,6 @@ Events emitted during a conversation lifecycle:
|
|
|
1867
1867
|
| `tool_permission_decided` | ToolTraceListener | Permission granted or denied (carries `decision`) |
|
|
1868
1868
|
| `tool_finished` | ToolTraceListener | Tool execution completed (carries `durationMs`) |
|
|
1869
1869
|
| `tool_failed` | ToolTraceListener | Tool execution failed (carries `durationMs`) |
|
|
1870
|
-
| `secret_detected` | ToolTraceListener | Secret found in tool output |
|
|
1871
1870
|
| `generation_handoff` | Conversation | Yielding to next queued message |
|
|
1872
1871
|
| `message_complete` | Conversation | Full request processing finished |
|
|
1873
1872
|
| `generation_cancelled` | Conversation | User cancelled the generation |
|
|
@@ -1876,7 +1875,7 @@ Events emitted during a conversation lifecycle:
|
|
|
1876
1875
|
### Architecture
|
|
1877
1876
|
|
|
1878
1877
|
- **TraceEmitter** (daemon, per-conversation): Constructed with a `conversationId` and a `sendToClient` callback. Maintains a monotonic sequence counter for stable ordering. Truncates summaries to 200 chars and attribute values to 500 chars. Each call to `emit()` sends a `trace_event` SSE event to connected clients.
|
|
1879
|
-
- **ToolTraceListener** (daemon): Subscribes to the conversation's `EventBus` via `onAny()` and translates tool domain events (`tool.execution.started`, `tool.execution.finished`, `tool.execution.failed`, `tool.permission.requested`, `tool.permission.decided
|
|
1878
|
+
- **ToolTraceListener** (daemon): Subscribes to the conversation's `EventBus` via `onAny()` and translates tool domain events (`tool.execution.started`, `tool.execution.finished`, `tool.execution.failed`, `tool.permission.requested`, `tool.permission.decided`) into trace events through the `TraceEmitter`.
|
|
1880
1879
|
- **DaemonClient** (Swift, shared): Decodes `trace_event` SSE events into `TraceEventMessage` structs and invokes the `onTraceEvent` callback.
|
|
1881
1880
|
- **TraceStore** (Swift, macOS): `@MainActor ObservableObject` that ingests `TraceEventMessage` structs. Deduplicates by `eventId`, maintains stable sort order (sequence, then timestampMs, then insertion order), groups events by conversation and requestId, and enforces a retention cap of 5,000 events per conversation. Each request group is classified with a terminal status: `completed` (via `message_complete`), `cancelled` (via `generation_cancelled`), `handedOff` (via `generation_handoff`), `error` (via `request_error` or any event with `status == "error"`), or `active` (no terminal event yet).
|
|
1882
1881
|
- **DebugPanel** (Swift, macOS): SwiftUI view that observes `TraceStore`. Displays a metrics strip (request count, LLM calls, total tokens, average latency, tool failures) and a `TraceTimelineView` showing events grouped by requestId with color-coded status indicators. The timeline auto-scrolls to new events while the user is at the bottom; scrolling up pauses auto-scroll and shows a "Jump to bottom" button that resumes it.
|
package/Dockerfile
CHANGED
|
@@ -23,6 +23,7 @@ COPY packages/credential-storage ./packages/credential-storage
|
|
|
23
23
|
COPY packages/egress-proxy ./packages/egress-proxy
|
|
24
24
|
COPY packages/gateway-client ./packages/gateway-client
|
|
25
25
|
COPY packages/skill-host-contracts ./packages/skill-host-contracts
|
|
26
|
+
COPY packages/slack-text ./packages/slack-text
|
|
26
27
|
|
|
27
28
|
# Install deps for shared packages that have their own file: dependencies.
|
|
28
29
|
# Without this, bun's module resolution at runtime walks up from e.g.
|
package/README.md
CHANGED
|
@@ -85,7 +85,7 @@ bun run src/index.ts # interactive CLI session
|
|
|
85
85
|
| `assistant conversations list\|new\|export\|clear` | Manage conversations |
|
|
86
86
|
| `assistant config set\|get\|list` | Manage configuration |
|
|
87
87
|
| `assistant keys set\|list\|delete` | Manage API keys in secure storage |
|
|
88
|
-
| `assistant trust list\|add\|update\|remove`
|
|
88
|
+
| `assistant trust list\|add\|update\|remove` | Manage trust rules |
|
|
89
89
|
|
|
90
90
|
## Project Structure
|
|
91
91
|
|
|
@@ -189,7 +189,7 @@ Internal forwarding routes (`/v1/internal/twilio/*`) are unaffected — these ac
|
|
|
189
189
|
The `/channels/inbound` endpoint requires a JWT with the `svc_gateway` principal type and `ingress.write` scope to prove the request originated from the gateway. This ensures channel messages can only arrive via the gateway (which performs webhook-level verification) and not via direct HTTP calls that bypass signature checks.
|
|
190
190
|
|
|
191
191
|
- **JWT-based enforcement:** The route policy in `route-policy.ts` restricts `/channels/inbound` to the `svc_gateway` principal type with `ingress.write` scope. Actor and local principals are rejected with 403.
|
|
192
|
-
- **
|
|
192
|
+
- **Auth bypass:** When `DISABLE_HTTP_AUTH=true` is set (platform-managed deployments), JWT verification is skipped and a synthetic context is used.
|
|
193
193
|
|
|
194
194
|
## Twilio Setup Primitive
|
|
195
195
|
|
|
@@ -2,35 +2,32 @@ import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
// ── Mocks ────────────────────────────────────────────────────────────────────
|
|
4
4
|
|
|
5
|
-
let mockFeatureFlagEnabled = true;
|
|
6
|
-
|
|
7
5
|
mock.module("../../src/config/assistant-feature-flags.js", () => ({
|
|
8
|
-
isAssistantFeatureFlagEnabled: (
|
|
9
|
-
mockFeatureFlagEnabled,
|
|
6
|
+
isAssistantFeatureFlagEnabled: () => true,
|
|
10
7
|
}));
|
|
11
8
|
|
|
12
9
|
mock.module("../../src/config/loader.js", () => ({
|
|
13
10
|
getConfig: () => ({}),
|
|
14
11
|
}));
|
|
15
12
|
|
|
16
|
-
// Track
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return
|
|
13
|
+
// Track ipcCall invocations for assertion
|
|
14
|
+
const ipcCallLog: string[] = [];
|
|
15
|
+
|
|
16
|
+
// Handler receives (method, params) and returns the IPC response value.
|
|
17
|
+
// Return `undefined` to simulate a transport failure.
|
|
18
|
+
// Return `null` for get_conversation_threshold to indicate "no override".
|
|
19
|
+
type IpcHandler = (method: string, params?: Record<string, unknown>) => unknown;
|
|
20
|
+
let ipcHandler: IpcHandler = () => undefined;
|
|
21
|
+
|
|
22
|
+
mock.module("../../src/ipc/gateway-client.js", () => ({
|
|
23
|
+
ipcCall: async (method: string, params?: Record<string, unknown>) => {
|
|
24
|
+
// Normalise to a readable key for assertions
|
|
25
|
+
const key =
|
|
26
|
+
method === "get_conversation_threshold" && params?.conversationId
|
|
27
|
+
? `/v1/permissions/thresholds/conversations/${params.conversationId}`
|
|
28
|
+
: "/v1/permissions/thresholds";
|
|
29
|
+
ipcCallLog.push(key);
|
|
30
|
+
return ipcHandler(method, params);
|
|
34
31
|
},
|
|
35
32
|
}));
|
|
36
33
|
|
|
@@ -48,42 +45,41 @@ import {
|
|
|
48
45
|
_clearGlobalCacheForTesting,
|
|
49
46
|
getAutoApproveThreshold,
|
|
50
47
|
} from "../../src/permissions/gateway-threshold-reader.js";
|
|
51
|
-
// Import GatewayRequestError from the mock so we can throw instances of it
|
|
52
|
-
const { GatewayRequestError } =
|
|
53
|
-
await import("../../src/runtime/gateway-internal-client.js");
|
|
54
48
|
|
|
55
49
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
56
50
|
|
|
57
51
|
function resetMocks(): void {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
gatewayGetHandler = () => ({});
|
|
52
|
+
ipcCallLog.length = 0;
|
|
53
|
+
ipcHandler = () => undefined;
|
|
61
54
|
_clearGlobalCacheForTesting();
|
|
62
55
|
}
|
|
63
56
|
|
|
64
57
|
afterEach(resetMocks);
|
|
65
58
|
|
|
59
|
+
// Convenience: set up a handler that returns the given global thresholds and,
|
|
60
|
+
// optionally, a per-conversation override threshold string.
|
|
61
|
+
function withGlobals(
|
|
62
|
+
globals: { interactive: string; autonomous: string },
|
|
63
|
+
conversationOverride?: { conversationId: string; threshold: string },
|
|
64
|
+
): void {
|
|
65
|
+
ipcHandler = (method, params) => {
|
|
66
|
+
if (method === "get_global_thresholds") return globals;
|
|
67
|
+
if (method === "get_conversation_threshold") {
|
|
68
|
+
const id = params?.conversationId;
|
|
69
|
+
if (conversationOverride && id === conversationOverride.conversationId) {
|
|
70
|
+
return { threshold: conversationOverride.threshold };
|
|
71
|
+
}
|
|
72
|
+
return null; // no override
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
66
78
|
// ── Tests ────────────────────────────────────────────────────────────────────
|
|
67
79
|
|
|
68
80
|
describe("getAutoApproveThreshold", () => {
|
|
69
|
-
test("returns undefined when feature flag is off", async () => {
|
|
70
|
-
mockFeatureFlagEnabled = false;
|
|
71
|
-
const result = await getAutoApproveThreshold("conv-123", "conversation");
|
|
72
|
-
expect(result).toBeUndefined();
|
|
73
|
-
// Should not make any gateway calls
|
|
74
|
-
expect(gatewayGetCalls).toHaveLength(0);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
81
|
test("returns global defaults when gateway returns them", async () => {
|
|
78
|
-
|
|
79
|
-
if (path === "/v1/permissions/thresholds") {
|
|
80
|
-
return {
|
|
81
|
-
interactive: "medium",
|
|
82
|
-
autonomous: "low",
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
return {};
|
|
86
|
-
};
|
|
82
|
+
withGlobals({ interactive: "medium", autonomous: "low" });
|
|
87
83
|
|
|
88
84
|
// conversation maps to interactive
|
|
89
85
|
expect(await getAutoApproveThreshold(undefined, "conversation")).toBe(
|
|
@@ -102,105 +98,73 @@ describe("getAutoApproveThreshold", () => {
|
|
|
102
98
|
});
|
|
103
99
|
|
|
104
100
|
test("returns conversation override when it exists", async () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (path === "/v1/permissions/thresholds") {
|
|
110
|
-
return {
|
|
111
|
-
interactive: "low",
|
|
112
|
-
autonomous: "none",
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
return {};
|
|
116
|
-
};
|
|
101
|
+
withGlobals(
|
|
102
|
+
{ interactive: "low", autonomous: "none" },
|
|
103
|
+
{ conversationId: "conv-xyz", threshold: "medium" },
|
|
104
|
+
);
|
|
117
105
|
|
|
118
106
|
const result = await getAutoApproveThreshold("conv-xyz", "conversation");
|
|
119
107
|
expect(result).toBe("medium");
|
|
120
108
|
// Should have called the conversation endpoint, not the global one
|
|
121
|
-
expect(
|
|
109
|
+
expect(ipcCallLog).toEqual([
|
|
122
110
|
"/v1/permissions/thresholds/conversations/conv-xyz",
|
|
123
111
|
]);
|
|
124
112
|
});
|
|
125
113
|
|
|
126
|
-
test("falls back to global when conversation override returns
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
throw new GatewayRequestError("Not found", 404, "Not found");
|
|
130
|
-
}
|
|
131
|
-
if (path === "/v1/permissions/thresholds") {
|
|
132
|
-
return {
|
|
133
|
-
interactive: "low",
|
|
134
|
-
autonomous: "none",
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return {};
|
|
138
|
-
};
|
|
114
|
+
test("falls back to global when conversation override returns null (no override)", async () => {
|
|
115
|
+
withGlobals({ interactive: "low", autonomous: "none" });
|
|
116
|
+
// ipcHandler returns null for get_conversation_threshold (no row)
|
|
139
117
|
|
|
140
118
|
const result = await getAutoApproveThreshold("conv-123", "conversation");
|
|
141
119
|
expect(result).toBe("low");
|
|
142
|
-
//
|
|
143
|
-
expect(
|
|
120
|
+
// Called conversation endpoint first, then global
|
|
121
|
+
expect(ipcCallLog).toEqual([
|
|
144
122
|
"/v1/permissions/thresholds/conversations/conv-123",
|
|
145
123
|
"/v1/permissions/thresholds",
|
|
146
124
|
]);
|
|
147
125
|
});
|
|
148
126
|
|
|
149
|
-
test("falls back to
|
|
150
|
-
|
|
127
|
+
test("falls back to global when conversation ipc returns undefined (transport failure)", async () => {
|
|
128
|
+
ipcHandler = (method) => {
|
|
129
|
+
if (method === "get_conversation_threshold") return undefined; // transport failure
|
|
130
|
+
if (method === "get_global_thresholds")
|
|
131
|
+
return { interactive: "low", autonomous: "none" };
|
|
132
|
+
return undefined;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const result = await getAutoApproveThreshold("conv-123", "conversation");
|
|
136
|
+
expect(result).toBe("low");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("falls back to 'none' (Strict) for all contexts on global gateway failure", async () => {
|
|
140
|
+
// When the gateway IPC is unreachable, the reader defaults to "none" for
|
|
141
|
+
// all contexts — defense-in-depth ensures no tools are silently
|
|
142
|
+
// auto-approved when the gateway is down.
|
|
143
|
+
ipcHandler = () => {
|
|
151
144
|
throw new Error("Connection refused");
|
|
152
145
|
};
|
|
153
146
|
|
|
154
|
-
// conversation → "low"
|
|
155
147
|
expect(await getAutoApproveThreshold(undefined, "conversation")).toBe(
|
|
156
|
-
"
|
|
148
|
+
"none",
|
|
157
149
|
);
|
|
158
150
|
|
|
159
151
|
_clearGlobalCacheForTesting();
|
|
160
152
|
|
|
161
|
-
|
|
162
|
-
expect(await getAutoApproveThreshold(undefined, "background")).toBe(
|
|
163
|
-
"none",
|
|
164
|
-
);
|
|
153
|
+
expect(await getAutoApproveThreshold(undefined, "background")).toBe("none");
|
|
165
154
|
|
|
166
155
|
_clearGlobalCacheForTesting();
|
|
167
156
|
|
|
168
|
-
// headless → "none"
|
|
169
157
|
expect(await getAutoApproveThreshold(undefined, "headless")).toBe("none");
|
|
170
158
|
});
|
|
171
159
|
|
|
172
|
-
test("falls back to hardcoded defaults on non-404 conversation error", async () => {
|
|
173
|
-
gatewayGetHandler = (path: string) => {
|
|
174
|
-
if (path.startsWith("/v1/permissions/thresholds/conversations/")) {
|
|
175
|
-
throw new GatewayRequestError("Internal error", 500, "Server error");
|
|
176
|
-
}
|
|
177
|
-
// Should not reach global endpoint
|
|
178
|
-
return {
|
|
179
|
-
interactive: "medium",
|
|
180
|
-
autonomous: "medium",
|
|
181
|
-
};
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
const result = await getAutoApproveThreshold("conv-123", "conversation");
|
|
185
|
-
// Should fall back to hardcoded default for conversation, not global endpoint
|
|
186
|
-
expect(result).toBe("low");
|
|
187
|
-
// Should have only called the conversation endpoint
|
|
188
|
-
expect(gatewayGetCalls).toEqual([
|
|
189
|
-
"/v1/permissions/thresholds/conversations/conv-123",
|
|
190
|
-
]);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
160
|
test("caching: second call within 30s does not re-fetch global", async () => {
|
|
194
161
|
let fetchCount = 0;
|
|
195
|
-
|
|
196
|
-
if (
|
|
162
|
+
ipcHandler = (method) => {
|
|
163
|
+
if (method === "get_global_thresholds") {
|
|
197
164
|
fetchCount++;
|
|
198
|
-
return {
|
|
199
|
-
interactive: "medium",
|
|
200
|
-
autonomous: "low",
|
|
201
|
-
};
|
|
165
|
+
return { interactive: "medium", autonomous: "low" };
|
|
202
166
|
}
|
|
203
|
-
return
|
|
167
|
+
return null;
|
|
204
168
|
};
|
|
205
169
|
|
|
206
170
|
// First call — should fetch
|
|
@@ -226,15 +190,7 @@ describe("getAutoApproveThreshold", () => {
|
|
|
226
190
|
});
|
|
227
191
|
|
|
228
192
|
test("defaults executionContext to conversation when omitted", async () => {
|
|
229
|
-
|
|
230
|
-
if (path === "/v1/permissions/thresholds") {
|
|
231
|
-
return {
|
|
232
|
-
interactive: "medium",
|
|
233
|
-
autonomous: "low",
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
return {};
|
|
237
|
-
};
|
|
193
|
+
withGlobals({ interactive: "medium", autonomous: "low" });
|
|
238
194
|
|
|
239
195
|
// executionContext omitted — should default to "conversation" → interactive
|
|
240
196
|
const result = await getAutoApproveThreshold(undefined, undefined);
|
|
@@ -242,36 +198,20 @@ describe("getAutoApproveThreshold", () => {
|
|
|
242
198
|
});
|
|
243
199
|
|
|
244
200
|
test("skips conversation override when no conversationId", async () => {
|
|
245
|
-
|
|
246
|
-
if (path === "/v1/permissions/thresholds") {
|
|
247
|
-
return {
|
|
248
|
-
interactive: "low",
|
|
249
|
-
autonomous: "none",
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
return {};
|
|
253
|
-
};
|
|
201
|
+
withGlobals({ interactive: "low", autonomous: "none" });
|
|
254
202
|
|
|
255
203
|
const result = await getAutoApproveThreshold(undefined, "conversation");
|
|
256
204
|
expect(result).toBe("low");
|
|
257
205
|
// Should only call global endpoint, not conversation
|
|
258
|
-
expect(
|
|
206
|
+
expect(ipcCallLog).toEqual(["/v1/permissions/thresholds"]);
|
|
259
207
|
});
|
|
260
208
|
|
|
261
209
|
test("skips conversation override for non-conversation contexts", async () => {
|
|
262
|
-
|
|
263
|
-
if (path === "/v1/permissions/thresholds") {
|
|
264
|
-
return {
|
|
265
|
-
interactive: "low",
|
|
266
|
-
autonomous: "medium",
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
return {};
|
|
270
|
-
};
|
|
210
|
+
withGlobals({ interactive: "low", autonomous: "medium" });
|
|
271
211
|
|
|
272
212
|
// Even with a conversationId, background context should not check conversation override
|
|
273
213
|
const result = await getAutoApproveThreshold("conv-123", "background");
|
|
274
214
|
expect(result).toBe("medium");
|
|
275
|
-
expect(
|
|
215
|
+
expect(ipcCallLog).toEqual(["/v1/permissions/thresholds"]);
|
|
276
216
|
});
|
|
277
217
|
});
|
package/bun.lock
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"@vellumai/gateway-client": "file:../packages/gateway-client",
|
|
21
21
|
"@vellumai/service-contracts": "file:../packages/service-contracts",
|
|
22
22
|
"@vellumai/skill-host-contracts": "file:../packages/skill-host-contracts",
|
|
23
|
+
"@vellumai/slack-text": "file:../packages/slack-text",
|
|
23
24
|
"archiver": "7.0.1",
|
|
24
25
|
"commander": "13.1.0",
|
|
25
26
|
"croner": "10.0.1",
|
|
@@ -422,6 +423,8 @@
|
|
|
422
423
|
|
|
423
424
|
"@vellumai/skill-host-contracts": ["@vellumai/skill-host-contracts@file:../packages/skill-host-contracts", { "devDependencies": { "@types/bun": "1.3.10", "typescript": "5.9.3" } }],
|
|
424
425
|
|
|
426
|
+
"@vellumai/slack-text": ["@vellumai/slack-text@file:../packages/slack-text", { "devDependencies": { "@types/bun": "1.3.10", "typescript": "5.9.3" } }],
|
|
427
|
+
|
|
425
428
|
"@vue/compiler-core": ["@vue/compiler-core@3.5.33", "", { "dependencies": { "@babel/parser": "^7.29.2", "@vue/shared": "3.5.33", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-3PZLQwFw4Za3TC8t0FvTy3wI16Kt+pmwcgNZca4Pj9iWL2E72a/gZlpBtAJvEdDMdCxdG/qq0C7PN0bsJuv0Rw=="],
|
|
426
429
|
|
|
427
430
|
"@vue/compiler-dom": ["@vue/compiler-dom@3.5.33", "", { "dependencies": { "@vue/compiler-core": "3.5.33", "@vue/shared": "3.5.33" } }, "sha512-PXq0yrfCLzzL07rbXO4awtXY1Z06LG2eu6Adg3RJFa/j3Cii217XxxLXG22N330gw7GmALCY0Z8RgXEviwgpjA=="],
|
|
@@ -39,11 +39,11 @@ graph TB
|
|
|
39
39
|
Auto-approve thresholds are **gateway-owned** — they live in the gateway's SQLite database and are read by the assistant via IPC (`get_global_thresholds`, `get_conversation_threshold`). Users control thresholds via the **Settings UI** (Permissions & Privacy tab) or the **per-conversation risk tolerance picker**. When the gateway is unreachable, the assistant defaults to `"none"` (Strict) — fail-closed with no local fallback.
|
|
40
40
|
|
|
41
41
|
| `autoApproveUpTo` | Low-risk tools | Medium-risk tools | High-risk tools |
|
|
42
|
-
|
|
|
43
|
-
| `"none"`
|
|
44
|
-
| `"low"` (default)
|
|
45
|
-
| `"medium"`
|
|
46
|
-
| `"high"`
|
|
42
|
+
| ----------------- | -------------- | ----------------- | --------------- |
|
|
43
|
+
| `"none"` | Prompted | Prompted | Prompted |
|
|
44
|
+
| `"low"` (default) | Auto-allowed | Prompted | Prompted |
|
|
45
|
+
| `"medium"` | Auto-allowed | Auto-allowed | Prompted |
|
|
46
|
+
| `"high"` | Auto-allowed | Auto-allowed | Auto-allowed |
|
|
47
47
|
|
|
48
48
|
When set to `"none"`, every tool invocation requires explicit approval. Explicit deny and ask rules always take precedence over the threshold.
|
|
49
49
|
|
|
@@ -262,20 +262,22 @@ The `allowOneTimeSend` config gate (default: `false`) enables a secondary "Send
|
|
|
262
262
|
| ------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
263
263
|
| Secret values | CES credential store or encrypted file store | Encrypted credential values keyed as `credential/{service}/{field}`. Stored via CES RPC (primary), CES HTTP (containerized), or encrypted file store (fallback). |
|
|
264
264
|
| Credential metadata | `~/.vellum/workspace/data/credentials/metadata.json` | Service, field, label, policy (allowedTools, allowedDomains), timestamps |
|
|
265
|
-
| Config | `~/.vellum/workspace/config.*` | `secretDetection` settings: enabled,
|
|
265
|
+
| Config | `~/.vellum/workspace/config.*` | `secretDetection` settings: enabled, blockIngress, allowOneTimeSend |
|
|
266
266
|
|
|
267
267
|
### Key Files
|
|
268
268
|
|
|
269
|
-
| File | Role
|
|
270
|
-
| ---------------------------------------------------- |
|
|
271
|
-
| `assistant/src/tools/credentials/vault.ts` | `credential_store` tool — store, list, delete, prompt actions
|
|
272
|
-
| `assistant/src/security/secure-keys.ts` | Async secure key CRUD via CES and encrypted file store
|
|
273
|
-
| `assistant/src/tools/credentials/metadata-store.ts` | JSON file metadata CRUD for credential records
|
|
274
|
-
| `assistant/src/tools/credentials/broker.ts` | Brokered credential access with policy enforcement and transient send
|
|
275
|
-
| `assistant/src/tools/credentials/policy-validate.ts` | Policy input validation (allowedTools, allowedDomains)
|
|
276
|
-
| `assistant/src/permissions/secret-prompter.ts` | HTTP secret_request/secret_response flow
|
|
277
|
-
| `assistant/src/security/secret-scanner.ts` |
|
|
278
|
-
| `
|
|
269
|
+
| File | Role |
|
|
270
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
271
|
+
| `assistant/src/tools/credentials/vault.ts` | `credential_store` tool — store, list, delete, prompt actions |
|
|
272
|
+
| `assistant/src/security/secure-keys.ts` | Async secure key CRUD via CES and encrypted file store |
|
|
273
|
+
| `assistant/src/tools/credentials/metadata-store.ts` | JSON file metadata CRUD for credential records |
|
|
274
|
+
| `assistant/src/tools/credentials/broker.ts` | Brokered credential access with policy enforcement and transient send |
|
|
275
|
+
| `assistant/src/tools/credentials/policy-validate.ts` | Policy input validation (allowedTools, allowedDomains) |
|
|
276
|
+
| `assistant/src/permissions/secret-prompter.ts` | HTTP secret_request/secret_response flow |
|
|
277
|
+
| `assistant/src/security/secret-scanner.ts` | Prefix + shape-based secret regex detection (used by display-time `redactSecrets`) |
|
|
278
|
+
| `assistant/src/security/secret-ingress.ts` | Prefix-only ingress check on user messages |
|
|
279
|
+
| `assistant/src/util/log-redact.ts` | Pino log serializers — prefix-based redaction for logs |
|
|
280
|
+
| `clients/macos/.../SecretPromptManager.swift` | Floating panel UI for secure credential entry |
|
|
279
281
|
|
|
280
282
|
---
|
|
281
283
|
|
package/knip.json
CHANGED
|
@@ -259,7 +259,6 @@ beforeEach(async () => {
|
|
|
259
259
|
server = new StubServer(socketPath);
|
|
260
260
|
// Standard identity/platform/log stubs every test relies on for
|
|
261
261
|
// `connect()` to succeed.
|
|
262
|
-
server.register("host.identity.getInternalAssistantId", () => "self");
|
|
263
262
|
server.register(
|
|
264
263
|
"host.identity.getAssistantName",
|
|
265
264
|
() => "Example Assistant",
|
|
@@ -298,7 +297,6 @@ async function openClient(
|
|
|
298
297
|
describe("SkillHostClient: bootstrap + sync accessors", () => {
|
|
299
298
|
test("connect populates identity/platform caches", async () => {
|
|
300
299
|
client = await openClient();
|
|
301
|
-
expect(client.identity.internalAssistantId).toBe("self");
|
|
302
300
|
expect(client.identity.getAssistantName()).toBe("Example Assistant");
|
|
303
301
|
expect(client.platform.workspaceDir()).toBe("/tmp/workspace");
|
|
304
302
|
expect(client.platform.vellumRoot()).toBe("/tmp/vellum");
|
|
@@ -310,7 +308,6 @@ describe("SkillHostClient: bootstrap + sync accessors", () => {
|
|
|
310
308
|
socketPath,
|
|
311
309
|
skillId: "test-skill",
|
|
312
310
|
});
|
|
313
|
-
expect(() => client!.identity.internalAssistantId).toThrow(/not connected/);
|
|
314
311
|
expect(() => client!.platform.workspaceDir()).toThrow(/not connected/);
|
|
315
312
|
});
|
|
316
313
|
|
|
@@ -880,11 +877,10 @@ describe("SkillHostClient: connect() retry semantics", () => {
|
|
|
880
877
|
client = new SkillHostClient({ socketPath, skillId: "test-skill" });
|
|
881
878
|
await expect(client.connect()).rejects.toThrow(/boom/);
|
|
882
879
|
// Sync accessors should still throw — the cache wasn't populated.
|
|
883
|
-
expect(() => client!.
|
|
880
|
+
expect(() => client!.platform.workspaceDir()).toThrow(/not connected/);
|
|
884
881
|
// Second connect() must retry prefetch instead of short-circuiting on
|
|
885
882
|
// the still-alive socket.
|
|
886
883
|
await client.connect();
|
|
887
|
-
expect(client.identity.internalAssistantId).toBe("self");
|
|
888
884
|
expect(client.identity.getAssistantName()).toBe("Recovered Assistant");
|
|
889
885
|
expect(nameCalls).toBe(2);
|
|
890
886
|
});
|
|
@@ -28,8 +28,6 @@ import { randomUUID } from "node:crypto";
|
|
|
28
28
|
export interface AssistantEvent<TMessage = unknown> {
|
|
29
29
|
/** Globally unique event identifier (UUID). */
|
|
30
30
|
id: string;
|
|
31
|
-
/** The assistant this event belongs to. */
|
|
32
|
-
assistantId: string;
|
|
33
31
|
/** Resolved conversation id when available. */
|
|
34
32
|
conversationId?: string;
|
|
35
33
|
/** ISO-8601 timestamp of when the event was emitted. */
|
|
@@ -43,18 +41,15 @@ export interface AssistantEvent<TMessage = unknown> {
|
|
|
43
41
|
/**
|
|
44
42
|
* Construct an `AssistantEvent` envelope around a message payload.
|
|
45
43
|
*
|
|
46
|
-
* @param assistantId The logical assistant identifier (e.g. from the daemon or HTTP route).
|
|
47
44
|
* @param message The outbound message payload.
|
|
48
45
|
* @param conversationId Optional conversation id -- pass when known.
|
|
49
46
|
*/
|
|
50
47
|
export function buildAssistantEvent<TMessage>(
|
|
51
|
-
assistantId: string,
|
|
52
48
|
message: TMessage,
|
|
53
49
|
conversationId?: string,
|
|
54
50
|
): AssistantEvent<TMessage> {
|
|
55
51
|
return {
|
|
56
52
|
id: randomUUID(),
|
|
57
|
-
assistantId,
|
|
58
53
|
conversationId,
|
|
59
54
|
emittedAt: new Date().toISOString(),
|
|
60
55
|
message,
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
* ### Sync-method bootstrap
|
|
65
65
|
*
|
|
66
66
|
* The `SkillHost` contract exposes a number of synchronous accessors
|
|
67
|
-
* (`identity.
|
|
67
|
+
* (`identity.getAssistantName()`, `platform.workspaceDir()`,
|
|
68
68
|
* `platform.runtimeMode()`, etc.) that naturally cannot round-trip an async
|
|
69
69
|
* IPC call on every invocation. `connect()` prefetches the stable subset of
|
|
70
70
|
* these values once, caches them locally, and every subsequent sync accessor
|
|
@@ -311,8 +311,8 @@ export class SkillHostClient implements SkillHost {
|
|
|
311
311
|
>();
|
|
312
312
|
|
|
313
313
|
// Prefetched sync state — populated by `connect()`.
|
|
314
|
-
private cachedInternalAssistantId: string | null = null;
|
|
315
314
|
private cachedAssistantName: string | undefined = undefined;
|
|
315
|
+
private cachedPrefetchDone = false;
|
|
316
316
|
private cachedWorkspaceDir: string | null = null;
|
|
317
317
|
private cachedVellumRoot: string | null = null;
|
|
318
318
|
private cachedRuntimeMode: DaemonRuntimeMode | null = null;
|
|
@@ -383,7 +383,7 @@ export class SkillHostClient implements SkillHost {
|
|
|
383
383
|
// the caches are still null and sync accessors would throw — fall
|
|
384
384
|
// through and re-run prefetch over the existing socket.
|
|
385
385
|
const socketAlive = !!this.socket && !this.socket.destroyed;
|
|
386
|
-
const prefetchDone = this.
|
|
386
|
+
const prefetchDone = this.cachedPrefetchDone;
|
|
387
387
|
if (socketAlive && prefetchDone) return;
|
|
388
388
|
|
|
389
389
|
const ensureSocket = socketAlive ? Promise.resolve() : this.doConnect();
|
|
@@ -774,15 +774,14 @@ export class SkillHostClient implements SkillHost {
|
|
|
774
774
|
// ── Internal: bootstrap cache ───────────────────────────────────────────
|
|
775
775
|
|
|
776
776
|
private async prefetchSyncState(): Promise<void> {
|
|
777
|
-
const [
|
|
777
|
+
const [workspaceDir, vellumRootValue, runtimeMode, name] =
|
|
778
778
|
await Promise.all([
|
|
779
|
-
this.call<string>("host.identity.getInternalAssistantId"),
|
|
780
779
|
this.call<string>("host.platform.workspaceDir"),
|
|
781
780
|
this.call<string>("host.platform.vellumRoot"),
|
|
782
781
|
this.call<DaemonRuntimeMode>("host.platform.runtimeMode"),
|
|
783
782
|
this.call<string | null>("host.identity.getAssistantName"),
|
|
784
783
|
]);
|
|
785
|
-
this.
|
|
784
|
+
this.cachedPrefetchDone = true;
|
|
786
785
|
this.cachedWorkspaceDir = workspaceDir;
|
|
787
786
|
this.cachedVellumRoot = vellumRootValue;
|
|
788
787
|
this.cachedRuntimeMode = runtimeMode;
|
|
@@ -844,13 +843,9 @@ export class SkillHostClient implements SkillHost {
|
|
|
844
843
|
const self = this;
|
|
845
844
|
return {
|
|
846
845
|
getAssistantName: () => {
|
|
847
|
-
if (self.
|
|
846
|
+
if (!self.cachedPrefetchDone) throw notConnected();
|
|
848
847
|
return self.cachedAssistantName;
|
|
849
848
|
},
|
|
850
|
-
get internalAssistantId(): string {
|
|
851
|
-
if (self.cachedInternalAssistantId === null) throw notConnected();
|
|
852
|
-
return self.cachedInternalAssistantId;
|
|
853
|
-
},
|
|
854
849
|
};
|
|
855
850
|
}
|
|
856
851
|
|
|
@@ -1000,13 +995,12 @@ export class SkillHostClient implements SkillHost {
|
|
|
1000
995
|
// `buildEvent` is typed as sync on the contract (the daemon
|
|
1001
996
|
// allocates a uuid + timestamp and returns the envelope). A sync
|
|
1002
997
|
// round-trip isn't possible, so the client produces an envelope
|
|
1003
|
-
// locally using the
|
|
1004
|
-
//
|
|
1005
|
-
//
|
|
1006
|
-
if (this.
|
|
998
|
+
// locally using the standard uuid / timestamp sources. This matches
|
|
999
|
+
// the observable shape of the daemon's `buildAssistantEvent` without
|
|
1000
|
+
// the round-trip.
|
|
1001
|
+
if (!this.cachedPrefetchDone) throw notConnected();
|
|
1007
1002
|
return {
|
|
1008
1003
|
id: randomUUID(),
|
|
1009
|
-
assistantId: this.cachedInternalAssistantId,
|
|
1010
1004
|
conversationId,
|
|
1011
1005
|
emittedAt: new Date().toISOString(),
|
|
1012
1006
|
message,
|
|
@@ -94,12 +94,6 @@ export interface IdentityFacet {
|
|
|
94
94
|
* `undefined` when no name has been set.
|
|
95
95
|
*/
|
|
96
96
|
getAssistantName(): string | undefined;
|
|
97
|
-
/**
|
|
98
|
-
* The daemon's internal assistant id (`DAEMON_INTERNAL_ASSISTANT_ID`).
|
|
99
|
-
* Skills use this as the `assistantId` field on events they publish and
|
|
100
|
-
* as the subject of memory writes.
|
|
101
|
-
*/
|
|
102
|
-
readonly internalAssistantId: string;
|
|
103
97
|
}
|
|
104
98
|
|
|
105
99
|
// ---------------------------------------------------------------------------
|
|
@@ -228,9 +222,7 @@ export interface MemoryFacet {
|
|
|
228
222
|
|
|
229
223
|
/** Subscription filter mirroring `AssistantEventFilter` from the daemon's hub. */
|
|
230
224
|
export interface Filter {
|
|
231
|
-
/**
|
|
232
|
-
assistantId: string;
|
|
233
|
-
/** When set, further restrict to this conversation. */
|
|
225
|
+
/** When set, restrict delivery to this conversation. */
|
|
234
226
|
conversationId?: string;
|
|
235
227
|
}
|
|
236
228
|
|