@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
|
@@ -9,9 +9,9 @@ import { statSync } from "node:fs";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
|
|
11
11
|
import { type ChannelId, parseInterfaceId } from "../channels/types.js";
|
|
12
|
-
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
13
12
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
14
13
|
import { getConfig } from "../config/loader.js";
|
|
14
|
+
import { isMemoryV3Live } from "../config/memory-v3-gate.js";
|
|
15
15
|
import type { LLMCallSite, LLMConfig } from "../config/schemas/llm.js";
|
|
16
16
|
import {
|
|
17
17
|
NOW_SCRATCHPAD_STRIP_PREFIXES,
|
|
@@ -62,11 +62,11 @@ import type {
|
|
|
62
62
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
63
63
|
import {
|
|
64
64
|
type ActorTrustContext,
|
|
65
|
-
isUntrustedTrustClass,
|
|
66
65
|
resolveActorTrust,
|
|
67
66
|
type TrustClass,
|
|
68
67
|
} from "../runtime/actor-trust-resolver.js";
|
|
69
68
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
69
|
+
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
70
70
|
import { channelStatusToMemberStatus } from "../runtime/routes/inbound-stages/acl-enforcement.js";
|
|
71
71
|
import { getSubagentManager } from "../subagent/index.js";
|
|
72
72
|
import type { SubagentState } from "../subagent/types.js";
|
|
@@ -125,8 +125,8 @@ export interface InboundActorContext {
|
|
|
125
125
|
actorSenderDisplayName?: string;
|
|
126
126
|
/** Guardian-managed display name from the contact record. */
|
|
127
127
|
actorMemberDisplayName?: string;
|
|
128
|
-
/** Trust classification:
|
|
129
|
-
trustClass:
|
|
128
|
+
/** Trust classification: see TrustClass. */
|
|
129
|
+
trustClass: TrustClass;
|
|
130
130
|
/** Guardian identity for this (assistant, channel) binding. */
|
|
131
131
|
guardianIdentity?: string;
|
|
132
132
|
/** Member status when the actor has a contact record. */
|
|
@@ -916,7 +916,7 @@ function filterSlackConversationRowsForActor(
|
|
|
916
916
|
rows: MessageRow[],
|
|
917
917
|
trustClass: TrustClass | undefined,
|
|
918
918
|
): MessageRow[] {
|
|
919
|
-
if (
|
|
919
|
+
if (resolveCapabilities(trustClass).canAccessMemory) return rows;
|
|
920
920
|
const nonSlackVisibleRows = filterMessagesForUntrustedActor(rows);
|
|
921
921
|
const nonSlackVisibleIds = new Set(nonSlackVisibleRows.map((row) => row.id));
|
|
922
922
|
return rows.filter((row) => {
|
|
@@ -1009,6 +1009,7 @@ function rowToRenderable(row: SlackTranscriptInputRow): RenderableSlackMessage {
|
|
|
1009
1009
|
if (
|
|
1010
1010
|
outer.provenanceTrustClass === "guardian" ||
|
|
1011
1011
|
outer.provenanceTrustClass === "trusted_contact" ||
|
|
1012
|
+
outer.provenanceTrustClass === "unverified_contact" ||
|
|
1012
1013
|
outer.provenanceTrustClass === "unknown"
|
|
1013
1014
|
) {
|
|
1014
1015
|
provenanceTrustClass = outer.provenanceTrustClass;
|
|
@@ -1322,9 +1323,9 @@ export function loadSlackChronologicalContext(
|
|
|
1322
1323
|
options,
|
|
1323
1324
|
);
|
|
1324
1325
|
return assembleSlackChronologicalContext(rows, capabilities, {
|
|
1325
|
-
contextSummary:
|
|
1326
|
-
?
|
|
1327
|
-
:
|
|
1326
|
+
contextSummary: resolveCapabilities(options.trustClass).canAccessMemory
|
|
1327
|
+
? options.contextSummary
|
|
1328
|
+
: null,
|
|
1328
1329
|
});
|
|
1329
1330
|
}
|
|
1330
1331
|
|
|
@@ -1536,8 +1537,8 @@ export interface RuntimeInjectionBlocks {
|
|
|
1536
1537
|
*/
|
|
1537
1538
|
memoryV3InjectedBlock?: string;
|
|
1538
1539
|
/**
|
|
1539
|
-
* True when memory-v3 superseded v2 as this turn's `<memory>` source —
|
|
1540
|
-
* `memory
|
|
1540
|
+
* True when memory-v3 superseded v2 as this turn's `<memory>` source —
|
|
1541
|
+
* `memory.v3.live` is on AND the v3 injector produced a block (possibly
|
|
1541
1542
|
* empty-text on an all-repeat turn), i.e. exactly when assembly stripped
|
|
1542
1543
|
* v2's fresh tail block. The user-prompt-submit hook keys v2's
|
|
1543
1544
|
* `memoryInjectedBlock` metadata persist off this so a stripped v2 block is
|
|
@@ -2177,7 +2178,7 @@ export async function applyRuntimeInjections(
|
|
|
2177
2178
|
// no-op, keeping the v2 path bit-for-bit identical.
|
|
2178
2179
|
let runMessagesForAssembly = stripSpotlightInjections(runMessages);
|
|
2179
2180
|
|
|
2180
|
-
// v2 suppression: when
|
|
2181
|
+
// v2 suppression: when `memory.v3.live` is on AND the v3 injector
|
|
2181
2182
|
// produced a block this turn (possibly empty-text on an all-repeat turn), v3
|
|
2182
2183
|
// owns the `<memory>` layer. v2's `prepareMemory` already prepended its own
|
|
2183
2184
|
// fresh `<memory>` block to the tail user message — strip the TAIL's v2
|
|
@@ -2196,10 +2197,7 @@ export async function applyRuntimeInjections(
|
|
|
2196
2197
|
// (`produce()` → null) leaves v2's block intact — fallback rather than a
|
|
2197
2198
|
// memory-less turn. Idempotent: re-injection sites that already stripped
|
|
2198
2199
|
// see no change. Flag off → bit-for-bit identical to the v2 path.
|
|
2199
|
-
const suppressV2MemoryForV3 =
|
|
2200
|
-
"memory-v3-live",
|
|
2201
|
-
getConfig(),
|
|
2202
|
-
);
|
|
2200
|
+
const suppressV2MemoryForV3 = isMemoryV3Live(getConfig());
|
|
2203
2201
|
const v3ProducedBlock = afterMemory.some((b) => b.id === MEMORY_V3_BLOCK_ID);
|
|
2204
2202
|
const memoryV3Active = suppressV2MemoryForV3 && v3ProducedBlock;
|
|
2205
2203
|
if (memoryV3Active) {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
loadRawConfig,
|
|
8
8
|
saveRawConfig,
|
|
9
9
|
} from "../config/loader.js";
|
|
10
|
+
import { orderProfileKeys } from "../config/profile-order.js";
|
|
10
11
|
import { getConversationOverrideProfile } from "../memory/conversation-crud.js";
|
|
11
12
|
import { getConfiguredProviders } from "../providers/provider-availability.js";
|
|
12
13
|
import { getVisibleProviderCatalog } from "../providers/provider-catalog-visibility.js";
|
|
@@ -130,28 +131,6 @@ function parseModelCommand(trimmed: string): ModelCommandParse | null {
|
|
|
130
131
|
return { kind: "switch", profileName: rest };
|
|
131
132
|
}
|
|
132
133
|
|
|
133
|
-
function orderedProfileNames(
|
|
134
|
-
profiles: Record<
|
|
135
|
-
string,
|
|
136
|
-
{ label?: string; description?: string; status?: "active" | "disabled" }
|
|
137
|
-
>,
|
|
138
|
-
profileOrder: readonly string[] | undefined,
|
|
139
|
-
): string[] {
|
|
140
|
-
const order = profileOrder ?? [];
|
|
141
|
-
const seen = new Set<string>();
|
|
142
|
-
const ordered: string[] = [];
|
|
143
|
-
for (const name of order) {
|
|
144
|
-
if (profiles[name] != null && !seen.has(name)) {
|
|
145
|
-
ordered.push(name);
|
|
146
|
-
seen.add(name);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const tail = Object.keys(profiles)
|
|
150
|
-
.filter((n) => !seen.has(n))
|
|
151
|
-
.sort();
|
|
152
|
-
return [...ordered, ...tail];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
134
|
async function resolveModelCommand(
|
|
156
135
|
parse: ModelCommandParse,
|
|
157
136
|
): Promise<SlashResolution> {
|
|
@@ -160,7 +139,7 @@ async function resolveModelCommand(
|
|
|
160
139
|
string,
|
|
161
140
|
{ label?: string; description?: string; status?: "active" | "disabled" }
|
|
162
141
|
>;
|
|
163
|
-
const profileNames =
|
|
142
|
+
const profileNames = orderProfileKeys(profiles, config.llm.profileOrder);
|
|
164
143
|
const activeProfile = config.llm.activeProfile;
|
|
165
144
|
|
|
166
145
|
if (parse.kind === "list") {
|
|
@@ -291,6 +291,32 @@ export function markSurfaceCompleted(
|
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Complete a `ui_surface` card and notify live clients, addressed only by
|
|
296
|
+
* conversation + surface id.
|
|
297
|
+
*
|
|
298
|
+
* Unlike {@link completeSurfaceFromAction}, this needs no live `Conversation`
|
|
299
|
+
* instance, so it can run from flows that don't own one — projecting a
|
|
300
|
+
* terminal guardian-request status onto its in-app approval card when the
|
|
301
|
+
* request was resolved on another surface (or by the expiry sweep). Persists
|
|
302
|
+
* the completion (reload-safe) and broadcasts `ui_surface_complete` so every
|
|
303
|
+
* connected client of this guardian converges. No-ops when the surface block
|
|
304
|
+
* isn't found in the conversation.
|
|
305
|
+
*/
|
|
306
|
+
export function completeSurfaceAndNotify(
|
|
307
|
+
conversationId: string,
|
|
308
|
+
surfaceId: string,
|
|
309
|
+
summary: string,
|
|
310
|
+
): void {
|
|
311
|
+
markSurfaceCompleted({ conversationId }, surfaceId, summary);
|
|
312
|
+
broadcastMessage({
|
|
313
|
+
type: "ui_surface_complete",
|
|
314
|
+
conversationId,
|
|
315
|
+
surfaceId,
|
|
316
|
+
summary,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
294
320
|
/**
|
|
295
321
|
* Remove a `ui_surface` content block from history so a passively dismissed
|
|
296
322
|
* surface does not survive a reload. The live client drops a dismissed surface
|
|
@@ -26,7 +26,10 @@ import {
|
|
|
26
26
|
ACTIVITY_SKIP_SET,
|
|
27
27
|
injectActivityField,
|
|
28
28
|
} from "../tools/schema-transforms.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
augmentSkillExecuteError,
|
|
31
|
+
resolveSkillExecuteInput,
|
|
32
|
+
} from "../tools/skills/execute.js";
|
|
30
33
|
import { resolveToolInvocationAlias } from "../tools/tool-name-aliases.js";
|
|
31
34
|
import {
|
|
32
35
|
isDiskPressureCleanupToolName,
|
|
@@ -52,7 +55,7 @@ import {
|
|
|
52
55
|
} from "./doordash-steps.js";
|
|
53
56
|
import type { ServerMessage, UiSurfaceShow } from "./message-protocol.js";
|
|
54
57
|
import { runPostExecutionSideEffects } from "./tool-side-effects.js";
|
|
55
|
-
import { resolveTrustClass } from "./trust-context.js";
|
|
58
|
+
import { FALLBACK_TURN_TRUST, resolveTrustClass } from "./trust-context.js";
|
|
56
59
|
|
|
57
60
|
const log = getLogger("conversation-tool-setup");
|
|
58
61
|
|
|
@@ -178,28 +181,32 @@ export function createToolExecutor(
|
|
|
178
181
|
markDoordashStepInProgress(ctx, executionInput);
|
|
179
182
|
}
|
|
180
183
|
|
|
181
|
-
//
|
|
182
|
-
//
|
|
184
|
+
// Per-turn trust snapshot: prefer the snapshot captured at turn start so
|
|
185
|
+
// a concurrent owner meta command (/status, /clean) that mutates the live
|
|
186
|
+
// trustContext cannot elevate the in-flight turn to guardian.
|
|
187
|
+
const turnTrust =
|
|
188
|
+
ctx.currentTurnTrustContext ?? ctx.trustContext ?? FALLBACK_TURN_TRUST;
|
|
189
|
+
|
|
183
190
|
const toolContext: ToolContext = {
|
|
184
191
|
workingDir: ctx.workingDir,
|
|
185
192
|
conversationId: ctx.conversationId,
|
|
186
193
|
assistantId: ctx.assistantId,
|
|
187
194
|
requestId: ctx.currentRequestId,
|
|
188
195
|
taskRunId: ctx.taskRunId,
|
|
189
|
-
trustClass: resolveTrustClass(
|
|
190
|
-
executionChannel:
|
|
191
|
-
sourceActorPrincipalId:
|
|
196
|
+
trustClass: resolveTrustClass(turnTrust),
|
|
197
|
+
executionChannel: turnTrust.sourceChannel,
|
|
198
|
+
sourceActorPrincipalId: turnTrust.guardianPrincipalId,
|
|
192
199
|
callSessionId: ctx.callSessionId,
|
|
193
200
|
triggeredBySurfaceAction:
|
|
194
201
|
ctx.surfaceActionRequestIds?.has(ctx.currentRequestId ?? "") ?? false,
|
|
195
202
|
approvedViaPrompt: ctx.approvedViaPromptThisTurn || undefined,
|
|
196
203
|
batchAuthorizedByTask: false,
|
|
197
|
-
requesterExternalUserId:
|
|
198
|
-
requesterChatId:
|
|
199
|
-
requesterIdentifier:
|
|
200
|
-
requesterDisplayName:
|
|
204
|
+
requesterExternalUserId: turnTrust.requesterExternalUserId,
|
|
205
|
+
requesterChatId: turnTrust.requesterChatId,
|
|
206
|
+
requesterIdentifier: turnTrust.requesterIdentifier,
|
|
207
|
+
requesterDisplayName: turnTrust.requesterDisplayName,
|
|
201
208
|
channelPermissionChannelId:
|
|
202
|
-
|
|
209
|
+
turnTrust.sourceChannel === "slack"
|
|
203
210
|
? getBindingByConversation(ctx.conversationId)?.externalChatId
|
|
204
211
|
: undefined,
|
|
205
212
|
onOutput,
|
|
@@ -211,6 +218,7 @@ export function createToolExecutor(
|
|
|
211
218
|
isPlatformHosted: getIsPlatform(),
|
|
212
219
|
transportInterface: ctx.transportInterface,
|
|
213
220
|
overrideProfile: ctx.currentTurnOverrideProfile,
|
|
221
|
+
invokingCallSite: ctx.currentCallSite ?? "mainAgent",
|
|
214
222
|
attribution: resolveConversationAttribution(ctx),
|
|
215
223
|
onToolLifecycleEvent: handleToolLifecycleEvent,
|
|
216
224
|
sendToClient: (msg) => {
|
|
@@ -320,7 +328,12 @@ export function createToolExecutor(
|
|
|
320
328
|
const innerRejection = rejectNonAllowlistedTool(toolName);
|
|
321
329
|
if (innerRejection) return innerRejection;
|
|
322
330
|
|
|
323
|
-
const
|
|
331
|
+
const rawResult = await executor.execute(
|
|
332
|
+
toolName,
|
|
333
|
+
toolInput,
|
|
334
|
+
toolContext,
|
|
335
|
+
);
|
|
336
|
+
const result = augmentSkillExecuteError(toolName, toolInput, rawResult);
|
|
324
337
|
if (toolContext.approvedViaPrompt) {
|
|
325
338
|
ctx.approvedViaPromptThisTurn = true;
|
|
326
339
|
}
|
|
@@ -371,7 +384,7 @@ export function createProxyApprovalCallback(
|
|
|
371
384
|
* history or explicit preactivation. Without this, their tools are
|
|
372
385
|
* unavailable in fresh conversations until `skill_load` is called.
|
|
373
386
|
*/
|
|
374
|
-
const DEFAULT_PREACTIVATED_SKILL_IDS = ["
|
|
387
|
+
const DEFAULT_PREACTIVATED_SKILL_IDS = ["notifications", "subagent"];
|
|
375
388
|
|
|
376
389
|
/**
|
|
377
390
|
* Subset of Conversation state that the resolveTools callback reads at each
|
|
@@ -80,12 +80,10 @@ import {
|
|
|
80
80
|
} from "../prompts/system-prompt.js";
|
|
81
81
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
82
82
|
import type { Provider } from "../providers/types.js";
|
|
83
|
-
import {
|
|
84
|
-
isUntrustedTrustClass,
|
|
85
|
-
type TrustClass,
|
|
86
|
-
} from "../runtime/actor-trust-resolver.js";
|
|
83
|
+
import { type TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
87
84
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
88
85
|
import type { AuthContext } from "../runtime/auth/types.js";
|
|
86
|
+
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
89
87
|
import type { InteractiveUiResult } from "../runtime/interactive-ui.js";
|
|
90
88
|
import { publishSyncInvalidation } from "../runtime/sync/sync-publisher.js";
|
|
91
89
|
import {
|
|
@@ -107,7 +105,7 @@ import {
|
|
|
107
105
|
runAgentLoopImpl,
|
|
108
106
|
} from "./conversation-agent-loop.js";
|
|
109
107
|
import type { HistoryConversationContext } from "./conversation-history.js";
|
|
110
|
-
import { undo as undoImpl } from "./conversation-history.js";
|
|
108
|
+
import { isToolResultBlock, undo as undoImpl } from "./conversation-history.js";
|
|
111
109
|
import {
|
|
112
110
|
abortConversation,
|
|
113
111
|
disposeConversation,
|
|
@@ -175,6 +173,36 @@ import { TraceEmitter } from "./trace-emitter.js";
|
|
|
175
173
|
|
|
176
174
|
const log = getLogger("conversation");
|
|
177
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Whether a persisted message starts a new conversation turn. A turn is
|
|
178
|
+
* delimited by a "real" user message; a user message whose content is entirely
|
|
179
|
+
* tool_result blocks is a continuation within the current turn, and assistant
|
|
180
|
+
* messages never start one. Mirrors the turn-boundary definition used by
|
|
181
|
+
* `getAssistantMessageIdsInTurn`/`getTurnTimeBounds` and the agent loop's
|
|
182
|
+
* per-turn `turnCount++`, so counting these reconstructs `turnCount` on load.
|
|
183
|
+
*/
|
|
184
|
+
function startsNewTurn(role: string, content: string): boolean {
|
|
185
|
+
if (role !== "user") return false;
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(content);
|
|
188
|
+
if (
|
|
189
|
+
Array.isArray(parsed) &&
|
|
190
|
+
parsed.length > 0 &&
|
|
191
|
+
parsed.every(
|
|
192
|
+
(block: unknown) =>
|
|
193
|
+
block != null &&
|
|
194
|
+
typeof block === "object" &&
|
|
195
|
+
isToolResultBlock(block as Record<string, unknown>),
|
|
196
|
+
)
|
|
197
|
+
) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
// Non-JSON content is a plain user message — a turn boundary.
|
|
202
|
+
}
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
178
206
|
export interface CleanResult {
|
|
179
207
|
previousEstimatedInputTokens: number;
|
|
180
208
|
estimatedInputTokens: number;
|
|
@@ -366,6 +394,13 @@ export class Conversation {
|
|
|
366
394
|
workspaceDir: string,
|
|
367
395
|
) => Pick<WorkspaceGitService, "ensureInitialized">;
|
|
368
396
|
/** @internal */ commitTurnChanges?: typeof commitTurnChanges;
|
|
397
|
+
/**
|
|
398
|
+
* Abort-watchdog timeout (ms) for the agent loop's bounded-unwind backstop.
|
|
399
|
+
* Overridable in tests to fire the watchdog quickly; defaults to the
|
|
400
|
+
* production constant in the agent loop when unset.
|
|
401
|
+
* @internal
|
|
402
|
+
*/
|
|
403
|
+
abortWatchdogMs?: number;
|
|
369
404
|
/**
|
|
370
405
|
* The conversation's immutable creation type (`interactive`, `background`,
|
|
371
406
|
* `scheduled`, …) as stored on the DB row. Cached on load (and set directly
|
|
@@ -824,10 +859,25 @@ export class Conversation {
|
|
|
824
859
|
|
|
825
860
|
async loadFromDb(): Promise<void> {
|
|
826
861
|
const trustClass = this.trustContext?.trustClass;
|
|
862
|
+
const canAccessMemory = resolveCapabilities(trustClass).canAccessMemory;
|
|
827
863
|
const allDbMessages = getMessages(this.conversationId);
|
|
828
|
-
const dbMessages =
|
|
829
|
-
?
|
|
830
|
-
: allDbMessages;
|
|
864
|
+
const dbMessages = canAccessMemory
|
|
865
|
+
? allDbMessages
|
|
866
|
+
: filterMessagesForUntrustedActor(allDbMessages);
|
|
867
|
+
|
|
868
|
+
// Rehydrate the in-memory turn counter from persisted history. `turnCount`
|
|
869
|
+
// is otherwise a fresh-zero field, so a reloaded conversation (eviction,
|
|
870
|
+
// restart, fork) would restart its turn numbering at 0 and the next turn
|
|
871
|
+
// would reuse `turnIndex` 0 — colliding with the conversation's first turn.
|
|
872
|
+
// The memory-v3 selector memoizes per (conversationId, turnIndex) for the
|
|
873
|
+
// life of the daemon process, so a collided turnIndex serves a stale
|
|
874
|
+
// selection and skips retrieval. One turn per real (turn-starting) user
|
|
875
|
+
// message, matching the agent loop's per-turn `turnCount++`. Counted from
|
|
876
|
+
// the full unsliced history so it survives compaction and is independent of
|
|
877
|
+
// the viewer's trust class.
|
|
878
|
+
this.turnCount = allDbMessages.filter((m) =>
|
|
879
|
+
startsNewTurn(m.role, m.content),
|
|
880
|
+
).length;
|
|
831
881
|
|
|
832
882
|
const conv = getConversation(this.conversationId);
|
|
833
883
|
this.conversationType = conv?.conversationType ?? undefined;
|
|
@@ -855,12 +905,12 @@ export class Conversation {
|
|
|
855
905
|
// than exist. Slack chronological context is a separate consumer that
|
|
856
906
|
// applies its own trust filtering downstream, so it reads the raw
|
|
857
907
|
// mirrored count rather than this in-context boundary.
|
|
858
|
-
const inContextCompactedCount =
|
|
859
|
-
?
|
|
860
|
-
:
|
|
861
|
-
const contextSummaryForHistory =
|
|
862
|
-
? null
|
|
863
|
-
:
|
|
908
|
+
const inContextCompactedCount = canAccessMemory
|
|
909
|
+
? Math.min(this.contextCompactedMessageCount, dbMessages.length)
|
|
910
|
+
: 0;
|
|
911
|
+
const contextSummaryForHistory = canAccessMemory
|
|
912
|
+
? this.contextSummary?.trim() || null
|
|
913
|
+
: null;
|
|
864
914
|
|
|
865
915
|
// Every injection-strip event (`/clean` or compaction) updates
|
|
866
916
|
// `historyStrippedAt`. Messages older than this should skip metadata
|
|
@@ -1847,6 +1897,8 @@ export class Conversation {
|
|
|
1847
1897
|
* this value via {@link SubagentManager.spawn}.
|
|
1848
1898
|
*/
|
|
1849
1899
|
overrideProfile?: string;
|
|
1900
|
+
/** Float `overrideProfile` above call-site layers for this run. */
|
|
1901
|
+
forceOverrideProfile?: boolean;
|
|
1850
1902
|
},
|
|
1851
1903
|
): Promise<void> {
|
|
1852
1904
|
const { onEvent, ...rest } = options ?? {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { InterfaceId } from "../channels/types.js";
|
|
2
2
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
3
|
+
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
3
4
|
import type { DiskPressureStatus } from "./disk-pressure-guard.js";
|
|
4
5
|
import type { ConversationType } from "./message-types/shared.js";
|
|
5
6
|
import type { TrustContext } from "./trust-context.js";
|
|
@@ -74,11 +75,11 @@ export function classifyDiskPressureTurnPolicy(
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
const trustClass = metadata.trustContext?.trustClass;
|
|
77
|
-
if (trustClass
|
|
78
|
+
if (resolveCapabilities(trustClass).canActUnderDiskPressureCleanup) {
|
|
78
79
|
return { action: "allow-cleanup-mode", reason: "guardian" };
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
if (trustClass === "trusted_contact") {
|
|
82
|
+
if (trustClass === "trusted_contact" || trustClass === "unverified_contact") {
|
|
82
83
|
return { action: "block", reason: "trusted-contact" };
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -156,6 +157,7 @@ function isExplicitLocalOwnerCleanupTurn(
|
|
|
156
157
|
}
|
|
157
158
|
return (
|
|
158
159
|
metadata.trustContext == null ||
|
|
159
|
-
metadata.trustContext.trustClass
|
|
160
|
+
resolveCapabilities(metadata.trustContext.trustClass)
|
|
161
|
+
.canActUnderDiskPressureCleanup
|
|
160
162
|
);
|
|
161
163
|
}
|
|
@@ -121,7 +121,6 @@ describe("completeA2AInvite", () => {
|
|
|
121
121
|
const invite = findById(created.inviteId!);
|
|
122
122
|
const contact = getContact(invite!.contactId);
|
|
123
123
|
expect(contact!.channels[0]!.address).toBe("upper-case-id-123");
|
|
124
|
-
expect(contact!.channels[0]!.externalUserId).toBe("UPPER-Case-ID-123");
|
|
125
124
|
});
|
|
126
125
|
|
|
127
126
|
test("assistantContactMetadata has correct assistantId and gatewayUrl", () => {
|
|
@@ -120,7 +120,6 @@ describe("redeemA2AInvite", () => {
|
|
|
120
120
|
|
|
121
121
|
const contact = getContact(result.contactId!);
|
|
122
122
|
expect(contact!.channels[0]!.address).toBe("upper-case-sender-id");
|
|
123
|
-
expect(contact!.channels[0]!.externalUserId).toBe("UPPER-Case-SENDER-ID");
|
|
124
123
|
});
|
|
125
124
|
|
|
126
125
|
test("does not make outbound fetch calls", () => {
|
|
@@ -221,7 +221,6 @@ export function completeA2AInvite(params: {
|
|
|
221
221
|
{
|
|
222
222
|
type: "a2a",
|
|
223
223
|
address: params.acceptor.assistantId.toLowerCase(),
|
|
224
|
-
externalUserId: params.acceptor.assistantId,
|
|
225
224
|
status: "active",
|
|
226
225
|
policy: "allow",
|
|
227
226
|
},
|
|
@@ -289,7 +288,6 @@ export function redeemA2AInvite(params: {
|
|
|
289
288
|
{
|
|
290
289
|
type: "a2a",
|
|
291
290
|
address: params.sender.assistantId.toLowerCase(),
|
|
292
|
-
externalUserId: params.sender.assistantId,
|
|
293
291
|
status: "active",
|
|
294
292
|
policy: "allow",
|
|
295
293
|
},
|
|
@@ -204,7 +204,7 @@ export function revokeVerificationForChannel(
|
|
|
204
204
|
// revocation becomes a no-op (wrong reason or skipped entirely).
|
|
205
205
|
const contactResult = findContactChannel({
|
|
206
206
|
channelType: resolvedChannel,
|
|
207
|
-
|
|
207
|
+
address: bindingBeforeRevoke.guardianExternalUserId,
|
|
208
208
|
externalChatId: bindingBeforeRevoke.guardianDeliveryChatId,
|
|
209
209
|
});
|
|
210
210
|
|
|
@@ -331,7 +331,10 @@ export async function verifyTrustedContact(
|
|
|
331
331
|
const sessionResult = createOutboundSession({
|
|
332
332
|
channel: verificationChannel,
|
|
333
333
|
expectedChatId: channel.externalChatId,
|
|
334
|
-
expectedExternalUserId:
|
|
334
|
+
expectedExternalUserId:
|
|
335
|
+
channel.address !== channel.externalChatId
|
|
336
|
+
? channel.address
|
|
337
|
+
: undefined,
|
|
335
338
|
identityBindingStatus: "bound",
|
|
336
339
|
destinationAddress: effectiveDestination,
|
|
337
340
|
verificationPurpose: "trusted_contact",
|
|
@@ -404,22 +407,14 @@ export async function verifyTrustedContact(
|
|
|
404
407
|
|
|
405
408
|
// --- Slack verification ---
|
|
406
409
|
if (verificationChannel === "slack") {
|
|
407
|
-
const slackUserId = channel.
|
|
408
|
-
|
|
409
|
-
const hasIdentityBinding = Boolean(
|
|
410
|
-
channel.externalUserId || channel.externalChatId,
|
|
411
|
-
);
|
|
412
|
-
if (!hasIdentityBinding) {
|
|
413
|
-
return {
|
|
414
|
-
success: false,
|
|
415
|
-
error:
|
|
416
|
-
"Slack verification requires an externalUserId or externalChatId for identity binding",
|
|
417
|
-
};
|
|
418
|
-
}
|
|
410
|
+
const slackUserId = channel.address;
|
|
419
411
|
|
|
420
412
|
const sessionResult = createOutboundSession({
|
|
421
413
|
channel: verificationChannel,
|
|
422
|
-
expectedExternalUserId:
|
|
414
|
+
expectedExternalUserId:
|
|
415
|
+
channel.address !== channel.externalChatId
|
|
416
|
+
? channel.address
|
|
417
|
+
: undefined,
|
|
423
418
|
expectedChatId: channel.externalChatId ?? undefined,
|
|
424
419
|
identityBindingStatus: "bound",
|
|
425
420
|
destinationAddress: slackUserId,
|
|
@@ -560,7 +555,11 @@ export async function handleChannelVerificationSession(
|
|
|
560
555
|
const { to, text, subject, assistantId: aid } = result._pendingEmail;
|
|
561
556
|
deliverVerificationEmail(to, text, subject, aid);
|
|
562
557
|
}
|
|
563
|
-
const {
|
|
558
|
+
const {
|
|
559
|
+
_pendingSlackDm: _,
|
|
560
|
+
_pendingEmail: __,
|
|
561
|
+
...publicResult
|
|
562
|
+
} = result;
|
|
564
563
|
broadcastMessage({
|
|
565
564
|
type: "channel_verification_session_response",
|
|
566
565
|
...publicResult,
|
|
@@ -28,6 +28,9 @@ import { log as _log } from "./shared.js";
|
|
|
28
28
|
|
|
29
29
|
// -- Result type --
|
|
30
30
|
|
|
31
|
+
export const SlackThreadMode = z.enum(["mention_only", "mention_then_thread"]);
|
|
32
|
+
export type SlackThreadMode = z.infer<typeof SlackThreadMode>;
|
|
33
|
+
|
|
31
34
|
export const SlackChannelConfigResultSchema = z.object({
|
|
32
35
|
success: z.boolean(),
|
|
33
36
|
hasBotToken: z.boolean(),
|
|
@@ -39,6 +42,7 @@ export const SlackChannelConfigResultSchema = z.object({
|
|
|
39
42
|
teamUrl: z.string().optional(),
|
|
40
43
|
botUserId: z.string().optional(),
|
|
41
44
|
botUsername: z.string().optional(),
|
|
45
|
+
threadMode: SlackThreadMode,
|
|
42
46
|
error: z.string().optional(),
|
|
43
47
|
warning: z.string().optional(),
|
|
44
48
|
});
|
|
@@ -129,6 +133,8 @@ export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult>
|
|
|
129
133
|
ensureUserTokenInjectionTemplates();
|
|
130
134
|
}
|
|
131
135
|
|
|
136
|
+
const { threadMode } = getConfig().slack;
|
|
137
|
+
|
|
132
138
|
return {
|
|
133
139
|
success: true,
|
|
134
140
|
hasBotToken,
|
|
@@ -140,6 +146,7 @@ export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult>
|
|
|
140
146
|
...(teamUrl ? { teamUrl } : {}),
|
|
141
147
|
...(botUserId ? { botUserId } : {}),
|
|
142
148
|
...(botUsername ? { botUsername } : {}),
|
|
149
|
+
threadMode,
|
|
143
150
|
};
|
|
144
151
|
}
|
|
145
152
|
|
|
@@ -166,6 +173,7 @@ async function currentErrorSnapshot(
|
|
|
166
173
|
!!(errConn && errConn.status === "active") &&
|
|
167
174
|
errHasBotToken &&
|
|
168
175
|
errHasAppToken,
|
|
176
|
+
threadMode: getConfig().slack.threadMode,
|
|
169
177
|
error,
|
|
170
178
|
};
|
|
171
179
|
}
|
|
@@ -429,6 +437,7 @@ export async function setSlackChannelConfig(
|
|
|
429
437
|
hasUserToken,
|
|
430
438
|
connected: hasBotToken && hasAppToken,
|
|
431
439
|
...metadata,
|
|
440
|
+
threadMode: getConfig().slack.threadMode,
|
|
432
441
|
...(warning ? { warning } : {}),
|
|
433
442
|
};
|
|
434
443
|
}
|
|
@@ -440,9 +449,8 @@ export async function setSlackChannelConfig(
|
|
|
440
449
|
* the bot_token, app_token, oauth_connection row, and Slack config metadata
|
|
441
450
|
* untouched so the Socket Mode connection stays up. Returns a
|
|
442
451
|
* `SlackChannelConfigResult` reflecting the remaining state. A `not-found`
|
|
443
|
-
* delete outcome is reported as a failure to match the
|
|
444
|
-
*
|
|
445
|
-
* detection).
|
|
452
|
+
* delete outcome is reported as a failure to match the credential delete
|
|
453
|
+
* semantics (callers and automation rely on missing-credential detection).
|
|
446
454
|
*/
|
|
447
455
|
export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
448
456
|
const result = await deleteSecureKeyAsync(
|
|
@@ -467,6 +475,7 @@ export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
|
467
475
|
hasUserToken,
|
|
468
476
|
connected:
|
|
469
477
|
!!(conn && conn.status === "active") && hasBotToken && hasAppToken,
|
|
478
|
+
threadMode: getConfig().slack.threadMode,
|
|
470
479
|
error:
|
|
471
480
|
result === "not-found"
|
|
472
481
|
? "Slack user token not found in secure storage"
|
|
@@ -498,6 +507,7 @@ export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
|
498
507
|
...(teamUrl ? { teamUrl } : {}),
|
|
499
508
|
...(botUserId ? { botUserId } : {}),
|
|
500
509
|
...(botUsername ? { botUsername } : {}),
|
|
510
|
+
threadMode: getConfig().slack.threadMode,
|
|
501
511
|
};
|
|
502
512
|
}
|
|
503
513
|
|
|
@@ -531,6 +541,7 @@ export async function clearSlackChannelConfig(): Promise<SlackChannelConfigResul
|
|
|
531
541
|
hasUserToken,
|
|
532
542
|
connected:
|
|
533
543
|
!!(conn && conn.status === "active") && hasBotToken && hasAppToken,
|
|
544
|
+
threadMode: getConfig().slack.threadMode,
|
|
534
545
|
error: "Failed to delete Slack channel credentials from secure storage",
|
|
535
546
|
};
|
|
536
547
|
}
|
|
@@ -557,5 +568,13 @@ export async function clearSlackChannelConfig(): Promise<SlackChannelConfigResul
|
|
|
557
568
|
hasAppToken: false,
|
|
558
569
|
hasUserToken: false,
|
|
559
570
|
connected: false,
|
|
571
|
+
threadMode: "mention_only",
|
|
560
572
|
};
|
|
561
573
|
}
|
|
574
|
+
|
|
575
|
+
export function patchSlackChannelConfig(threadMode: SlackThreadMode): void {
|
|
576
|
+
const raw = loadRawConfig();
|
|
577
|
+
setNestedValue(raw, "slack.threadMode", threadMode);
|
|
578
|
+
saveRawConfig(raw);
|
|
579
|
+
invalidateConfigCache();
|
|
580
|
+
}
|