@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240317.ea25efe
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-guard.test.ts +41 -0
- 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 +40 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -0
- 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/__tests__/workspace-tool-loader.test.ts +3 -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-exclusive-tool.test.ts +150 -0
- package/src/agent/loop.ts +101 -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 +149 -53
- package/src/daemon/disk-pressure-guard.ts +12 -2
- 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 +90 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
- package/src/plugins/defaults/advisor/consult.ts +65 -6
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/steering.ts +14 -2
- package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
- 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 +290 -185
- package/src/providers/call-site-routing.ts +14 -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/openai/responses-provider.ts +5 -0
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/provider-send-message.ts +4 -0
- package/src/providers/ratelimit.ts +13 -0
- package/src/providers/retry.ts +14 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +11 -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/tool-defaults.ts +2 -0
- package/src/tools/types.ts +18 -2
- 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
|
@@ -11,6 +11,7 @@ import type { ModelIntent } from "../providers/types.js";
|
|
|
11
11
|
import { credentialKey } from "../security/credential-key.js";
|
|
12
12
|
import { getLogger } from "../util/logger.js";
|
|
13
13
|
import { loadRawConfig, saveRawConfig } from "./loader.js";
|
|
14
|
+
import { isDispatchableProfile } from "./profile-dispatchability.js";
|
|
14
15
|
import {
|
|
15
16
|
DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS,
|
|
16
17
|
type ProfileEntry,
|
|
@@ -41,12 +42,12 @@ type ManagedProfileTemplate = Omit<
|
|
|
41
42
|
* (`preserveProfileNames`) take precedence when present.
|
|
42
43
|
*/
|
|
43
44
|
const MANAGED_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
|
|
44
|
-
// Served by MiniMax M3 on
|
|
45
|
+
// Served by MiniMax M3 on Together AI via managed platform inference: a strong
|
|
45
46
|
// open model at a lower price point than the managed Anthropic route.
|
|
46
47
|
balanced: {
|
|
47
48
|
intent: "balanced",
|
|
48
|
-
provider: "
|
|
49
|
-
connectionName: "
|
|
49
|
+
provider: "together",
|
|
50
|
+
connectionName: "together-managed",
|
|
50
51
|
source: "managed",
|
|
51
52
|
label: "Balanced",
|
|
52
53
|
description: "Good balance of quality, cost, and speed",
|
|
@@ -56,12 +57,28 @@ const MANAGED_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
|
|
|
56
57
|
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
57
58
|
topP: 0.95,
|
|
58
59
|
},
|
|
60
|
+
// Served by GLM 5.2 on Fireworks via managed platform inference: a leading
|
|
61
|
+
// open model. `model` is pinned explicitly rather than resolved via the
|
|
62
|
+
// `quality-optimized` intent (which still maps to Anthropic Opus for the
|
|
63
|
+
// `frontier` profile below).
|
|
59
64
|
"quality-optimized": {
|
|
65
|
+
model: "accounts/fireworks/models/glm-5p2",
|
|
66
|
+
provider: "fireworks",
|
|
67
|
+
connectionName: "fireworks-managed",
|
|
68
|
+
source: "managed",
|
|
69
|
+
label: "Quality",
|
|
70
|
+
description: "High-quality results with a leading open model (GLM 5.2)",
|
|
71
|
+
maxTokens: 32000,
|
|
72
|
+
effort: "high",
|
|
73
|
+
thinking: { enabled: true, streamThinking: true },
|
|
74
|
+
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
75
|
+
},
|
|
76
|
+
frontier: {
|
|
60
77
|
intent: "quality-optimized",
|
|
61
78
|
provider: "anthropic",
|
|
62
79
|
connectionName: "anthropic-managed",
|
|
63
80
|
source: "managed",
|
|
64
|
-
label: "
|
|
81
|
+
label: "Frontier",
|
|
65
82
|
description: "Best results with the most capable model",
|
|
66
83
|
maxTokens: 32000,
|
|
67
84
|
effort: "high",
|
|
@@ -71,15 +88,24 @@ const MANAGED_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
|
|
|
71
88
|
// profile there's nothing stronger to consult, so the advisor defaults off.
|
|
72
89
|
advisorEnabled: false,
|
|
73
90
|
},
|
|
91
|
+
// Served by DeepSeek V4 Flash on Fireworks via managed platform inference: a
|
|
92
|
+
// fast, low-cost open model. `model` is pinned explicitly rather than
|
|
93
|
+
// resolved via the `latency-optimized` intent (which still maps to Kimi K2.5
|
|
94
|
+
// on Fireworks and Anthropic Haiku elsewhere).
|
|
95
|
+
//
|
|
96
|
+
// `effort: "none"` (not "low") because Fireworks is not thinking-aware: the
|
|
97
|
+
// disabled `thinking` config is stripped before the request, so a non-"none"
|
|
98
|
+
// effort would be sent as `reasoning_effort` and make this profile pay for
|
|
99
|
+
// reasoning despite thinking being off. "none" keeps Speed non-reasoning.
|
|
74
100
|
"cost-optimized": {
|
|
75
|
-
|
|
76
|
-
provider: "
|
|
77
|
-
connectionName: "
|
|
101
|
+
model: "accounts/fireworks/models/deepseek-v4-flash",
|
|
102
|
+
provider: "fireworks",
|
|
103
|
+
connectionName: "fireworks-managed",
|
|
78
104
|
source: "managed",
|
|
79
105
|
label: "Speed",
|
|
80
|
-
description: "Fastest responses at lower cost",
|
|
106
|
+
description: "Fastest responses at lower cost (DeepSeek V4 Flash)",
|
|
81
107
|
maxTokens: 8192,
|
|
82
|
-
effort: "
|
|
108
|
+
effort: "none",
|
|
83
109
|
thinking: { enabled: false, streamThinking: false },
|
|
84
110
|
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
85
111
|
},
|
|
@@ -131,14 +157,6 @@ const USER_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
|
|
|
131
157
|
},
|
|
132
158
|
};
|
|
133
159
|
|
|
134
|
-
/**
|
|
135
|
-
* The "auto" profile key. When active, the daemon injects the
|
|
136
|
-
* `switch_inference_profile` tool and lets the model self-select a profile
|
|
137
|
-
* per query. No provider/model — the resolver falls through to the call-site
|
|
138
|
-
* default (balanced or custom-balanced for BYOK).
|
|
139
|
-
*/
|
|
140
|
-
export const AUTO_PROFILE_KEY = "auto";
|
|
141
|
-
|
|
142
160
|
export const OS_BETA_PROFILE_KEY = "os-beta";
|
|
143
161
|
export const OS_BETA_FEATURE_FLAG_KEY = "os-beta";
|
|
144
162
|
|
|
@@ -170,9 +188,19 @@ export const OS_BETA_PROFILE_TEMPLATE: ManagedProfileTemplate = {
|
|
|
170
188
|
export const MANAGED_PROFILE_NAMES = new Set([
|
|
171
189
|
...Object.keys(MANAGED_PROFILE_TEMPLATES),
|
|
172
190
|
OS_BETA_PROFILE_KEY,
|
|
173
|
-
AUTO_PROFILE_KEY,
|
|
174
191
|
]);
|
|
175
192
|
|
|
193
|
+
// Managed names introduced after profile-ownership metadata existed, so any
|
|
194
|
+
// pre-existing same-named entry must have been user-created. The seed loop
|
|
195
|
+
// protects these from being clobbered: a user may already own a profile under
|
|
196
|
+
// such a name (the settings UI saves custom profiles without a `source`), so an
|
|
197
|
+
// entry that isn't explicitly `source: "managed"` is treated as theirs. The
|
|
198
|
+
// original canonical names (`balanced`/`quality-optimized`/`cost-optimized`)
|
|
199
|
+
// predate ownership metadata — migration 052 seeded them source-less — so they
|
|
200
|
+
// are NOT listed here and always reseed, even when source is absent.
|
|
201
|
+
const NEWLY_RESERVED_MANAGED_NAMES = new Set(["frontier"]);
|
|
202
|
+
const MIX_MIN_ARMS = 2;
|
|
203
|
+
|
|
176
204
|
export type SeedInferenceProfilesOptions = {
|
|
177
205
|
/**
|
|
178
206
|
* Profile names supplied by the platform/default overlay for this startup.
|
|
@@ -289,6 +317,21 @@ export function seedInferenceProfiles(
|
|
|
289
317
|
if (preservedProfileNames.has(name)) continue;
|
|
290
318
|
|
|
291
319
|
const previous = readObject(profiles[name]);
|
|
320
|
+
// Never clobber a custom profile that happens to share a *newly reserved*
|
|
321
|
+
// managed name (e.g. `frontier`): reseeding would change its provider/model
|
|
322
|
+
// and mark it managed. Treat anything not explicitly `source: "managed"` as
|
|
323
|
+
// the user's, since the settings UI saves custom profiles without a `source`
|
|
324
|
+
// and the source backfill below skips managed names. The original canonical
|
|
325
|
+
// names are excluded from this guard — they may be source-less *managed*
|
|
326
|
+
// entries from migration 052, so they must keep reseeding to receive
|
|
327
|
+
// template updates (see NEWLY_RESERVED_MANAGED_NAMES).
|
|
328
|
+
if (
|
|
329
|
+
NEWLY_RESERVED_MANAGED_NAMES.has(name) &&
|
|
330
|
+
previous &&
|
|
331
|
+
previous.source !== "managed"
|
|
332
|
+
) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
292
335
|
const effectiveTemplate: ManagedProfileTemplate = isByokMode
|
|
293
336
|
? { ...template, label: `${template.label} (Managed)` }
|
|
294
337
|
: template;
|
|
@@ -334,25 +377,6 @@ export function seedInferenceProfiles(
|
|
|
334
377
|
profiles[name] = next as ProfileEntry;
|
|
335
378
|
}
|
|
336
379
|
|
|
337
|
-
// 1b. Auto profile — a metadata-only profile with no provider/model. When
|
|
338
|
-
// the user selects "Auto", the resolver falls through to the call-site
|
|
339
|
-
// default (balanced or custom-balanced), and the agent loop injects the
|
|
340
|
-
// switch_inference_profile tool so the model can self-select per query.
|
|
341
|
-
if (!preservedProfileNames.has(AUTO_PROFILE_KEY)) {
|
|
342
|
-
const previousAuto = readObject(profiles[AUTO_PROFILE_KEY]);
|
|
343
|
-
const autoEntry: Record<string, unknown> = {
|
|
344
|
-
source: "managed",
|
|
345
|
-
label: "Auto",
|
|
346
|
-
description:
|
|
347
|
-
"Automatically routes each query to the best profile — fast for simple questions, capable for complex ones",
|
|
348
|
-
};
|
|
349
|
-
if (previousAuto) {
|
|
350
|
-
if ("label" in previousAuto) autoEntry.label = previousAuto.label;
|
|
351
|
-
if ("status" in previousAuto) autoEntry.status = previousAuto.status;
|
|
352
|
-
}
|
|
353
|
-
profiles[AUTO_PROFILE_KEY] = autoEntry as ProfileEntry;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
380
|
// 2. User profiles — only at hatch time for off-platform installations.
|
|
357
381
|
let userConnectionName: string | undefined;
|
|
358
382
|
if (options.isHatch && !isPlatform) {
|
|
@@ -394,6 +418,8 @@ export function seedInferenceProfiles(
|
|
|
394
418
|
}
|
|
395
419
|
}
|
|
396
420
|
|
|
421
|
+
pruneNonDispatchableProfiles(llm, profiles);
|
|
422
|
+
|
|
397
423
|
// Active profile resolution.
|
|
398
424
|
const requestedActiveProfile = readString(llm.activeProfile);
|
|
399
425
|
const requestedActiveEntry =
|
|
@@ -414,26 +440,26 @@ export function seedInferenceProfiles(
|
|
|
414
440
|
}
|
|
415
441
|
|
|
416
442
|
// Advisor profile: default to the strongest managed profile when unset, so
|
|
417
|
-
// the advisor consults `
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
443
|
+
// the advisor consults `frontier` (Anthropic Opus) out of the box, falling
|
|
444
|
+
// back to `quality-optimized` if `frontier` is unavailable. The `frontier`
|
|
445
|
+
// arm requires managed ownership: the seed loop above leaves a user-owned
|
|
446
|
+
// profile named `frontier` in place, and pointing the advisor at that would
|
|
447
|
+
// consult an arbitrary user model. Guarded on existence so it never names a
|
|
448
|
+
// missing profile (superRefine rejects that); off-platform/BYOK installs can
|
|
449
|
+
// repoint it at one of their own profiles.
|
|
450
|
+
if (readString(llm.advisorProfile) === undefined) {
|
|
451
|
+
if (readObject(profiles["frontier"])?.source === "managed") {
|
|
452
|
+
llm.advisorProfile = "frontier";
|
|
453
|
+
} else if (readObject(profiles["quality-optimized"]) !== null) {
|
|
454
|
+
llm.advisorProfile = "quality-optimized";
|
|
455
|
+
}
|
|
425
456
|
}
|
|
426
457
|
|
|
427
458
|
// Profile ordering — ensure all seeded profiles appear in the order array.
|
|
428
|
-
// "auto" is prepended so it appears first in the picker.
|
|
429
459
|
const profileOrder = Array.isArray(llm.profileOrder)
|
|
430
460
|
? (llm.profileOrder as string[])
|
|
431
461
|
: [];
|
|
432
462
|
const orderSet = new Set(profileOrder);
|
|
433
|
-
if (!orderSet.has(AUTO_PROFILE_KEY)) {
|
|
434
|
-
profileOrder.unshift(AUTO_PROFILE_KEY);
|
|
435
|
-
orderSet.add(AUTO_PROFILE_KEY);
|
|
436
|
-
}
|
|
437
463
|
for (const name of Object.keys(MANAGED_PROFILE_TEMPLATES)) {
|
|
438
464
|
if (!orderSet.has(name)) {
|
|
439
465
|
profileOrder.push(name);
|
|
@@ -490,6 +516,77 @@ export function readObject(value: unknown): Record<string, unknown> | null {
|
|
|
490
516
|
: null;
|
|
491
517
|
}
|
|
492
518
|
|
|
519
|
+
function pruneNonDispatchableProfiles(
|
|
520
|
+
llm: Record<string, unknown>,
|
|
521
|
+
profiles: Record<string, Record<string, unknown>>,
|
|
522
|
+
): void {
|
|
523
|
+
const removed = new Set<string>();
|
|
524
|
+
for (const [name, profile] of Object.entries(profiles)) {
|
|
525
|
+
if (!isDispatchableProfile(profile)) {
|
|
526
|
+
delete profiles[name];
|
|
527
|
+
removed.add(name);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
pruneRemovedProfileReferences(llm, profiles, removed);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function pruneRemovedProfileReferences(
|
|
534
|
+
llm: Record<string, unknown>,
|
|
535
|
+
profiles: Record<string, Record<string, unknown>>,
|
|
536
|
+
removed: Set<string>,
|
|
537
|
+
): void {
|
|
538
|
+
if (removed.size === 0) return;
|
|
539
|
+
|
|
540
|
+
let cascading = true;
|
|
541
|
+
while (cascading) {
|
|
542
|
+
cascading = false;
|
|
543
|
+
for (const [name, profile] of Object.entries(profiles)) {
|
|
544
|
+
if (removed.has(name)) continue;
|
|
545
|
+
if (!Array.isArray(profile.mix)) continue;
|
|
546
|
+
const arms = profile.mix as unknown[];
|
|
547
|
+
const kept = arms.filter((arm) => {
|
|
548
|
+
const armProfile = readObject(arm)?.profile;
|
|
549
|
+
return typeof armProfile !== "string" || !removed.has(armProfile);
|
|
550
|
+
});
|
|
551
|
+
if (kept.length === arms.length) continue;
|
|
552
|
+
if (kept.length >= MIX_MIN_ARMS) {
|
|
553
|
+
profile.mix = kept;
|
|
554
|
+
} else {
|
|
555
|
+
delete profiles[name];
|
|
556
|
+
removed.add(name);
|
|
557
|
+
}
|
|
558
|
+
cascading = true;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if (Array.isArray(llm.profileOrder)) {
|
|
563
|
+
llm.profileOrder = (llm.profileOrder as unknown[]).filter(
|
|
564
|
+
(name) => typeof name !== "string" || !removed.has(name),
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (
|
|
569
|
+
typeof llm.advisorProfile === "string" &&
|
|
570
|
+
removed.has(llm.advisorProfile)
|
|
571
|
+
) {
|
|
572
|
+
delete llm.advisorProfile;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const callSites = readObject(llm.callSites);
|
|
576
|
+
if (callSites) {
|
|
577
|
+
for (const entry of Object.values(callSites)) {
|
|
578
|
+
const site = readObject(entry);
|
|
579
|
+
if (
|
|
580
|
+
site &&
|
|
581
|
+
typeof site.profile === "string" &&
|
|
582
|
+
removed.has(site.profile)
|
|
583
|
+
) {
|
|
584
|
+
delete site.profile;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
493
590
|
function readString(value: unknown): string | undefined {
|
|
494
591
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
495
592
|
}
|
package/src/config/skills.ts
CHANGED
|
@@ -688,6 +688,9 @@ function discoverSkillDirectories(skillsDir: string): string[] {
|
|
|
688
688
|
* parseable `package.json` whose `name` equals the directory name. This
|
|
689
689
|
* mirrors the external plugin loader's recognition gate, which skips any
|
|
690
690
|
* directory whose `manifest.name` does not match its directory name.
|
|
691
|
+
*
|
|
692
|
+
* The caller is responsible for the missing-`package.json` case (it emits a
|
|
693
|
+
* diagnostic warning); this function only judges a manifest that is present.
|
|
691
694
|
*/
|
|
692
695
|
function isRecognizedPluginDir(pluginDir: string, dirName: string): boolean {
|
|
693
696
|
const manifestPath = join(pluginDir, "package.json");
|
|
@@ -735,12 +738,31 @@ function discoverPluginResidentSkills(): SkillSummary[] {
|
|
|
735
738
|
for (const entry of entries) {
|
|
736
739
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
737
740
|
const pluginDir = join(pluginsDir, entry.name);
|
|
741
|
+
|
|
742
|
+
// A directory under `plugins/` with no `package.json` is not a plugin the
|
|
743
|
+
// runtime can load, so its skills are never surfaced. This is an easy
|
|
744
|
+
// footgun — a plugin dropped in without its manifest looks installed but
|
|
745
|
+
// silently contributes nothing — so warn loudly with the path rather than
|
|
746
|
+
// skipping in silence, to make the misconfiguration diagnosable.
|
|
747
|
+
if (!existsSync(join(pluginDir, "package.json"))) {
|
|
748
|
+
log.warn(
|
|
749
|
+
{ pluginDir },
|
|
750
|
+
"Plugin directory is missing package.json — skipping; its skills will not be available. Add a package.json whose `name` matches the directory.",
|
|
751
|
+
);
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Honor the `.disabled` sentinel the runtime plugin scan checks
|
|
756
|
+
// (`plugins/mtime-cache.ts`): a disabled plugin contributes no hooks or
|
|
757
|
+
// tools, so its resident skills must not be loadable either.
|
|
758
|
+
if (existsSync(join(pluginDir, ".disabled"))) continue;
|
|
759
|
+
|
|
738
760
|
// Mirror the plugin loader's recognition gate: a directory is a real
|
|
739
|
-
// installed plugin only if
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
//
|
|
761
|
+
// installed plugin only if its `package.json` `name` matches the directory.
|
|
762
|
+
// This rejects staging dirs and malformed/mismatched clones (e.g. an
|
|
763
|
+
// un-adapted `caveman-installer`) that the loader itself would skip, so the
|
|
764
|
+
// catalog never surfaces skills from a directory the runtime would refuse
|
|
765
|
+
// to load.
|
|
744
766
|
if (!isRecognizedPluginDir(pluginDir, entry.name)) continue;
|
|
745
767
|
|
|
746
768
|
const skillsDir = join(pluginDir, "skills");
|
|
@@ -193,7 +193,19 @@ function disableProfile(
|
|
|
193
193
|
typeof llm.advisorProfile === "string" &&
|
|
194
194
|
removed.has(llm.advisorProfile)
|
|
195
195
|
) {
|
|
196
|
-
|
|
196
|
+
// Repoint the advisor at the managed Frontier profile (the strongest).
|
|
197
|
+
// `frontier` is seeded unconditionally every boot, so target it even if it
|
|
198
|
+
// has not been materialized yet this startup — this reconcile can run before
|
|
199
|
+
// the seeder in the boot sequence, and the later seeder won't rewrite an
|
|
200
|
+
// already-set `advisorProfile`. The exception is a user-owned profile named
|
|
201
|
+
// `frontier`: that is not ours to route to, so fall back to the
|
|
202
|
+
// always-managed Quality profile, then clear the pointer as a last resort.
|
|
203
|
+
const frontierEntry = readObject(profiles["frontier"]);
|
|
204
|
+
const frontierIsUserOwned =
|
|
205
|
+
frontierEntry !== null && frontierEntry.source !== "managed";
|
|
206
|
+
if (!frontierIsUserOwned) {
|
|
207
|
+
llm.advisorProfile = "frontier";
|
|
208
|
+
} else if (readObject(profiles["quality-optimized"]) !== null) {
|
|
197
209
|
llm.advisorProfile = "quality-optimized";
|
|
198
210
|
} else {
|
|
199
211
|
delete llm.advisorProfile;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the gateway-backed guardian delivery reader.
|
|
3
|
+
*
|
|
4
|
+
* Guardian binding is near-static, so the reader caches behind a minutes-scale
|
|
5
|
+
* TTL, clears event-driven on invalidation, and coalesces concurrent cold-cache
|
|
6
|
+
* reads single-flight. These tests pin the parse contract plus all three cache
|
|
7
|
+
* behaviors (TTL hit, invalidation, single-flight) and the failure-no-poison
|
|
8
|
+
* rule.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
14
|
+
|
|
15
|
+
// ── Controllable IPC mock ────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
type IpcHandler = (params?: Record<string, unknown>) => unknown;
|
|
18
|
+
|
|
19
|
+
const ipcHandlers = new Map<string, IpcHandler>();
|
|
20
|
+
const ipcCallLog: Array<{
|
|
21
|
+
method: string;
|
|
22
|
+
params?: Record<string, unknown>;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}> = [];
|
|
25
|
+
|
|
26
|
+
mock.module("../../ipc/gateway-client.js", () => ({
|
|
27
|
+
ipcCall: async (
|
|
28
|
+
method: string,
|
|
29
|
+
params?: Record<string, unknown>,
|
|
30
|
+
timeoutMs?: number,
|
|
31
|
+
) => {
|
|
32
|
+
ipcCallLog.push({ method, params, timeoutMs });
|
|
33
|
+
const handler = ipcHandlers.get(method);
|
|
34
|
+
return handler ? handler(params) : undefined;
|
|
35
|
+
},
|
|
36
|
+
ipcCallPersistent: async () => undefined,
|
|
37
|
+
resetPersistentClient: () => {},
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
import { emitContactChange } from "../contact-events.js";
|
|
41
|
+
import {
|
|
42
|
+
__resetGuardianDeliveryCacheForTest,
|
|
43
|
+
anyGuardian,
|
|
44
|
+
getGuardianDelivery,
|
|
45
|
+
getGuardianDeliveryFresh,
|
|
46
|
+
guardianForChannel,
|
|
47
|
+
invalidateGuardianDeliveryCache,
|
|
48
|
+
} from "../guardian-delivery-reader.js";
|
|
49
|
+
|
|
50
|
+
const METHOD = "resolve_guardian_delivery";
|
|
51
|
+
|
|
52
|
+
function countCalls(method: string): number {
|
|
53
|
+
return ipcCallLog.filter((c) => c.method === method).length;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const telegramGuardian: GuardianDelivery = {
|
|
57
|
+
channelType: "telegram",
|
|
58
|
+
contactId: "contact-123",
|
|
59
|
+
address: "@guardian",
|
|
60
|
+
status: "active",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const emailGuardian: GuardianDelivery = {
|
|
64
|
+
channelType: "email",
|
|
65
|
+
contactId: "contact-456",
|
|
66
|
+
address: "guardian@example.com",
|
|
67
|
+
status: "active",
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
describe("getGuardianDelivery", () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
__resetGuardianDeliveryCacheForTest();
|
|
73
|
+
ipcHandlers.clear();
|
|
74
|
+
ipcCallLog.length = 0;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("returns the parsed guardian list", async () => {
|
|
78
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
79
|
+
|
|
80
|
+
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("bounds the IPC read with a short timeout", async () => {
|
|
84
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
85
|
+
|
|
86
|
+
await getGuardianDelivery();
|
|
87
|
+
|
|
88
|
+
const call = ipcCallLog.find((c) => c.method === METHOD);
|
|
89
|
+
expect(call?.timeoutMs).toBe(2_000);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("returns null when IPC transport fails (undefined)", async () => {
|
|
93
|
+
ipcHandlers.set(METHOD, () => undefined);
|
|
94
|
+
expect(await getGuardianDelivery()).toBeNull();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("returns null when the IPC call throws", async () => {
|
|
98
|
+
ipcHandlers.set(METHOD, () => {
|
|
99
|
+
throw new Error("socket exploded");
|
|
100
|
+
});
|
|
101
|
+
expect(await getGuardianDelivery()).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("returns null for a malformed response shape", async () => {
|
|
105
|
+
ipcHandlers.set(METHOD, () => ({ guardians: "not-an-array" }));
|
|
106
|
+
expect(await getGuardianDelivery()).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("two calls within the TTL issue only ONE IPC call (cache hit)", async () => {
|
|
110
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
111
|
+
|
|
112
|
+
await getGuardianDelivery();
|
|
113
|
+
await getGuardianDelivery();
|
|
114
|
+
|
|
115
|
+
expect(countCalls(METHOD)).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("caches per channelTypes filter key", async () => {
|
|
119
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
120
|
+
|
|
121
|
+
await getGuardianDelivery();
|
|
122
|
+
await getGuardianDelivery({ channelTypes: ["telegram"] });
|
|
123
|
+
|
|
124
|
+
// Distinct keys ("ALL" vs "telegram") miss each other → two IPC calls.
|
|
125
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("invalidateGuardianDeliveryCache() forces the next call to re-fetch", async () => {
|
|
129
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
130
|
+
|
|
131
|
+
await getGuardianDelivery();
|
|
132
|
+
invalidateGuardianDeliveryCache();
|
|
133
|
+
await getGuardianDelivery();
|
|
134
|
+
|
|
135
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("a contact-change event clears the cache", async () => {
|
|
139
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
140
|
+
|
|
141
|
+
await getGuardianDelivery();
|
|
142
|
+
emitContactChange();
|
|
143
|
+
await getGuardianDelivery();
|
|
144
|
+
|
|
145
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("a burst of concurrent cold-cache calls issues only ONE IPC call (single-flight)", async () => {
|
|
149
|
+
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
150
|
+
ipcHandlers.set(
|
|
151
|
+
METHOD,
|
|
152
|
+
() =>
|
|
153
|
+
new Promise((resolve) => {
|
|
154
|
+
resolveIpc = resolve;
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const burst = Promise.all([
|
|
159
|
+
getGuardianDelivery(),
|
|
160
|
+
getGuardianDelivery(),
|
|
161
|
+
getGuardianDelivery(),
|
|
162
|
+
]);
|
|
163
|
+
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
164
|
+
const results = await burst;
|
|
165
|
+
|
|
166
|
+
expect(countCalls(METHOD)).toBe(1);
|
|
167
|
+
expect(results).toEqual([
|
|
168
|
+
[telegramGuardian],
|
|
169
|
+
[telegramGuardian],
|
|
170
|
+
[telegramGuardian],
|
|
171
|
+
]);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("an invalidation DURING an in-flight fetch is not masked — the next call re-fetches", async () => {
|
|
175
|
+
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
176
|
+
ipcHandlers.set(
|
|
177
|
+
METHOD,
|
|
178
|
+
() =>
|
|
179
|
+
new Promise((resolve) => {
|
|
180
|
+
resolveIpc = resolve;
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// Start a cold fetch, invalidate before it resolves, then resolve it.
|
|
185
|
+
const inFlight = getGuardianDelivery();
|
|
186
|
+
invalidateGuardianDeliveryCache();
|
|
187
|
+
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
188
|
+
expect(await inFlight).toEqual([telegramGuardian]);
|
|
189
|
+
|
|
190
|
+
// The pre-invalidation result must NOT have been cached: the next read
|
|
191
|
+
// issues a fresh IPC rather than serving the now-stale value.
|
|
192
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [emailGuardian] }));
|
|
193
|
+
expect(await getGuardianDelivery()).toEqual([emailGuardian]);
|
|
194
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("a failure does NOT poison the cache — the next call retries", async () => {
|
|
198
|
+
ipcHandlers.set(METHOD, () => undefined);
|
|
199
|
+
expect(await getGuardianDelivery()).toBeNull();
|
|
200
|
+
|
|
201
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
202
|
+
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
203
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("fresh read ignores a stale cached entry and re-fetches", async () => {
|
|
207
|
+
// Seed the cache with an empty list (the stale gateway-side view).
|
|
208
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
209
|
+
expect(await getGuardianDelivery()).toEqual([]);
|
|
210
|
+
|
|
211
|
+
// A cached read still serves the stale empty list (no new IPC)...
|
|
212
|
+
expect(await getGuardianDelivery()).toEqual([]);
|
|
213
|
+
expect(countCalls(METHOD)).toBe(1);
|
|
214
|
+
|
|
215
|
+
// ...but a fresh read bypasses the cache and sees the now-present guardian.
|
|
216
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
217
|
+
expect(await getGuardianDeliveryFresh()).toEqual([telegramGuardian]);
|
|
218
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("fresh read updates the cache with the fresh result", async () => {
|
|
222
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
223
|
+
await getGuardianDelivery();
|
|
224
|
+
|
|
225
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
226
|
+
await getGuardianDeliveryFresh();
|
|
227
|
+
|
|
228
|
+
// A subsequent cached read serves the refreshed value without a new IPC.
|
|
229
|
+
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
230
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("getGuardianDeliveryFresh bypasses a stale cached empty list", async () => {
|
|
234
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
235
|
+
expect(
|
|
236
|
+
await getGuardianDelivery({ channelTypes: ["telegram"] }),
|
|
237
|
+
).toEqual([]);
|
|
238
|
+
|
|
239
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
240
|
+
expect(
|
|
241
|
+
await getGuardianDeliveryFresh({ channelTypes: ["telegram"] }),
|
|
242
|
+
).toEqual([telegramGuardian]);
|
|
243
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("a burst of forceRefresh reads still coalesces single-flight", async () => {
|
|
247
|
+
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
248
|
+
ipcHandlers.set(
|
|
249
|
+
METHOD,
|
|
250
|
+
() =>
|
|
251
|
+
new Promise((resolve) => {
|
|
252
|
+
resolveIpc = resolve;
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const burst = Promise.all([
|
|
257
|
+
getGuardianDeliveryFresh(),
|
|
258
|
+
getGuardianDeliveryFresh(),
|
|
259
|
+
getGuardianDeliveryFresh(),
|
|
260
|
+
]);
|
|
261
|
+
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
262
|
+
await burst;
|
|
263
|
+
|
|
264
|
+
expect(countCalls(METHOD)).toBe(1);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("a fresh read does NOT coalesce with an in-flight non-force fetch (issues its own IPC)", async () => {
|
|
268
|
+
// A normal read starts a fetch that will resolve to the pre-write empty
|
|
269
|
+
// list and is still in flight when the fresh read arrives.
|
|
270
|
+
let resolveStale: ((value: unknown) => void) | undefined;
|
|
271
|
+
ipcHandlers.set(
|
|
272
|
+
METHOD,
|
|
273
|
+
() =>
|
|
274
|
+
new Promise((resolve) => {
|
|
275
|
+
resolveStale = resolve;
|
|
276
|
+
}),
|
|
277
|
+
);
|
|
278
|
+
const stale = getGuardianDelivery();
|
|
279
|
+
|
|
280
|
+
// The gateway-side write lands (not reflected in the in-flight fetch). The
|
|
281
|
+
// fresh read must NOT reuse the stale in-flight promise — it issues its own
|
|
282
|
+
// IPC observing the post-write guardian.
|
|
283
|
+
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
284
|
+
const fresh = await getGuardianDeliveryFresh();
|
|
285
|
+
expect(fresh).toEqual([telegramGuardian]);
|
|
286
|
+
|
|
287
|
+
// Release the stale fetch last; it must not have masked the fresh result.
|
|
288
|
+
resolveStale?.({ guardians: [] });
|
|
289
|
+
expect(await stale).toEqual([]);
|
|
290
|
+
expect(countCalls(METHOD)).toBe(2);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe("selectors", () => {
|
|
295
|
+
test("guardianForChannel picks the first active match for the type", () => {
|
|
296
|
+
const inactive: GuardianDelivery = {
|
|
297
|
+
...telegramGuardian,
|
|
298
|
+
contactId: "contact-999",
|
|
299
|
+
status: "revoked",
|
|
300
|
+
};
|
|
301
|
+
const list = [inactive, telegramGuardian, emailGuardian];
|
|
302
|
+
|
|
303
|
+
expect(guardianForChannel(list, "telegram")).toBe(telegramGuardian);
|
|
304
|
+
expect(guardianForChannel(list, "email")).toBe(emailGuardian);
|
|
305
|
+
expect(guardianForChannel(list, "phone")).toBeUndefined();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
test("anyGuardian returns the first overall", () => {
|
|
309
|
+
expect(anyGuardian([emailGuardian, telegramGuardian])).toBe(emailGuardian);
|
|
310
|
+
expect(anyGuardian([])).toBeUndefined();
|
|
311
|
+
});
|
|
312
|
+
});
|