@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240206.7c2bca6
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 +36 -37
- package/bun.lock +3 -0
- package/docs/workflows.md +12 -7
- package/eslint-rules/cli-no-daemon-internals.js +12 -0
- package/node_modules/@slack/types/LICENSE +23 -0
- package/node_modules/@slack/types/README.md +32 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
- package/node_modules/@slack/types/dist/calls.d.ts +26 -0
- package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/calls.js +6 -0
- package/node_modules/@slack/types/dist/calls.js.map +1 -0
- package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
- package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/chunk.js +3 -0
- package/node_modules/@slack/types/dist/chunk.js.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
- package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
- package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/dialog.js +3 -0
- package/node_modules/@slack/types/dist/dialog.js.map +1 -0
- package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
- package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/app.js +3 -0
- package/node_modules/@slack/types/dist/events/app.js.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.js +3 -0
- package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
- package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/call.js +3 -0
- package/node_modules/@slack/types/dist/events/call.js.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.js +3 -0
- package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.js +3 -0
- package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
- package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
- package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/email.js +3 -0
- package/node_modules/@slack/types/dist/events/email.js.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.js +3 -0
- package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
- package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/file.js +4 -0
- package/node_modules/@slack/types/dist/events/file.js.map +1 -0
- package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
- package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/function.js +3 -0
- package/node_modules/@slack/types/dist/events/function.js.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
- package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
- package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/group.js +3 -0
- package/node_modules/@slack/types/dist/events/group.js.map +1 -0
- package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
- package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/im.js +3 -0
- package/node_modules/@slack/types/dist/events/im.js.map +1 -0
- package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/index.js +43 -0
- package/node_modules/@slack/types/dist/events/index.js.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.js +3 -0
- package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
- package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
- package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
- package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/member.js +3 -0
- package/node_modules/@slack/types/dist/events/member.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
- package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message.js +3 -0
- package/node_modules/@slack/types/dist/events/message.js.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.js +3 -0
- package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.js +3 -0
- package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
- package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/star.js +3 -0
- package/node_modules/@slack/types/dist/events/star.js.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.js +3 -0
- package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
- package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
- package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/team.js +3 -0
- package/node_modules/@slack/types/dist/events/team.js.map +1 -0
- package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/token.js +3 -0
- package/node_modules/@slack/types/dist/events/token.js.map +1 -0
- package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
- package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/user.js +3 -0
- package/node_modules/@slack/types/dist/events/user.js.map +1 -0
- package/node_modules/@slack/types/dist/index.d.ts +12 -0
- package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/index.js +28 -0
- package/node_modules/@slack/types/dist/index.js.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.js +3 -0
- package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.js +27 -0
- package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/views.d.ts +71 -0
- package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/views.js +3 -0
- package/node_modules/@slack/types/dist/views.js.map +1 -0
- package/node_modules/@slack/types/package.json +47 -0
- package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +96 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +28 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +95 -0
- package/openapi.yaml +458 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- package/scripts/test.sh +36 -15
- package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
- package/src/__tests__/activation-early-marking.test.ts +1 -1
- package/src/__tests__/actor-token-service.test.ts +39 -17
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
- package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
- package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/anthropic-provider.test.ts +210 -9
- package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
- package/src/__tests__/app-source-watcher.test.ts +30 -10
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
- package/src/__tests__/approval-primitive.test.ts +1 -1
- package/src/__tests__/approval-routes-http.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +155 -0
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
- package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
- package/src/__tests__/attachments-store.test.ts +1 -1
- package/src/__tests__/audit-log-rotation.test.ts +50 -54
- package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
- package/src/__tests__/background-shell-bash.test.ts +4 -1
- package/src/__tests__/background-shell-host-bash.test.ts +17 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-controller.test.ts +20 -1
- package/src/__tests__/call-conversation-messages.test.ts +1 -1
- package/src/__tests__/call-domain.test.ts +1 -1
- package/src/__tests__/call-pointer-messages.test.ts +3 -4
- package/src/__tests__/call-recovery.test.ts +1 -1
- package/src/__tests__/call-routes-http.test.ts +1 -1
- package/src/__tests__/call-store.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/canonical-guardian-store.test.ts +24 -1
- package/src/__tests__/card-surface-data.test.ts +60 -0
- package/src/__tests__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +291 -641
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
- package/src/__tests__/channel-retry-sweep.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compaction-trail-store.test.ts +6 -5
- package/src/__tests__/compaction.benchmark.test.ts +0 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +188 -52
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
- package/src/__tests__/contact-store-user-file.test.ts +2 -2
- package/src/__tests__/contacts-relay-reads.test.ts +409 -0
- package/src/__tests__/contacts-tools.test.ts +4 -4
- package/src/__tests__/contacts-write.test.ts +1 -2
- package/src/__tests__/context-search-conversations-source.test.ts +1 -1
- package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop.test.ts +7 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -5
- package/src/__tests__/conversation-attention-store.test.ts +1 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
- package/src/__tests__/conversation-clear-safety.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +10 -8
- package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
- package/src/__tests__/conversation-fork-route.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +117 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -3
- package/src/__tests__/conversation-process-callsite.test.ts +6 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +95 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +12 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +12 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-starter-routes.test.ts +5 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +4 -4
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +352 -0
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-wipe.test.ts +9 -8
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/db-acp-history.test.ts +2 -2
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
- package/src/__tests__/db-migration-rollback.test.ts +129 -39
- package/src/__tests__/db-proxy-transaction.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
- package/src/__tests__/db-test-helpers.ts +36 -19
- package/src/__tests__/delete-propagation.test.ts +1 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +28 -8
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/dm-backfill.test.ts +1 -1
- package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
- package/src/__tests__/dynamic-page-surface.test.ts +0 -94
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +93 -5
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -1
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/followup-tools.test.ts +1 -1
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-action-sweep.test.ts +9 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +76 -11
- package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +96 -2
- package/src/__tests__/guardian-outbound-http.test.ts +20 -12
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/guardian-routing-state.test.ts +1 -2
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +2 -2
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +6 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +92 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- package/src/__tests__/http-user-message-parity.test.ts +165 -8
- package/src/__tests__/image-recovery-hook.test.ts +1 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
- package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
- package/src/__tests__/inference-profile-reaper.test.ts +1 -1
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +11 -6
- package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
- package/src/__tests__/invite-redemption-service.test.ts +244 -43
- package/src/__tests__/invite-routes-http.test.ts +35 -186
- package/src/__tests__/invite-service-ipc.test.ts +287 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
- package/src/__tests__/list-messages-attachments.test.ts +42 -1
- package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
- package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
- package/src/__tests__/list-messages-page-latest.test.ts +1 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-context-route-provider.test.ts +69 -4
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
- package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
- package/src/__tests__/llm-resolver.test.ts +205 -5
- package/src/__tests__/llm-usage-store.test.ts +65 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
- package/src/__tests__/memory-recall-log-store.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +375 -0
- package/src/__tests__/non-member-access-request.test.ts +190 -19
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +4 -0
- package/src/__tests__/notification-guardian-path.test.ts +20 -1
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +1 -1
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image.test.ts +1 -1
- package/src/__tests__/persona-resolver.test.ts +39 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
- package/src/__tests__/plugin-bootstrap.test.ts +78 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
- package/src/__tests__/provider-usage-tracking.test.ts +1 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/relay-server.test.ts +1026 -73
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -1
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-retry.test.ts +1 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +1 -1
- package/src/__tests__/schedule-store.test.ts +1 -1
- package/src/__tests__/schedule-tools.test.ts +1 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +1 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
- package/src/__tests__/scheduler-wake.test.ts +2 -1
- package/src/__tests__/scoped-approval-grants.test.ts +1 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
- package/src/__tests__/secret-ingress-http.test.ts +12 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +31 -9
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +40 -1
- package/src/__tests__/settings-routes.test.ts +11 -10
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +48 -5
- package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +44 -13
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
- package/src/__tests__/subagent-tools.test.ts +1 -31
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/task-management-tools.test.ts +1 -1
- package/src/__tests__/task-memory-cleanup.test.ts +9 -6
- package/src/__tests__/task-scheduler.test.ts +1 -1
- package/src/__tests__/thread-backfill.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +37 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
- package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
- package/src/__tests__/turn-events-store.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +98 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
- package/src/__tests__/usage-routes.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +34 -29
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +134 -36
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-git-service.test.ts +114 -1
- package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
- package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
- package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
- package/src/a2a/__tests__/task-store.test.ts +1 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
- package/src/acp/__tests__/session-manager.test.ts +72 -1
- package/src/acp/index.ts +10 -0
- package/src/acp/session-manager.ts +35 -0
- package/src/agent/loop.ts +45 -27
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/ui-surface-show.ts +8 -3
- package/src/api/index.ts +7 -6
- package/src/api/responses/conversation-message.ts +4 -0
- package/src/api/responses/llm-request-log-entry.ts +25 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +33 -0
- package/src/approvals/AGENTS.md +1 -2
- package/src/approvals/guardian-decision-primitive.ts +13 -210
- package/src/approvals/guardian-request-resolvers.ts +104 -58
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +349 -65
- package/src/calls/guardian-dispatch.ts +10 -8
- package/src/calls/inbound-trust-reader.ts +56 -0
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-server.ts +231 -72
- package/src/calls/relay-setup-router.ts +57 -13
- package/src/calls/relay-verification.ts +7 -7
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +13 -3
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +6 -24
- package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
- package/src/cli/commands/db/__tests__/status.test.ts +7 -3
- package/src/cli/commands/db/status.ts +212 -33
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
- package/src/cli/commands/memory/index.ts +4 -0
- package/src/cli/commands/memory/memory-retrospective.ts +129 -0
- package/src/cli/commands/memory/memory-v3.ts +176 -4
- package/src/cli/commands/memory/worker.ts +175 -0
- package/src/cli/commands/plugins.ts +343 -14
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
- package/src/cli/lib/install-from-github.ts +47 -6
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/toggle-plugin.ts +146 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
- package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
- package/src/config/bundled-skills/contacts/SKILL.md +7 -12
- package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +4 -3
- package/src/config/call-site-defaults.ts +11 -2
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/llm-resolver.ts +151 -14
- package/src/config/loader.ts +36 -5
- package/src/config/profile-dispatchability.ts +11 -0
- 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/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +17 -3
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +32 -0
- package/src/config/seed-inference-profiles.ts +147 -50
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/contact-store.ts +21 -0
- package/src/contacts/contacts-write.ts +3 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-status.ts +9 -0
- package/src/credential-health/credential-health-service.ts +1 -5
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/app-source-watcher.ts +31 -18
- package/src/daemon/assistant-attachments.ts +94 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
- package/src/daemon/conversation-agent-loop.ts +18 -36
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-surfaces.ts +273 -18
- package/src/daemon/conversation-tool-setup.ts +24 -64
- package/src/daemon/conversation.ts +145 -52
- package/src/daemon/event-loop-watchdog.test.ts +85 -0
- package/src/daemon/event-loop-watchdog.ts +133 -0
- package/src/daemon/external-plugins-bootstrap.ts +26 -80
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
- package/src/daemon/handlers/config-channels.ts +41 -27
- package/src/daemon/handlers/conversations.ts +84 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +44 -5
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/inbox.ts +0 -6
- package/src/daemon/message-types/messages.ts +0 -4
- package/src/daemon/message-types/surfaces.ts +12 -11
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +7 -5
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-conversation-ops.ts +70 -0
- package/src/daemon/workspace-tools-watcher.ts +7 -3
- package/src/documents/document-comments-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
- package/src/heartbeat/heartbeat-service.ts +3 -4
- package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +10 -2
- package/src/ipc/gateway-client.ts +2 -1
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
- package/src/ipc/routes/invite-ipc-routes.ts +66 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
- package/src/memory/__tests__/activation-session-store.test.ts +1 -1
- package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
- package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
- package/src/memory/__tests__/conversation-queries.test.ts +1 -1
- package/src/memory/__tests__/db-async-query.test.ts +1 -1
- package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
- package/src/memory/__tests__/db-maintenance.test.ts +28 -36
- package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
- package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
- package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
- package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
- package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/table-relocation.test.ts +129 -0
- package/src/memory/conversation-crud.ts +461 -152
- package/src/memory/db-async-query.ts +89 -5
- package/src/memory/db-connection.ts +101 -18
- package/src/memory/db-init.ts +409 -234
- package/src/memory/db-maintenance.ts +43 -38
- package/src/memory/db-singleton.ts +45 -19
- package/src/memory/embedding-gemini.test.ts +3 -1
- package/src/memory/embedding-gemini.ts +18 -2
- package/src/memory/fork-message-copy.ts +170 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
- package/src/memory/graph/bootstrap.test.ts +6 -3
- package/src/memory/graph/retriever.test.ts +12 -12
- package/src/memory/graph/store.test.ts +15 -25
- package/src/memory/graph/store.ts +23 -14
- package/src/memory/graph/tool-handlers.ts +34 -5
- package/src/memory/graph/tools.ts +5 -2
- package/src/memory/indexer.ts +21 -9
- package/src/memory/job-handlers/cleanup.ts +10 -3
- package/src/memory/job-handlers/embedding.test.ts +4 -4
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
- package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
- package/src/memory/jobs-store.ts +36 -24
- package/src/memory/llm-request-log-store.ts +51 -19
- package/src/memory/llm-usage-store.ts +79 -21
- package/src/memory/memory-retrospective-job.ts +27 -19
- package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
- package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
- package/src/memory/migrations/104-core-indexes.ts +1 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
- package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +241 -219
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
- package/src/memory/migrations/141-rename-verification-table.ts +45 -48
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
- package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
- package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
- package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
- package/src/memory/migrations/157-invite-contact-id.ts +73 -76
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
- package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
- package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
- package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
- package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
- package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
- package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
- package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +135 -68
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
- package/src/memory/migrations/217-conversation-host-access.ts +13 -18
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
- package/src/memory/migrations/230-acp-session-history.ts +23 -28
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
- package/src/memory/migrations/232-activation-state.ts +11 -16
- package/src/memory/migrations/233-document-conversations.ts +20 -25
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
- package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
- package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
- package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
- package/src/memory/migrations/242-message-bookmarks.ts +17 -22
- package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
- package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
- package/src/memory/migrations/251-a2a-tasks.ts +27 -32
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
- package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
- package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
- package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
- package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
- package/src/memory/migrations/270-schedule-description.ts +7 -12
- package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
- package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
- package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
- package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
- package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
- package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
- package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
- package/src/memory/migrations/helpers/relocation.ts +227 -0
- package/src/memory/migrations/registry.ts +63 -0
- package/src/memory/migrations/run-migrations.ts +187 -16
- package/src/memory/migrations/schema-introspection.ts +14 -0
- package/src/memory/migrations/validate-migration-state.ts +50 -145
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/raw-query.ts +47 -2
- package/src/memory/skill-loaded-events-store.test.ts +1 -1
- package/src/memory/task-memory-cleanup.ts +62 -41
- package/src/memory/tool-executed-events-store.test.ts +1 -1
- package/src/memory/turn-trace-store.test.ts +1 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
- package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
- package/src/memory/v3-eval/eval-packets.ts +197 -12
- package/src/memory/v3-eval/eval-tally.ts +234 -0
- package/src/memory/worker-control.ts +118 -0
- package/src/memory/worker-process.ts +72 -0
- package/src/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +13 -0
- package/src/messaging/providers/index.ts +1 -1
- package/src/messaging/providers/slack/send.test.ts +87 -39
- package/src/messaging/providers/slack/send.ts +84 -105
- package/src/notifications/README.md +9 -5
- package/src/notifications/__tests__/broadcaster.test.ts +16 -8
- package/src/notifications/__tests__/connected-channels.test.ts +114 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
- package/src/notifications/adapters/slack.ts +12 -10
- package/src/notifications/approval-card-builder.ts +81 -20
- package/src/notifications/approval-card-data.ts +8 -5
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/canonical-delivery-recorder.ts +7 -5
- package/src/notifications/conversation-candidates.ts +24 -59
- package/src/notifications/copy-composer.ts +48 -68
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +68 -24
- package/src/notifications/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +68 -15
- package/src/notifications/trusted-contact-payloads.ts +70 -0
- package/src/oauth/byo-connection.test.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +174 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +39 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +9 -4
- package/src/plugin-api/model-profiles.test.ts +123 -0
- package/src/plugin-api/model-profiles.ts +5 -1
- package/src/plugin-api/vision-support.test.ts +173 -0
- package/src/plugin-api/vision-support.ts +113 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +46 -0
- package/src/plugins/defaults/advisor/consult.ts +18 -1
- package/src/plugins/defaults/advisor/tools/advisor.ts +4 -0
- package/src/plugins/defaults/compaction/window-manager.ts +45 -64
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +441 -0
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +57 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +61 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +108 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +56 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +27 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +134 -5
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +246 -19
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
- package/src/plugins/external-plugin-loader.ts +47 -6
- package/src/plugins/mtime-cache.ts +772 -0
- package/src/plugins/pipeline.ts +7 -2
- package/src/plugins/registry.ts +16 -5
- package/src/plugins/user-loader.ts +22 -76
- package/src/prompts/persona-resolver.ts +29 -11
- package/src/prompts/system-prompt.ts +1 -1
- package/src/prompts/templates/system-sections.ts +4 -4
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/anthropic/client.ts +285 -185
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +6 -1
- package/src/providers/model-catalog.ts +53 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +10 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +64 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +670 -0
- package/src/runtime/access-request-helper.ts +19 -39
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/anchored-guardian.test.ts +156 -0
- package/src/runtime/anchored-guardian.ts +135 -0
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/channel-verification-service.ts +24 -0
- package/src/runtime/guardian-decision-types.ts +3 -22
- package/src/runtime/guardian-vellum-migration.ts +66 -7
- package/src/runtime/http-server.ts +1 -15
- package/src/runtime/invite-redemption-service.ts +155 -6
- package/src/runtime/invite-service.ts +113 -62
- package/src/runtime/local-actor-identity.ts +76 -11
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +163 -0
- package/src/runtime/routes/acp-routes-list.test.ts +4 -0
- package/src/runtime/routes/acp-routes.test.ts +5 -6
- package/src/runtime/routes/attachment-routes.ts +21 -17
- package/src/runtime/routes/browser-routes.ts +19 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
- package/src/runtime/routes/channel-verification-routes.ts +13 -2
- package/src/runtime/routes/contact-routes.ts +275 -164
- package/src/runtime/routes/conversation-query-routes.ts +15 -5
- package/src/runtime/routes/conversation-routes.ts +80 -66
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/inbound-message-handler.ts +21 -16
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +376 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +86 -64
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/llm-context-normalization.ts +71 -0
- package/src/runtime/routes/log-export-routes.ts +2 -2
- package/src/runtime/routes/mcp-auth-routes.ts +38 -15
- package/src/runtime/routes/memory-eval-routes.ts +92 -0
- package/src/runtime/routes/memory-item-routes.test.ts +12 -11
- package/src/runtime/routes/migration-routes.ts +51 -40
- package/src/runtime/routes/plugins-routes.ts +164 -8
- package/src/runtime/routes/schedule-routes.ts +1 -0
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +39 -51
- package/src/runtime/routes/usage-routes.ts +3 -0
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/slack-block-formatting.ts +46 -48
- package/src/runtime/trust-verdict-consumer.ts +210 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/manager.ts +9 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +89 -52
- package/src/tools/ask-question/ask-question-tool.ts +27 -73
- package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
- package/src/tools/browser/browser-execution.ts +16 -4
- package/src/tools/document/document-comment-tool.test.ts +1 -1
- package/src/tools/executor.ts +15 -3
- package/src/tools/host-terminal/host-shell.ts +28 -9
- package/src/tools/memory/register.test.ts +32 -0
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +4 -10
- package/src/tools/terminal/shell.ts +16 -5
- package/src/tools/types.ts +1 -0
- package/src/tools/ui-surface/definitions.ts +0 -43
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/log-redact.ts +2 -4
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -0
- package/src/util/platform.ts +5 -0
- package/src/watcher/providers/gmail.ts +7 -2
- package/src/workflows/engine-integration.test.ts +1 -1
- package/src/workflows/engine.test.ts +1 -1
- package/src/workflows/engine.ts +22 -0
- package/src/workflows/fanout-load.test.ts +1 -1
- package/src/workflows/journal-store.test.ts +1 -1
- package/src/workflows/leaf-runner.test.ts +40 -1
- package/src/workflows/leaf-runner.ts +26 -1
- package/src/workspace/git-service.ts +144 -29
- package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
- package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/migrations/runner.ts +32 -2
- package/src/__tests__/access-request-decision.test.ts +0 -375
- package/src/__tests__/guardian-grant-minting.test.ts +0 -607
- package/src/__tests__/plugin-source-watcher.test.ts +0 -302
- package/src/api/events/turn-profile-auto-routed.ts +0 -28
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
- package/src/daemon/plugin-source-watcher.ts +0 -278
- package/src/daemon/switch-inference-profile-tool.ts +0 -62
- package/src/memory/guardian-approvals.ts +0 -361
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
- package/src/memory/migrations/038-actor-token-records.ts +0 -45
- package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
- package/src/memory/migrations/103-complex-migrations.ts +0 -23
- package/src/memory/migrations/113-late-migrations.ts +0 -30
- package/src/memory/migrations/index.ts +0 -301
- package/src/runtime/routes/access-request-decision.ts +0 -297
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
- package/src/runtime/routes/channel-guardian-routes.ts +0 -19
- package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
|
@@ -55,13 +55,42 @@ mock.module("../runtime/gateway-client.js", () => ({
|
|
|
55
55
|
},
|
|
56
56
|
}));
|
|
57
57
|
|
|
58
|
+
// Guardian identity resolves via the gateway delivery reader, not the local
|
|
59
|
+
// contacts DB. Seed it to mirror the createGuardianBinding calls below.
|
|
60
|
+
interface GatewayGuardian {
|
|
61
|
+
channelType: string;
|
|
62
|
+
contactId: string;
|
|
63
|
+
principalId?: string | null;
|
|
64
|
+
displayName?: string | null;
|
|
65
|
+
address: string;
|
|
66
|
+
externalChatId?: string | null;
|
|
67
|
+
status: string;
|
|
68
|
+
verifiedAt?: number | null;
|
|
69
|
+
}
|
|
70
|
+
let gatewayGuardians: GatewayGuardian[] = [];
|
|
71
|
+
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
72
|
+
getGuardianDelivery: async () => gatewayGuardians,
|
|
73
|
+
guardianForChannel: (list: GatewayGuardian[], channelType: string) =>
|
|
74
|
+
list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
function seedGatewayGuardian(
|
|
78
|
+
g: Partial<GatewayGuardian> & { channelType: string; address: string },
|
|
79
|
+
): void {
|
|
80
|
+
gatewayGuardians.push({
|
|
81
|
+
contactId: `c-${g.channelType}`,
|
|
82
|
+
status: "active",
|
|
83
|
+
...g,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
58
87
|
import { getDb } from "../memory/db-connection.js";
|
|
59
88
|
import { initializeDb } from "../memory/db-init.js";
|
|
60
89
|
import { findActiveSession } from "../runtime/channel-verification-service.js";
|
|
61
90
|
import { handleChannelInbound } from "./helpers/channel-test-adapter.js";
|
|
62
91
|
import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
|
|
63
92
|
|
|
64
|
-
initializeDb();
|
|
93
|
+
await initializeDb();
|
|
65
94
|
|
|
66
95
|
// ---------------------------------------------------------------------------
|
|
67
96
|
// Helpers
|
|
@@ -71,7 +100,6 @@ const TEST_BEARER_TOKEN = "test-token";
|
|
|
71
100
|
|
|
72
101
|
function resetState(): void {
|
|
73
102
|
const db = getDb();
|
|
74
|
-
db.run("DELETE FROM channel_guardian_approval_requests");
|
|
75
103
|
db.run("DELETE FROM channel_verification_sessions");
|
|
76
104
|
db.run("DELETE FROM channel_guardian_rate_limits");
|
|
77
105
|
db.run("DELETE FROM channel_inbound_events");
|
|
@@ -81,7 +109,16 @@ function resetState(): void {
|
|
|
81
109
|
db.run("DELETE FROM canonical_guardian_deliveries");
|
|
82
110
|
db.run("DELETE FROM contact_channels");
|
|
83
111
|
db.run("DELETE FROM contacts");
|
|
84
|
-
|
|
112
|
+
gatewayGuardians = [];
|
|
113
|
+
// Seed the vellum guardian binding (gateway does this at startup in
|
|
114
|
+
// production). The gateway list is the source of truth for guardian
|
|
115
|
+
// resolution; the DB write mirrors it for any local INFO reads.
|
|
116
|
+
seedGatewayGuardian({
|
|
117
|
+
channelType: "vellum",
|
|
118
|
+
address: "guardian-principal",
|
|
119
|
+
principalId: "guardian-principal",
|
|
120
|
+
displayName: "guardian-principal",
|
|
121
|
+
});
|
|
85
122
|
createGuardianBinding({
|
|
86
123
|
channel: "vellum",
|
|
87
124
|
guardianExternalUserId: "guardian-principal",
|
|
@@ -163,7 +200,14 @@ describe("Slack inbound trusted contact verification", () => {
|
|
|
163
200
|
});
|
|
164
201
|
|
|
165
202
|
test("guardian is notified of the access attempt alongside verification", async () => {
|
|
166
|
-
// Set up a guardian binding so the notification can target it
|
|
203
|
+
// Set up a guardian binding so the notification can target it. The gateway
|
|
204
|
+
// list resolves guardian identity; the DB write mirrors it.
|
|
205
|
+
seedGatewayGuardian({
|
|
206
|
+
channelType: "slack",
|
|
207
|
+
address: "U_GUARDIAN",
|
|
208
|
+
externalChatId: "D_GUARDIAN_DM",
|
|
209
|
+
principalId: "guardian-principal",
|
|
210
|
+
});
|
|
167
211
|
createGuardianBinding({
|
|
168
212
|
channel: "slack",
|
|
169
213
|
guardianExternalUserId: "U_GUARDIAN",
|
|
@@ -256,5 +300,4 @@ describe("Slack inbound trusted contact verification", () => {
|
|
|
256
300
|
|
|
257
301
|
// No Slack DM was sent
|
|
258
302
|
});
|
|
259
|
-
|
|
260
303
|
});
|
|
@@ -50,8 +50,11 @@ mock.module("../runtime/auth/token-service.js", () => ({}));
|
|
|
50
50
|
// Slack client stubs (not exercised in these tests, but required on import)
|
|
51
51
|
mock.module("../messaging/providers/slack/client.js", () => ({}));
|
|
52
52
|
|
|
53
|
-
// Gmail client stubs
|
|
54
|
-
|
|
53
|
+
// Gmail client stubs. Re-export GMAIL_REQUIRED_SCOPES so the adapter's
|
|
54
|
+
// `requiredScopes` is populated (and the forwarding assertion below is real).
|
|
55
|
+
mock.module("../messaging/providers/gmail/client.js", () => ({
|
|
56
|
+
GMAIL_REQUIRED_SCOPES: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
57
|
+
}));
|
|
55
58
|
mock.module("../messaging/providers/gmail/people-client.js", () => ({}));
|
|
56
59
|
|
|
57
60
|
// Telegram client stubs
|
|
@@ -244,8 +247,16 @@ describe("Slack messaging token resolution", () => {
|
|
|
244
247
|
|
|
245
248
|
const result = await getProviderConnection(gmailMessagingProvider);
|
|
246
249
|
expect(result).toBe(oauthConn);
|
|
250
|
+
// Gmail forwards its requiredScopes so a narrowly-scoped (e.g.
|
|
251
|
+
// Calendar-only) Google connection is rejected at resolution time
|
|
252
|
+
// instead of 403-ing on the first Gmail API call. Asserted as a concrete
|
|
253
|
+
// value (not the provider property) so removing the forwarding fails.
|
|
254
|
+
expect(gmailMessagingProvider.requiredScopes).toEqual([
|
|
255
|
+
"https://www.googleapis.com/auth/gmail.readonly",
|
|
256
|
+
]);
|
|
247
257
|
expect(resolveOAuthConnectionMock).toHaveBeenCalledWith("google", {
|
|
248
258
|
account: undefined,
|
|
259
|
+
requiredScopes: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
249
260
|
});
|
|
250
261
|
});
|
|
251
262
|
});
|
|
@@ -37,7 +37,7 @@ import { initializeDb } from "../memory/db-init.js";
|
|
|
37
37
|
import { routeGuardianReply } from "../runtime/guardian-reply-router.js";
|
|
38
38
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
39
39
|
|
|
40
|
-
initializeDb();
|
|
40
|
+
await initializeDb();
|
|
41
41
|
|
|
42
42
|
// ---------------------------------------------------------------------------
|
|
43
43
|
// Constants & helpers
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: the SSE subscribe path must resolve the actor principal from the
|
|
3
|
+
* SAME guardian source as the send/result routes.
|
|
4
|
+
*
|
|
5
|
+
* The send/result routes resolve the actor principal via the async,
|
|
6
|
+
* gateway-first `findLocalGuardianPrincipalId`. The SSE eager-subscribe path
|
|
7
|
+
* cannot await and uses the sync `findLocalGuardianPrincipalIdFromStore`. When
|
|
8
|
+
* the gateway binding is canonical but the local contact row is stale/missing
|
|
9
|
+
* (after a guardian reset or gateway-owned binding update), the sync path must
|
|
10
|
+
* still land on the gateway principal — otherwise the event hub registers the
|
|
11
|
+
* SSE client under a DIFFERENT principal than the turn/result paths use, and
|
|
12
|
+
* targeted result submissions 403.
|
|
13
|
+
*
|
|
14
|
+
* These tests pin the invariant by priming the gateway-delivery cache with a
|
|
15
|
+
* principal that differs from the stale local store and asserting both
|
|
16
|
+
* resolvers agree; and that a cold cache falls back to the local store.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
20
|
+
|
|
21
|
+
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
22
|
+
|
|
23
|
+
// ── Controllable IPC mock (drives the gateway-delivery cache) ────────────────
|
|
24
|
+
|
|
25
|
+
let ipcGuardians: GuardianDelivery[] = [];
|
|
26
|
+
|
|
27
|
+
mock.module("../ipc/gateway-client.js", () => ({
|
|
28
|
+
ipcCall: async () => ({ guardians: ipcGuardians }),
|
|
29
|
+
ipcCallPersistent: async () => undefined,
|
|
30
|
+
resetPersistentClient: () => {},
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
// ── Local store mock (the stale fallback source) ─────────────────────────────
|
|
34
|
+
|
|
35
|
+
let storePrincipalId: string | undefined;
|
|
36
|
+
|
|
37
|
+
mock.module("../contacts/contact-store.js", () => ({
|
|
38
|
+
findGuardianForChannel: (channelType: string) =>
|
|
39
|
+
storePrincipalId && channelType === "vellum"
|
|
40
|
+
? { contact: { principalId: storePrincipalId }, channel: {} }
|
|
41
|
+
: null,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
import {
|
|
45
|
+
__resetGuardianDeliveryCacheForTest,
|
|
46
|
+
getGuardianDelivery,
|
|
47
|
+
} from "../contacts/guardian-delivery-reader.js";
|
|
48
|
+
import {
|
|
49
|
+
findLocalGuardianPrincipalId,
|
|
50
|
+
findLocalGuardianPrincipalIdFromStore,
|
|
51
|
+
} from "../runtime/local-actor-identity.js";
|
|
52
|
+
|
|
53
|
+
const gatewayVellumGuardian: GuardianDelivery = {
|
|
54
|
+
channelType: "vellum",
|
|
55
|
+
contactId: "contact-gw",
|
|
56
|
+
principalId: "guardian-from-gateway",
|
|
57
|
+
address: "vellum:self",
|
|
58
|
+
status: "active",
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
describe("SSE actor principal resolves from the same guardian source as send/result routes", () => {
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
__resetGuardianDeliveryCacheForTest();
|
|
64
|
+
ipcGuardians = [];
|
|
65
|
+
storePrincipalId = undefined;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("warm gateway cache: sync (SSE) and async (send/result) resolve the SAME principal despite a stale local store", async () => {
|
|
69
|
+
// Gateway binding is canonical; local store row is stale (different id).
|
|
70
|
+
ipcGuardians = [gatewayVellumGuardian];
|
|
71
|
+
storePrincipalId = "guardian-stale-local";
|
|
72
|
+
|
|
73
|
+
// Prime the cache the way the async hot paths do.
|
|
74
|
+
const asyncPrincipalId = await findLocalGuardianPrincipalId();
|
|
75
|
+
expect(asyncPrincipalId).toBe("guardian-from-gateway");
|
|
76
|
+
|
|
77
|
+
// SSE's sync resolver reads the same cached gateway snapshot, NOT the
|
|
78
|
+
// stale store — so the principals match and host-proxy targeting works.
|
|
79
|
+
expect(findLocalGuardianPrincipalIdFromStore()).toBe(asyncPrincipalId);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("cold cache: sync resolver falls back to the local store as before", () => {
|
|
83
|
+
// Nothing primed the cache; only the local store has a binding.
|
|
84
|
+
storePrincipalId = "guardian-stale-local";
|
|
85
|
+
|
|
86
|
+
expect(findLocalGuardianPrincipalIdFromStore()).toBe("guardian-stale-local");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("cold cache with no store binding: sync resolver returns undefined", () => {
|
|
90
|
+
expect(findLocalGuardianPrincipalIdFromStore()).toBeUndefined();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("warm gateway cache primes via the vellum-filtered read the async path uses", async () => {
|
|
94
|
+
ipcGuardians = [gatewayVellumGuardian];
|
|
95
|
+
|
|
96
|
+
// The async path filters by channelType vellum; the sync peek must read
|
|
97
|
+
// the same cache key, not the unfiltered "ALL" entry.
|
|
98
|
+
await getGuardianDelivery({ channelTypes: ["vellum"] });
|
|
99
|
+
|
|
100
|
+
expect(findLocalGuardianPrincipalIdFromStore()).toBe("guardian-from-gateway");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enqueue-steer contract: when a chat message is enqueued while an
|
|
3
|
+
* `ask_question` prompt is open for the same conversation, the user has chosen
|
|
4
|
+
* to move on rather than answer it. `steerOnEnqueuedMessageIfQuestionParked`
|
|
5
|
+
* steers to that message — aborting the parked turn (which settles the open
|
|
6
|
+
* question via its turn-abort signal) and draining the message — instead of
|
|
7
|
+
* stranding it behind a prompt no one will answer.
|
|
8
|
+
*
|
|
9
|
+
* Only `kind: "question"` interactions trigger the steer; pending confirmations
|
|
10
|
+
* are handled separately by the enqueue path's auto-deny.
|
|
11
|
+
*/
|
|
12
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
13
|
+
|
|
14
|
+
import type { Conversation } from "../daemon/conversation.js";
|
|
15
|
+
import {
|
|
16
|
+
deleteConversation,
|
|
17
|
+
setConversation,
|
|
18
|
+
} from "../daemon/conversation-registry.js";
|
|
19
|
+
import {
|
|
20
|
+
steerOnEnqueuedMessageIfQuestionParked,
|
|
21
|
+
supersedePendingInteractionsOnEnqueue,
|
|
22
|
+
} from "../daemon/handlers/conversations.js";
|
|
23
|
+
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
24
|
+
|
|
25
|
+
interface ParkedTurn {
|
|
26
|
+
abortCount: () => number;
|
|
27
|
+
fake: { pendingSteerRepair: boolean };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Register a fake conversation whose in-flight turn is parked. The fake exposes
|
|
32
|
+
* just the surface `steerToMessage` touches: a processing flag, a queue whose
|
|
33
|
+
* head can be promoted, an abort controller that records aborts, and the
|
|
34
|
+
* confirmation-deny hook.
|
|
35
|
+
*/
|
|
36
|
+
function registerParkedTurn(id: string): ParkedTurn {
|
|
37
|
+
let abortCount = 0;
|
|
38
|
+
const fake = {
|
|
39
|
+
isProcessing: () => true,
|
|
40
|
+
queue: {
|
|
41
|
+
promoteToHead: (requestId: string) => ({ requestId }),
|
|
42
|
+
},
|
|
43
|
+
pendingSteerRepair: false,
|
|
44
|
+
abortController: {
|
|
45
|
+
abort: () => {
|
|
46
|
+
abortCount += 1;
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
hasAnyPendingConfirmation: () => false,
|
|
50
|
+
denyAllPendingConfirmations: () => {},
|
|
51
|
+
};
|
|
52
|
+
setConversation(id, fake as unknown as Conversation);
|
|
53
|
+
return { abortCount: () => abortCount, fake };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const registeredRequestIds: string[] = [];
|
|
57
|
+
function registerInteraction(
|
|
58
|
+
conversationId: string,
|
|
59
|
+
kind: "question" | "confirmation",
|
|
60
|
+
): void {
|
|
61
|
+
const requestId = `pending-${kind}-${conversationId}`;
|
|
62
|
+
pendingInteractions.register(requestId, { conversationId, kind });
|
|
63
|
+
registeredRequestIds.push(requestId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const QUESTION_CONV = "steer-enqueue-question";
|
|
67
|
+
const CONFIRMATION_CONV = "steer-enqueue-confirmation";
|
|
68
|
+
const NONE_CONV = "steer-enqueue-none";
|
|
69
|
+
|
|
70
|
+
describe("steerOnEnqueuedMessageIfQuestionParked", () => {
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
for (const id of registeredRequestIds) {
|
|
73
|
+
pendingInteractions.resolve(id, "cancelled");
|
|
74
|
+
}
|
|
75
|
+
registeredRequestIds.length = 0;
|
|
76
|
+
deleteConversation(QUESTION_CONV);
|
|
77
|
+
deleteConversation(CONFIRMATION_CONV);
|
|
78
|
+
deleteConversation(NONE_CONV);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("steers to the enqueued message when an ask_question is parked", () => {
|
|
82
|
+
const conv = registerParkedTurn(QUESTION_CONV);
|
|
83
|
+
registerInteraction(QUESTION_CONV, "question");
|
|
84
|
+
|
|
85
|
+
const steered = steerOnEnqueuedMessageIfQuestionParked(
|
|
86
|
+
QUESTION_CONV,
|
|
87
|
+
"msg-1",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// The parked turn is aborted (which settles the open question) and marked
|
|
91
|
+
// for tool-result repair so the drain path can pick up the new message.
|
|
92
|
+
expect(steered).toBe(true);
|
|
93
|
+
expect(conv.abortCount()).toBe(1);
|
|
94
|
+
expect(conv.fake.pendingSteerRepair).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("steers for a parked question even when a confirmation is also pending", () => {
|
|
98
|
+
// A single model response can open an ask_question and a confirmation
|
|
99
|
+
// concurrently (tools run via Promise.all), so both interactions can be
|
|
100
|
+
// registered at once. The steer must still fire for the question — the
|
|
101
|
+
// enqueue path runs it before the confirmation auto-deny clears entries.
|
|
102
|
+
const conv = registerParkedTurn(QUESTION_CONV);
|
|
103
|
+
registerInteraction(QUESTION_CONV, "confirmation");
|
|
104
|
+
registerInteraction(QUESTION_CONV, "question");
|
|
105
|
+
|
|
106
|
+
const steered = steerOnEnqueuedMessageIfQuestionParked(
|
|
107
|
+
QUESTION_CONV,
|
|
108
|
+
"msg-1",
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(steered).toBe(true);
|
|
112
|
+
expect(conv.abortCount()).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("does not steer for a pending confirmation (not a question)", () => {
|
|
116
|
+
const conv = registerParkedTurn(CONFIRMATION_CONV);
|
|
117
|
+
registerInteraction(CONFIRMATION_CONV, "confirmation");
|
|
118
|
+
|
|
119
|
+
const steered = steerOnEnqueuedMessageIfQuestionParked(
|
|
120
|
+
CONFIRMATION_CONV,
|
|
121
|
+
"msg-1",
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(steered).toBe(false);
|
|
125
|
+
expect(conv.abortCount()).toBe(0);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("does not steer when no prompt is parked", () => {
|
|
129
|
+
const conv = registerParkedTurn(NONE_CONV);
|
|
130
|
+
|
|
131
|
+
const steered = steerOnEnqueuedMessageIfQuestionParked(NONE_CONV, "msg-1");
|
|
132
|
+
|
|
133
|
+
expect(steered).toBe(false);
|
|
134
|
+
expect(conv.abortCount()).toBe(0);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("supersedePendingInteractionsOnEnqueue steers a parked question", () => {
|
|
138
|
+
// The centralized routine is invoked by both the HTTP send handler and the
|
|
139
|
+
// CLI signal path. With no pending confirmation it steers a parked question
|
|
140
|
+
// — the behavior the CLI signal path previously lacked.
|
|
141
|
+
const conv = registerParkedTurn(QUESTION_CONV);
|
|
142
|
+
registerInteraction(QUESTION_CONV, "question");
|
|
143
|
+
|
|
144
|
+
supersedePendingInteractionsOnEnqueue(QUESTION_CONV, "msg-1");
|
|
145
|
+
|
|
146
|
+
expect(conv.abortCount()).toBe(1);
|
|
147
|
+
expect(conv.fake.pendingSteerRepair).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe("removeByConversation preserves question interactions", () => {
|
|
152
|
+
// The enqueue path's confirmation auto-deny calls removeByConversation before
|
|
153
|
+
// the steer runs. Questions must survive it — they are settled instead by the
|
|
154
|
+
// steer's turn abort — or, when an ask_question and a confirmation are pending
|
|
155
|
+
// concurrently, the queued message would strand behind a question whose entry
|
|
156
|
+
// was cleared (and whose Promise was never settled) before the steer fired.
|
|
157
|
+
const CONV = "remove-by-conv-preserve-question";
|
|
158
|
+
const ids: string[] = [];
|
|
159
|
+
function register(kind: "question" | "confirmation"): void {
|
|
160
|
+
const requestId = `rbc-${kind}`;
|
|
161
|
+
pendingInteractions.register(requestId, { conversationId: CONV, kind });
|
|
162
|
+
ids.push(requestId);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
afterEach(() => {
|
|
166
|
+
for (const id of ids) pendingInteractions.resolve(id, "cancelled");
|
|
167
|
+
ids.length = 0;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("removes confirmations but leaves questions registered", () => {
|
|
171
|
+
register("confirmation");
|
|
172
|
+
register("question");
|
|
173
|
+
|
|
174
|
+
pendingInteractions.removeByConversation(CONV);
|
|
175
|
+
|
|
176
|
+
const remaining = pendingInteractions
|
|
177
|
+
.getByConversation(CONV)
|
|
178
|
+
.map((interaction) => interaction.kind);
|
|
179
|
+
expect(remaining).toEqual(["question"]);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -13,6 +13,15 @@ let mockRecentContacts: ContactWithChannels[] = [];
|
|
|
13
13
|
let mockFindContactByAddressThrows = false;
|
|
14
14
|
let mockListContactsThrows = false;
|
|
15
15
|
|
|
16
|
+
// Guardian deliveries returned by the mocked gateway reader. resolveGuardianName
|
|
17
|
+
// is mocked to echo mockGuardianName, so the displayName here is captured below.
|
|
18
|
+
let mockGuardianDelivery: Array<{
|
|
19
|
+
channelType: string;
|
|
20
|
+
status: string;
|
|
21
|
+
displayName: string | null;
|
|
22
|
+
}> | null = null;
|
|
23
|
+
let lastGuardianDisplayNameSeen: string | null | undefined;
|
|
24
|
+
|
|
16
25
|
const logWarnFn = mock(() => {});
|
|
17
26
|
|
|
18
27
|
// ---------------------------------------------------------------------------
|
|
@@ -25,7 +34,10 @@ mock.module("../daemon/identity-helpers.js", () => ({
|
|
|
25
34
|
|
|
26
35
|
mock.module("../prompts/user-reference.js", () => ({
|
|
27
36
|
DEFAULT_USER_REFERENCE: "my human",
|
|
28
|
-
resolveGuardianName: () =>
|
|
37
|
+
resolveGuardianName: (displayName?: string | null) => {
|
|
38
|
+
lastGuardianDisplayNameSeen = displayName;
|
|
39
|
+
return mockGuardianName;
|
|
40
|
+
},
|
|
29
41
|
}));
|
|
30
42
|
|
|
31
43
|
mock.module("../contacts/contact-store.js", () => ({
|
|
@@ -35,8 +47,6 @@ mock.module("../contacts/contact-store.js", () => ({
|
|
|
35
47
|
}
|
|
36
48
|
return mockTargetContact;
|
|
37
49
|
},
|
|
38
|
-
findGuardianForChannel: () => null,
|
|
39
|
-
listGuardianChannels: () => null,
|
|
40
50
|
listContacts: (_limit?: number) => {
|
|
41
51
|
if (mockListContactsThrows) {
|
|
42
52
|
throw new Error("DB error: listContacts");
|
|
@@ -45,6 +55,15 @@ mock.module("../contacts/contact-store.js", () => ({
|
|
|
45
55
|
},
|
|
46
56
|
}));
|
|
47
57
|
|
|
58
|
+
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
59
|
+
getGuardianDelivery: async () => mockGuardianDelivery,
|
|
60
|
+
guardianForChannel: (
|
|
61
|
+
list: Array<{ channelType: string; status: string }>,
|
|
62
|
+
channelType: string,
|
|
63
|
+
) => list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
64
|
+
anyGuardian: (list: unknown[]) => list[0],
|
|
65
|
+
}));
|
|
66
|
+
|
|
48
67
|
// Bun's mock.module for "../util/logger.js" doesn't intercept the transitive
|
|
49
68
|
// import in stt-hints.ts due to a Bun limitation. Mocking pino at the package
|
|
50
69
|
// level works because getLogger uses a Proxy that lazily creates a pino child
|
|
@@ -319,10 +338,22 @@ describe("resolveCallHints", () => {
|
|
|
319
338
|
mockRecentContacts = [];
|
|
320
339
|
mockFindContactByAddressThrows = false;
|
|
321
340
|
mockListContactsThrows = false;
|
|
341
|
+
mockGuardianDelivery = null;
|
|
342
|
+
lastGuardianDisplayNameSeen = undefined;
|
|
322
343
|
logWarnFn.mockClear();
|
|
323
344
|
});
|
|
324
345
|
|
|
325
|
-
test("
|
|
346
|
+
test("guardian displayName for hints comes from the gateway binding", async () => {
|
|
347
|
+
mockGuardianDelivery = [
|
|
348
|
+
{ channelType: "phone", status: "active", displayName: "GatewayGuardian" },
|
|
349
|
+
];
|
|
350
|
+
|
|
351
|
+
await resolveCallHints(null, []);
|
|
352
|
+
|
|
353
|
+
expect(lastGuardianDisplayNameSeen).toBe("GatewayGuardian");
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("happy path wires all sources correctly", async () => {
|
|
326
357
|
mockTargetContact = makeContact("Alice");
|
|
327
358
|
mockRecentContacts = [makeContact("Bob"), makeContact("Charlie")];
|
|
328
359
|
|
|
@@ -335,7 +366,7 @@ describe("resolveCallHints", () => {
|
|
|
335
366
|
inviteGuardianName: "Eve",
|
|
336
367
|
};
|
|
337
368
|
|
|
338
|
-
const result = resolveCallHints(session, ["StaticHint"]);
|
|
369
|
+
const result = await resolveCallHints(session, ["StaticHint"]);
|
|
339
370
|
const parts = result.split(",");
|
|
340
371
|
|
|
341
372
|
expect(parts).toContain("StaticHint");
|
|
@@ -351,7 +382,7 @@ describe("resolveCallHints", () => {
|
|
|
351
382
|
expect(logWarnFn).not.toHaveBeenCalled();
|
|
352
383
|
});
|
|
353
384
|
|
|
354
|
-
test("findContactByAddress failure is caught and logged without throwing", () => {
|
|
385
|
+
test("findContactByAddress failure is caught and logged without throwing", async () => {
|
|
355
386
|
mockFindContactByAddressThrows = true;
|
|
356
387
|
mockRecentContacts = [makeContact("Bob")];
|
|
357
388
|
|
|
@@ -365,7 +396,7 @@ describe("resolveCallHints", () => {
|
|
|
365
396
|
};
|
|
366
397
|
|
|
367
398
|
// Should not throw
|
|
368
|
-
const result = resolveCallHints(session, []);
|
|
399
|
+
const result = await resolveCallHints(session, []);
|
|
369
400
|
const parts = result.split(",");
|
|
370
401
|
|
|
371
402
|
// Target contact should be absent (lookup failed)
|
|
@@ -376,7 +407,7 @@ describe("resolveCallHints", () => {
|
|
|
376
407
|
expect(logWarnFn).toHaveBeenCalled();
|
|
377
408
|
});
|
|
378
409
|
|
|
379
|
-
test("listContacts failure is caught and logged without throwing", () => {
|
|
410
|
+
test("listContacts failure is caught and logged without throwing", async () => {
|
|
380
411
|
mockListContactsThrows = true;
|
|
381
412
|
mockTargetContact = makeContact("Alice");
|
|
382
413
|
|
|
@@ -390,7 +421,7 @@ describe("resolveCallHints", () => {
|
|
|
390
421
|
};
|
|
391
422
|
|
|
392
423
|
// Should not throw
|
|
393
|
-
const result = resolveCallHints(session, []);
|
|
424
|
+
const result = await resolveCallHints(session, []);
|
|
394
425
|
const parts = result.split(",");
|
|
395
426
|
|
|
396
427
|
// Recent contacts should be absent (listing failed)
|
|
@@ -401,7 +432,7 @@ describe("resolveCallHints", () => {
|
|
|
401
432
|
expect(logWarnFn).toHaveBeenCalled();
|
|
402
433
|
});
|
|
403
434
|
|
|
404
|
-
test("inbound call resolves caller contact from fromNumber", () => {
|
|
435
|
+
test("inbound call resolves caller contact from fromNumber", async () => {
|
|
405
436
|
mockTargetContact = makeContact("Alice");
|
|
406
437
|
mockRecentContacts = [makeContact("Bob")];
|
|
407
438
|
|
|
@@ -414,7 +445,7 @@ describe("resolveCallHints", () => {
|
|
|
414
445
|
inviteGuardianName: null,
|
|
415
446
|
};
|
|
416
447
|
|
|
417
|
-
const result = resolveCallHints(session, []);
|
|
448
|
+
const result = await resolveCallHints(session, []);
|
|
418
449
|
const parts = result.split(",");
|
|
419
450
|
|
|
420
451
|
// For inbound, the contact found via fromNumber should appear as caller, not target
|
|
@@ -425,10 +456,10 @@ describe("resolveCallHints", () => {
|
|
|
425
456
|
expect(logWarnFn).not.toHaveBeenCalled();
|
|
426
457
|
});
|
|
427
458
|
|
|
428
|
-
test("null session produces hints from assistant name, guardian name, and recent contacts", () => {
|
|
459
|
+
test("null session produces hints from assistant name, guardian name, and recent contacts", async () => {
|
|
429
460
|
mockRecentContacts = [makeContact("RecentOne"), makeContact("RecentTwo")];
|
|
430
461
|
|
|
431
|
-
const result = resolveCallHints(null, ["Static"]);
|
|
462
|
+
const result = await resolveCallHints(null, ["Static"]);
|
|
432
463
|
const parts = result.split(",");
|
|
433
464
|
|
|
434
465
|
expect(parts).toContain("Static");
|
|
@@ -130,6 +130,33 @@ describe("parseSubagentMessages", () => {
|
|
|
130
130
|
expect(result.objective).toBe("Research vampire lore");
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
test("emits toolUseId and raw input on tool_use, toolUseId on tool_result", () => {
|
|
134
|
+
const messages = [
|
|
135
|
+
msg("user", [{ type: "text", text: "Do something" }]),
|
|
136
|
+
msg("assistant", [
|
|
137
|
+
{
|
|
138
|
+
type: "tool_use",
|
|
139
|
+
id: "t-abc",
|
|
140
|
+
name: "bash",
|
|
141
|
+
input: { command: "ls -la" },
|
|
142
|
+
},
|
|
143
|
+
]),
|
|
144
|
+
msg("user", [
|
|
145
|
+
{ type: "tool_result", tool_use_id: "t-abc", content: "total 0" },
|
|
146
|
+
]),
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
const result = parseSubagentMessages("sub-1", messages);
|
|
150
|
+
const toolUse = result.events.find((e) => e.type === "tool_use");
|
|
151
|
+
expect(toolUse).toBeDefined();
|
|
152
|
+
expect(toolUse!.toolUseId).toBe("t-abc");
|
|
153
|
+
expect(toolUse!.input).toEqual({ command: "ls -la" });
|
|
154
|
+
|
|
155
|
+
const toolResult = result.events.find((e) => e.type === "tool_result");
|
|
156
|
+
expect(toolResult).toBeDefined();
|
|
157
|
+
expect(toolResult!.toolUseId).toBe("t-abc");
|
|
158
|
+
});
|
|
159
|
+
|
|
133
160
|
test("includes messageId on text events from assistant messages", () => {
|
|
134
161
|
const messages = [
|
|
135
162
|
msg("user", [{ type: "text", text: "Do something" }]),
|
|
@@ -326,3 +326,68 @@ describe("SubagentManager terminal disposal", () => {
|
|
|
326
326
|
asInternals(manager).stopSweep();
|
|
327
327
|
});
|
|
328
328
|
});
|
|
329
|
+
|
|
330
|
+
describe("SubagentManager.abort usage", () => {
|
|
331
|
+
test("emits the conversation's latest usage on abort, not zeros", () => {
|
|
332
|
+
const manager = new SubagentManager();
|
|
333
|
+
const sent: ServerMessage[] = [];
|
|
334
|
+
const sender = (msg: ServerMessage) => sent.push(msg);
|
|
335
|
+
|
|
336
|
+
const subagentId = "sa-abort-usage";
|
|
337
|
+
// state.usage starts at {0,0,0}; the live (fake) conversation has accrued
|
|
338
|
+
// usage (makeFakeConversation → {100, 50, 0.005}). Wire `sender` as the
|
|
339
|
+
// stored parent sender so `setStatus` routes the terminal event through it.
|
|
340
|
+
injectFakeSubagent(manager, subagentId, makeState(subagentId), sender);
|
|
341
|
+
|
|
342
|
+
const aborted = manager.abort(subagentId, sender, undefined, {
|
|
343
|
+
suppressNotification: true,
|
|
344
|
+
});
|
|
345
|
+
expect(aborted).toBe(true);
|
|
346
|
+
|
|
347
|
+
const statusMsg = sent.find(
|
|
348
|
+
(m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
|
|
349
|
+
m.type === "subagent_status_changed",
|
|
350
|
+
);
|
|
351
|
+
expect(statusMsg).toBeDefined();
|
|
352
|
+
expect(statusMsg!.status).toBe("aborted");
|
|
353
|
+
// The emitted usage is the conversation's accrued total — NOT the {0,0,0}
|
|
354
|
+
// init — so the client doesn't flush the token panel to zero on stop.
|
|
355
|
+
expect(statusMsg!.usage).toEqual({
|
|
356
|
+
inputTokens: 100,
|
|
357
|
+
outputTokens: 50,
|
|
358
|
+
estimatedCost: 0.005,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
asInternals(manager).stopSweep();
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("keeps the last-known state.usage when the conversation was already released", () => {
|
|
365
|
+
const manager = new SubagentManager();
|
|
366
|
+
const sent: ServerMessage[] = [];
|
|
367
|
+
const sender = (msg: ServerMessage) => sent.push(msg);
|
|
368
|
+
|
|
369
|
+
const subagentId = "sa-abort-no-conv";
|
|
370
|
+
// No live conversation (released), but state carries a last-known usage —
|
|
371
|
+
// the abort must surface that, not overwrite it.
|
|
372
|
+
const state = makeState(subagentId, {
|
|
373
|
+
usage: { inputTokens: 320, outputTokens: 80, estimatedCost: 0.004 },
|
|
374
|
+
});
|
|
375
|
+
injectFakeSubagent(manager, subagentId, state, sender, null);
|
|
376
|
+
|
|
377
|
+
manager.abort(subagentId, sender, undefined, {
|
|
378
|
+
suppressNotification: true,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const statusMsg = sent.find(
|
|
382
|
+
(m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
|
|
383
|
+
m.type === "subagent_status_changed",
|
|
384
|
+
);
|
|
385
|
+
expect(statusMsg!.usage).toEqual({
|
|
386
|
+
inputTokens: 320,
|
|
387
|
+
outputTokens: 80,
|
|
388
|
+
estimatedCost: 0.004,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
asInternals(manager).stopSweep();
|
|
392
|
+
});
|
|
393
|
+
});
|