@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
|
@@ -184,6 +184,27 @@ export function getContact(id: string): ContactWithChannels | null {
|
|
|
184
184
|
/** @deprecated Use {@link getContact} directly. */
|
|
185
185
|
export const getContactInternal = getContact;
|
|
186
186
|
|
|
187
|
+
/** INFO-only contact fields, joined locally by contact ID. */
|
|
188
|
+
export interface ContactInfo {
|
|
189
|
+
notes: string | null;
|
|
190
|
+
interactionCount: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Look up a contact's INFO fields (notes, interaction count) by ID.
|
|
195
|
+
*
|
|
196
|
+
* Carries no ACL state (status/policy/verification) — those are owned by the
|
|
197
|
+
* gateway-stamped trust verdict. Returns null when the contact does not exist.
|
|
198
|
+
*/
|
|
199
|
+
export function findContactInfoById(contactId: string): ContactInfo | null {
|
|
200
|
+
const contact = getContact(contactId);
|
|
201
|
+
if (!contact) return null;
|
|
202
|
+
return {
|
|
203
|
+
notes: contact.notes,
|
|
204
|
+
interactionCount: contact.interactionCount,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
187
208
|
/**
|
|
188
209
|
* Look up a single contact channel by its primary key.
|
|
189
210
|
* Returns the parsed channel row, or null if it does not exist.
|
|
@@ -30,6 +30,9 @@ import type {
|
|
|
30
30
|
* Returns true when a guardian channel was found and revoked, false otherwise.
|
|
31
31
|
*/
|
|
32
32
|
export function revokeGuardianBinding(channel: string): boolean {
|
|
33
|
+
// Local-store read, not the gateway: this read selects the row that the
|
|
34
|
+
// updateChannelStatus write below mutates, so it must stay transactionally
|
|
35
|
+
// consistent with that write. Leave for Combo 11 / gateway-bootstrap-binding.
|
|
33
36
|
const guardian = findGuardianForChannel(channel);
|
|
34
37
|
if (!guardian) return false;
|
|
35
38
|
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway-backed guardian binding + delivery reader.
|
|
3
|
+
*
|
|
4
|
+
* Resolves the active guardian binding(s) and their per-channel delivery
|
|
5
|
+
* endpoints from the gateway via the `resolve_guardian_delivery` IPC route,
|
|
6
|
+
* validating the response against {@link ResolveGuardianDeliveryResponseSchema}.
|
|
7
|
+
*
|
|
8
|
+
* Guardian binding is near-static — it only changes on guardian onboarding /
|
|
9
|
+
* verification or revocation — yet this reader sits on many hot paths. To keep
|
|
10
|
+
* those paths off the IPC, results are cached behind a minutes-scale TTL and
|
|
11
|
+
* coalesced single-flight so a cold cache storms the gateway at most once.
|
|
12
|
+
*
|
|
13
|
+
* Freshness comes from two sources: the {@link invalidateGuardianDeliveryCache}
|
|
14
|
+
* subscription to `onContactChange` (contact mutations clear the cache), and
|
|
15
|
+
* {@link getGuardianDeliveryFresh} reads on existence guards (gateway-side
|
|
16
|
+
* binding writes don't invalidate the daemon cache, so those paths read fresh).
|
|
17
|
+
*
|
|
18
|
+
* Returns `null` on ANY failure (transport failure, malformed shape, timeout,
|
|
19
|
+
* or thrown error); failures are NOT cached, so a recovered gateway is retried
|
|
20
|
+
* on the next call.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
type GuardianDelivery,
|
|
25
|
+
ResolveGuardianDeliveryResponseSchema,
|
|
26
|
+
} from "@vellumai/gateway-client";
|
|
27
|
+
|
|
28
|
+
import { ipcCall } from "../ipc/gateway-client.js";
|
|
29
|
+
import { onContactChange } from "./contact-events.js";
|
|
30
|
+
|
|
31
|
+
// Short IPC timeout so the read resolves promptly rather than stalling a hot
|
|
32
|
+
// path on a gateway that accepts the socket but hangs.
|
|
33
|
+
const GUARDIAN_DELIVERY_IPC_TIMEOUT_MS = 2_000;
|
|
34
|
+
|
|
35
|
+
// Guardian binding is near-static, so a minutes-scale TTL is safe; freshness is
|
|
36
|
+
// driven primarily by event-based invalidation, not by this backstop expiry.
|
|
37
|
+
const GUARDIAN_DELIVERY_CACHE_TTL_MS = 300_000;
|
|
38
|
+
|
|
39
|
+
interface CacheEntry {
|
|
40
|
+
guardians: GuardianDelivery[];
|
|
41
|
+
fetchedAt: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cache = new Map<string, CacheEntry>();
|
|
45
|
+
// Tracks whether the in-flight fetch was a force-refresh, so a fresh read never
|
|
46
|
+
// coalesces with an older non-force fetch that may predate a gateway-side write.
|
|
47
|
+
const inFlight = new Map<
|
|
48
|
+
string,
|
|
49
|
+
{ promise: Promise<GuardianDelivery[] | null>; fresh: boolean }
|
|
50
|
+
>();
|
|
51
|
+
|
|
52
|
+
// Bumped on every invalidation. A fetch captures the generation when it starts
|
|
53
|
+
// and only writes its result to the cache if the generation is unchanged on
|
|
54
|
+
// resolve, so an invalidation mid-flight can't repopulate a stale pre-change
|
|
55
|
+
// result and mask a guardian-binding change.
|
|
56
|
+
let cacheGeneration = 0;
|
|
57
|
+
|
|
58
|
+
function cacheKey(channelTypes?: string[]): string {
|
|
59
|
+
if (!channelTypes || channelTypes.length === 0) return "ALL";
|
|
60
|
+
return [...channelTypes].sort().join(",");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function fetchGuardianDelivery(
|
|
64
|
+
input: { channelTypes?: string[] },
|
|
65
|
+
): Promise<GuardianDelivery[] | null> {
|
|
66
|
+
try {
|
|
67
|
+
const result = await ipcCall(
|
|
68
|
+
"resolve_guardian_delivery",
|
|
69
|
+
input,
|
|
70
|
+
GUARDIAN_DELIVERY_IPC_TIMEOUT_MS,
|
|
71
|
+
);
|
|
72
|
+
if (!result) return null;
|
|
73
|
+
|
|
74
|
+
const parsed = ResolveGuardianDeliveryResponseSchema.safeParse(result);
|
|
75
|
+
return parsed.success ? parsed.data.guardians : null;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Shared fetch path for both the cached and fresh public surfaces. When
|
|
82
|
+
// `forceRefresh` is set the cached entry is bypassed; the read is still
|
|
83
|
+
// single-flight and still populates the cache with the fresh result.
|
|
84
|
+
async function readGuardianDelivery(
|
|
85
|
+
input: { channelTypes?: string[]; forceRefresh?: boolean },
|
|
86
|
+
): Promise<GuardianDelivery[] | null> {
|
|
87
|
+
const key = cacheKey(input.channelTypes);
|
|
88
|
+
|
|
89
|
+
if (!input.forceRefresh) {
|
|
90
|
+
const cached = cache.get(key);
|
|
91
|
+
if (
|
|
92
|
+
cached &&
|
|
93
|
+
Date.now() - cached.fetchedAt < GUARDIAN_DELIVERY_CACHE_TTL_MS
|
|
94
|
+
) {
|
|
95
|
+
return cached.guardians;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// A non-force read may coalesce with any in-flight fetch. A force read may
|
|
100
|
+
// only coalesce with another force fetch — never with a non-force fetch that
|
|
101
|
+
// could have started before a gateway-side binding write and resolve stale.
|
|
102
|
+
const pending = inFlight.get(key);
|
|
103
|
+
if (pending && (!input.forceRefresh || pending.fresh)) return pending.promise;
|
|
104
|
+
|
|
105
|
+
const startGen = cacheGeneration;
|
|
106
|
+
const promise = fetchGuardianDelivery({ channelTypes: input.channelTypes })
|
|
107
|
+
.then((guardians) => {
|
|
108
|
+
// Skip the write if an invalidation fired during the fetch: the result
|
|
109
|
+
// may predate the change. Return it to this caller (freshest it has) but
|
|
110
|
+
// leave the cache empty so the next call re-fetches.
|
|
111
|
+
if (guardians && cacheGeneration === startGen) {
|
|
112
|
+
cache.set(key, { guardians, fetchedAt: Date.now() });
|
|
113
|
+
}
|
|
114
|
+
return guardians;
|
|
115
|
+
})
|
|
116
|
+
.finally(() => {
|
|
117
|
+
// Only clear the slot if it still holds this fetch — a concurrent force
|
|
118
|
+
// read may have replaced a non-force entry (or vice versa).
|
|
119
|
+
if (inFlight.get(key)?.promise === promise) inFlight.delete(key);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
inFlight.set(key, { promise, fresh: !!input.forceRefresh });
|
|
123
|
+
return promise;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Resolve active guardian deliveries, optionally filtered by channel type.
|
|
128
|
+
* Returns the cached list when fresh, otherwise fetches (single-flight) and
|
|
129
|
+
* caches on success. Returns `null` on failure without caching.
|
|
130
|
+
*
|
|
131
|
+
* To force an uncached read, call {@link getGuardianDeliveryFresh} — the only
|
|
132
|
+
* public fresh-read entry point.
|
|
133
|
+
*/
|
|
134
|
+
export async function getGuardianDelivery(
|
|
135
|
+
input?: { channelTypes?: string[] },
|
|
136
|
+
): Promise<GuardianDelivery[] | null> {
|
|
137
|
+
return readGuardianDelivery({ channelTypes: input?.channelTypes });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Synchronous read of the already-cached guardian deliveries, without any IO.
|
|
142
|
+
*
|
|
143
|
+
* Returns the fresh cached list for the given channel filter, or `undefined`
|
|
144
|
+
* when the cache is cold or expired. Used by sync hot paths (SSE subscribe)
|
|
145
|
+
* that cannot await {@link getGuardianDelivery} but must resolve the SAME
|
|
146
|
+
* gateway-owned principal the async paths land on. A cold/expired return lets
|
|
147
|
+
* the caller fall back to the local store as before.
|
|
148
|
+
*/
|
|
149
|
+
export function peekCachedGuardianDelivery(
|
|
150
|
+
input?: { channelTypes?: string[] },
|
|
151
|
+
): GuardianDelivery[] | undefined {
|
|
152
|
+
const cached = cache.get(cacheKey(input?.channelTypes));
|
|
153
|
+
if (!cached) return undefined;
|
|
154
|
+
if (Date.now() - cached.fetchedAt >= GUARDIAN_DELIVERY_CACHE_TTL_MS) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
return cached.guardians;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Fresh (uncached) variant of {@link getGuardianDelivery}. Existence guards read
|
|
162
|
+
* fresh because gateway-side binding writes don't invalidate the daemon cache.
|
|
163
|
+
* Still single-flight, and still populates the cache with the fresh result.
|
|
164
|
+
*/
|
|
165
|
+
export async function getGuardianDeliveryFresh(
|
|
166
|
+
input?: { channelTypes?: string[] },
|
|
167
|
+
): Promise<GuardianDelivery[] | null> {
|
|
168
|
+
return readGuardianDelivery({
|
|
169
|
+
channelTypes: input?.channelTypes,
|
|
170
|
+
forceRefresh: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Clear ALL cached guardian deliveries. Subscribed to `onContactChange` so
|
|
176
|
+
* contact mutations refetch on the next read; also exported for any caller that
|
|
177
|
+
* wants to invalidate explicitly.
|
|
178
|
+
*/
|
|
179
|
+
export function invalidateGuardianDeliveryCache(): void {
|
|
180
|
+
cacheGeneration += 1;
|
|
181
|
+
cache.clear();
|
|
182
|
+
inFlight.clear();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
onContactChange(invalidateGuardianDeliveryCache);
|
|
186
|
+
|
|
187
|
+
/** First active guardian delivery for the given channel type, if any. */
|
|
188
|
+
export function guardianForChannel(
|
|
189
|
+
list: GuardianDelivery[],
|
|
190
|
+
channelType: string,
|
|
191
|
+
): GuardianDelivery | undefined {
|
|
192
|
+
return list.find(
|
|
193
|
+
(g) => g.channelType === channelType && g.status === "active",
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** First guardian delivery overall — the `listGuardianChannels` fallback. */
|
|
198
|
+
export function anyGuardian(
|
|
199
|
+
list: GuardianDelivery[],
|
|
200
|
+
): GuardianDelivery | undefined {
|
|
201
|
+
return list[0];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Resolve a guardian displayName for voice surfaces: prefer the phone-channel
|
|
206
|
+
* guardian, falling back to any guardian. Returns `undefined` when the list is
|
|
207
|
+
* absent or no guardian carries a displayName.
|
|
208
|
+
*/
|
|
209
|
+
export function voiceGuardianDisplayName(
|
|
210
|
+
list: GuardianDelivery[] | null,
|
|
211
|
+
): string | undefined {
|
|
212
|
+
const guardian = list
|
|
213
|
+
? (guardianForChannel(list, "phone") ?? anyGuardian(list))
|
|
214
|
+
: undefined;
|
|
215
|
+
return guardian?.displayName ?? undefined;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Test-only: reset cache + in-flight state for deterministic test runs. */
|
|
219
|
+
export function __resetGuardianDeliveryCacheForTest(): void {
|
|
220
|
+
cache.clear();
|
|
221
|
+
inFlight.clear();
|
|
222
|
+
cacheGeneration = 0;
|
|
223
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChannelStatus } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/** Map ChannelStatus to the API-facing member status (excludes "unverified"). */
|
|
4
|
+
export function channelStatusToMemberStatus(
|
|
5
|
+
status: ChannelStatus,
|
|
6
|
+
): Exclude<ChannelStatus, "unverified"> {
|
|
7
|
+
if (status === "unverified") return "pending";
|
|
8
|
+
return status;
|
|
9
|
+
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type OAuthConnectionRow,
|
|
25
25
|
type OAuthProviderRow,
|
|
26
26
|
} from "../oauth/oauth-store.js";
|
|
27
|
+
import { scopeDifference } from "../oauth/scope-utils.js";
|
|
27
28
|
import {
|
|
28
29
|
TokenExpiredError,
|
|
29
30
|
withValidToken,
|
|
@@ -77,11 +78,6 @@ function safeJsonParse<T>(raw: string | null | undefined, fallback: T): T {
|
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
function scopeDifference(required: string[], granted: string[]): string[] {
|
|
81
|
-
const grantedSet = new Set(granted);
|
|
82
|
-
return required.filter((s) => !grantedSet.has(s));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
81
|
// ── Liveness ping ─────────────────────────────────────────────────────
|
|
86
82
|
|
|
87
83
|
/** @internal Exposed for test injection. */
|
|
@@ -47,6 +47,20 @@ mock.module("../../runtime/assistant-event-hub.js", () => ({
|
|
|
47
47
|
broadcastMessage: () => {},
|
|
48
48
|
}));
|
|
49
49
|
|
|
50
|
+
// Control the advisor profile gate to verify the advisor tool is wired to it.
|
|
51
|
+
// The gate's own config semantics (default-on, active-profile fallback) are
|
|
52
|
+
// covered by advisor-gate.test.ts; here we only assert the wiring and the
|
|
53
|
+
// profile argument isToolActiveForContext passes through.
|
|
54
|
+
let advisorGateResult = true;
|
|
55
|
+
const advisorGateProfiles: (string | null)[] = [];
|
|
56
|
+
|
|
57
|
+
mock.module("../../plugins/defaults/advisor/advisor-gate.js", () => ({
|
|
58
|
+
advisorEnabledForProfile: (profile: string | null) => {
|
|
59
|
+
advisorGateProfiles.push(profile);
|
|
60
|
+
return advisorGateResult;
|
|
61
|
+
},
|
|
62
|
+
}));
|
|
63
|
+
|
|
50
64
|
// Dynamic imports after mock.module calls so the stubs take effect
|
|
51
65
|
// before the modules under test are loaded.
|
|
52
66
|
const { HOST_TOOL_NAMES, HOST_TOOL_TO_CAPABILITY, isToolActiveForContext } =
|
|
@@ -597,6 +611,36 @@ describe("isToolActiveForContext — ask_question macOS gating", () => {
|
|
|
597
611
|
});
|
|
598
612
|
});
|
|
599
613
|
|
|
614
|
+
describe("isToolActiveForContext — advisor profile gate", () => {
|
|
615
|
+
beforeEach(() => {
|
|
616
|
+
advisorGateResult = true;
|
|
617
|
+
advisorGateProfiles.length = 0;
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("advisor is active when the profile enables it", () => {
|
|
621
|
+
advisorGateResult = true;
|
|
622
|
+
expect(isToolActiveForContext("advisor", makeCtx())).toBe(true);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
test("advisor is NOT active when the profile disables it", () => {
|
|
626
|
+
advisorGateResult = false;
|
|
627
|
+
expect(isToolActiveForContext("advisor", makeCtx())).toBe(false);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
test("consults the gate with the per-turn override profile", () => {
|
|
631
|
+
isToolActiveForContext(
|
|
632
|
+
"advisor",
|
|
633
|
+
makeCtx({ currentTurnOverrideProfile: "cost-optimized" }),
|
|
634
|
+
);
|
|
635
|
+
expect(advisorGateProfiles).toEqual(["cost-optimized"]);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test("consults the gate with null when no per-turn override is set", () => {
|
|
639
|
+
isToolActiveForContext("advisor", makeCtx());
|
|
640
|
+
expect(advisorGateProfiles).toEqual([null]);
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
|
|
600
644
|
describe("HOST_TOOL_NAMES derivation", () => {
|
|
601
645
|
test("HOST_TOOL_NAMES is derived from HOST_TOOL_TO_CAPABILITY", () => {
|
|
602
646
|
// Sanity check: every tool in the names set has a capability mapping.
|
|
@@ -11,11 +11,9 @@
|
|
|
11
11
|
|
|
12
12
|
import { existsSync, type FSWatcher, watch } from "node:fs";
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
getAppsDir,
|
|
16
|
-
resolveAppIdByDirName,
|
|
17
|
-
} from "../memory/app-store.js";
|
|
14
|
+
import { getAppsDir, resolveAppIdByDirName } from "../memory/app-store.js";
|
|
18
15
|
import { DebouncerMap } from "../util/debounce.js";
|
|
16
|
+
import { attachFsWatcherErrorHandler } from "../util/fs-watcher-error.js";
|
|
19
17
|
import { getLogger } from "../util/logger.js";
|
|
20
18
|
|
|
21
19
|
const log = getLogger("app-source-watcher");
|
|
@@ -51,8 +49,10 @@ function resolveAppIdFromRelPath(relPath: string): string | null {
|
|
|
51
49
|
|
|
52
50
|
// Skip non-source directories (include bare directory names for fs.watch events)
|
|
53
51
|
if (
|
|
54
|
-
innerPath === "records" ||
|
|
55
|
-
innerPath
|
|
52
|
+
innerPath === "records" ||
|
|
53
|
+
innerPath.startsWith("records/") ||
|
|
54
|
+
innerPath === "dist" ||
|
|
55
|
+
innerPath.startsWith("dist/")
|
|
56
56
|
) {
|
|
57
57
|
return null;
|
|
58
58
|
}
|
|
@@ -89,7 +89,9 @@ export class AppSourceWatcher {
|
|
|
89
89
|
try {
|
|
90
90
|
appsDir = getAppsDir();
|
|
91
91
|
} catch {
|
|
92
|
-
log.warn(
|
|
92
|
+
log.warn(
|
|
93
|
+
"Could not resolve apps directory; app source watching disabled",
|
|
94
|
+
);
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -102,19 +104,30 @@ export class AppSourceWatcher {
|
|
|
102
104
|
if (!onChange) return;
|
|
103
105
|
|
|
104
106
|
try {
|
|
105
|
-
this.watcher = watch(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
this.watcher = watch(
|
|
108
|
+
appsDir,
|
|
109
|
+
{ recursive: true },
|
|
110
|
+
(_eventType, filename) => {
|
|
111
|
+
if (!filename) return;
|
|
112
|
+
|
|
113
|
+
const appId = resolveAppIdFromRelPath(filename);
|
|
114
|
+
if (!appId) return;
|
|
115
|
+
|
|
116
|
+
this.debouncer.schedule(`app:${appId}`, () => {
|
|
117
|
+
onChange(appId);
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
);
|
|
121
|
+
// Recursive watches over app trees (incl. node_modules) can exhaust the
|
|
122
|
+
// inotify watch limit and emit ENOSPC asynchronously. Without an 'error'
|
|
123
|
+
// listener that unhandled emitter error crashes the daemon.
|
|
124
|
+
attachFsWatcherErrorHandler(this.watcher, log, appsDir);
|
|
115
125
|
log.info("App source watcher started");
|
|
116
126
|
} catch (err) {
|
|
117
|
-
log.warn(
|
|
127
|
+
log.warn(
|
|
128
|
+
{ err },
|
|
129
|
+
"Failed to watch apps directory; source watching disabled",
|
|
130
|
+
);
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
133
|
|
|
@@ -256,6 +256,88 @@ export function parseDirectives(text: string): DirectiveParseResult {
|
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// vellum:// markdown link extraction
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Match markdown links with `vellum://workspace/` or `vellum://host/` URLs.
|
|
265
|
+
*
|
|
266
|
+
* Captures:
|
|
267
|
+
* [1] = link text (filename)
|
|
268
|
+
* [2] = scheme authority: "workspace" or "host"
|
|
269
|
+
* [3] = path after the authority
|
|
270
|
+
*
|
|
271
|
+
* The link text is NOT stripped from the assistant's message — unlike
|
|
272
|
+
* `<vellum-attachment />` tags, the markdown link is valid user-facing
|
|
273
|
+
* content that renders as a clickable download link.
|
|
274
|
+
*/
|
|
275
|
+
const VELLUM_LINK_RE = /\[([^\]]+)\]\(vellum:\/\/(workspace|host)(\/[^)]*)\)/g;
|
|
276
|
+
|
|
277
|
+
interface VellumLinkExtractResult {
|
|
278
|
+
directiveRequests: DirectiveRequest[];
|
|
279
|
+
parseWarnings: string[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Extract `[text](vellum://workspace/path)` and `[text](vellum://host/path)`
|
|
284
|
+
* markdown links from assistant text and return corresponding directive
|
|
285
|
+
* requests. The text is NOT modified — the links remain as rendered markdown.
|
|
286
|
+
*/
|
|
287
|
+
export function extractVellumLinks(text: string): VellumLinkExtractResult {
|
|
288
|
+
const directiveRequests: DirectiveRequest[] = [];
|
|
289
|
+
const parseWarnings: string[] = [];
|
|
290
|
+
|
|
291
|
+
let m: RegExpExecArray | null;
|
|
292
|
+
while ((m = VELLUM_LINK_RE.exec(text)) != null) {
|
|
293
|
+
const linkText = m[1]!;
|
|
294
|
+
const authority = m[2]!;
|
|
295
|
+
const rawPath = m[3]!;
|
|
296
|
+
|
|
297
|
+
if (authority === "workspace") {
|
|
298
|
+
// Strip the leading "/" to get a workspace-relative path
|
|
299
|
+
const path = rawPath.startsWith("/") ? rawPath.slice(1) : rawPath;
|
|
300
|
+
if (!path) {
|
|
301
|
+
parseWarnings.push(
|
|
302
|
+
`Ignored vellum://workspace link "${linkText}": empty path.`,
|
|
303
|
+
);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
directiveRequests.push({
|
|
307
|
+
source: "sandbox",
|
|
308
|
+
path,
|
|
309
|
+
filename: linkText || undefined,
|
|
310
|
+
mimeType: undefined,
|
|
311
|
+
});
|
|
312
|
+
} else {
|
|
313
|
+
// host: rawPath is already absolute (starts with /)
|
|
314
|
+
if (!rawPath || rawPath === "/") {
|
|
315
|
+
parseWarnings.push(
|
|
316
|
+
`Ignored vellum://host link "${linkText}": empty path.`,
|
|
317
|
+
);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
directiveRequests.push({
|
|
321
|
+
source: "host",
|
|
322
|
+
path: rawPath,
|
|
323
|
+
filename: linkText || undefined,
|
|
324
|
+
mimeType: undefined,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return { directiveRequests, parseWarnings };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Replace `[text](vellum://...)` markdown links with their link text.
|
|
334
|
+
* Used to sanitize text before channel delivery (Slack, Telegram, etc.)
|
|
335
|
+
* where the `vellum://` scheme has no meaning.
|
|
336
|
+
*/
|
|
337
|
+
export function stripVellumLinks(text: string): string {
|
|
338
|
+
return text.replace(VELLUM_LINK_RE, "$1");
|
|
339
|
+
}
|
|
340
|
+
|
|
259
341
|
/**
|
|
260
342
|
* Drain streamed assistant text while stripping only valid, complete
|
|
261
343
|
* self-closing `<vellum-attachment ... />` directives.
|
|
@@ -707,10 +789,18 @@ export function cleanAssistantContent(content: readonly unknown[]): {
|
|
|
707
789
|
const b = block as Record<string, unknown>;
|
|
708
790
|
if (b.type !== "text") return block;
|
|
709
791
|
const text = b.text as string;
|
|
710
|
-
|
|
711
|
-
//
|
|
712
|
-
|
|
713
|
-
|
|
792
|
+
|
|
793
|
+
// Extract vellum:// markdown links (non-destructive — links stay in text)
|
|
794
|
+
if (text.includes("vellum://")) {
|
|
795
|
+
const linkResult = extractVellumLinks(text);
|
|
796
|
+
directives.push(...linkResult.directiveRequests);
|
|
797
|
+
warnings.push(...linkResult.parseWarnings);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Strip legacy <vellum-attachment /> tags from the text
|
|
801
|
+
if (!text.includes("<vellum-attachment")) {
|
|
802
|
+
return block;
|
|
803
|
+
}
|
|
714
804
|
const result = parseDirectives(text);
|
|
715
805
|
directives.push(...result.directiveRequests);
|
|
716
806
|
warnings.push(...result.parseWarnings);
|
|
@@ -70,7 +70,6 @@ import type { UserPromptSubmitContext } from "../plugin-api/types.js";
|
|
|
70
70
|
import { runHook } from "../plugins/pipeline.js";
|
|
71
71
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
72
72
|
import type { Provider } from "../providers/types.js";
|
|
73
|
-
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
74
73
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
75
74
|
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
76
75
|
import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
|
|
@@ -190,8 +189,8 @@ export interface AssistantSurface {
|
|
|
190
189
|
// ── abort watchdog ───────────────────────────────────────────────────
|
|
191
190
|
|
|
192
191
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
192
|
+
* Backstop that drives an aborted turn to its `finally` even if some awaited
|
|
193
|
+
* operation fails to observe the abort signal.
|
|
195
194
|
*
|
|
196
195
|
* Abort is otherwise cooperative and already wired into the slow paths: the
|
|
197
196
|
* provider call forwards the signal to its HTTP/streaming fetch, and tool
|
|
@@ -199,10 +198,11 @@ export interface AssistantSurface {
|
|
|
199
198
|
* watchdog only fires when a future code path silently ignores abort — without
|
|
200
199
|
* it, such a path would hang the loop forever and latch the conversation's
|
|
201
200
|
* `processing` flag true (the wedged "Thinking…" indicator). It is
|
|
202
|
-
* defense-in-depth, not the primary mechanism
|
|
203
|
-
*
|
|
201
|
+
* defense-in-depth, not the primary mechanism: in the common case abort settles
|
|
202
|
+
* in-flight work in well under a second, so a few seconds is ample headroom for
|
|
203
|
+
* a cooperative unwind while still releasing a genuinely wedged turn promptly.
|
|
204
204
|
*/
|
|
205
|
-
const ABORT_WATCHDOG_MS =
|
|
205
|
+
const ABORT_WATCHDOG_MS = 5_000;
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* Race `work` against an abort watchdog. The watchdog stays disarmed until the
|
|
@@ -350,18 +350,11 @@ export async function runAgentLoopImpl(
|
|
|
350
350
|
|
|
351
351
|
const config = getConfig();
|
|
352
352
|
|
|
353
|
-
// Tool-based auto-routing: the switch_inference_profile tool lets the model
|
|
354
|
-
// self-select a different profile mid-turn. Reset the per-turn slot so a
|
|
355
|
-
// stale selection from a previous turn doesn't leak forward.
|
|
356
|
-
ctx.toolRoutedProfile = undefined;
|
|
357
|
-
|
|
358
353
|
const turnOverrideProfile = userExplicitOverride;
|
|
359
354
|
const forceOverrideProfile = options?.forceOverrideProfile === true;
|
|
360
355
|
|
|
361
356
|
const readCurrentOverrideProfile = (): string | undefined =>
|
|
362
|
-
options?.overrideProfile ??
|
|
363
|
-
resolveOverrideProfile(ctx) ??
|
|
364
|
-
ctx.toolRoutedProfile;
|
|
357
|
+
options?.overrideProfile ?? resolveOverrideProfile(ctx);
|
|
365
358
|
|
|
366
359
|
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
367
360
|
llm: config.llm,
|
|
@@ -383,7 +376,6 @@ export async function runAgentLoopImpl(
|
|
|
383
376
|
ctx.contextWindowManager.updateConfig(currentContextWindowConfig);
|
|
384
377
|
|
|
385
378
|
let appliedOverrideProfile = turnOverrideProfile;
|
|
386
|
-
let emittedToolRoutedProfile: string | undefined;
|
|
387
379
|
const refreshCurrentProfileState = (): string | undefined => {
|
|
388
380
|
const currentOverrideProfile = readCurrentOverrideProfile();
|
|
389
381
|
if (currentOverrideProfile !== appliedOverrideProfile) {
|
|
@@ -410,23 +402,6 @@ export async function runAgentLoopImpl(
|
|
|
410
402
|
);
|
|
411
403
|
}
|
|
412
404
|
|
|
413
|
-
// Emit turn_profile_auto_routed when the tool-based router selects a
|
|
414
|
-
// new profile. Deduplicated so the event fires at most once per profile.
|
|
415
|
-
if (
|
|
416
|
-
ctx.toolRoutedProfile &&
|
|
417
|
-
ctx.toolRoutedProfile !== emittedToolRoutedProfile
|
|
418
|
-
) {
|
|
419
|
-
emittedToolRoutedProfile = ctx.toolRoutedProfile;
|
|
420
|
-
const profileEntry = config.llm.profiles?.[ctx.toolRoutedProfile];
|
|
421
|
-
const label = profileEntry?.label ?? ctx.toolRoutedProfile;
|
|
422
|
-
broadcastMessage({
|
|
423
|
-
type: "turn_profile_auto_routed",
|
|
424
|
-
conversationId: ctx.conversationId,
|
|
425
|
-
profile: ctx.toolRoutedProfile,
|
|
426
|
-
profileLabel: label,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
|
|
430
405
|
ctx.currentTurnOverrideProfile = currentOverrideProfile;
|
|
431
406
|
return currentOverrideProfile;
|
|
432
407
|
};
|
|
@@ -505,6 +480,11 @@ export async function runAgentLoopImpl(
|
|
|
505
480
|
// resolved once here and threaded into every re-injection — including the
|
|
506
481
|
// post-compaction hook — rather than re-read per assembly call.
|
|
507
482
|
const isNonInteractive = !isInteractiveResolved;
|
|
483
|
+
// Expose the resolved turn-level interactivity to tool execution so tools
|
|
484
|
+
// (e.g. ask_question) see whether a human is present to answer, rather than
|
|
485
|
+
// re-deriving it from live client state that misclassifies a scheduled turn
|
|
486
|
+
// running on a client-attached conversation.
|
|
487
|
+
ctx.currentTurnIsNonInteractive = isNonInteractive;
|
|
508
488
|
const diskPressureDecision = classifyDiskPressureTurnPolicy(
|
|
509
489
|
getDiskPressureStatus(),
|
|
510
490
|
{
|
|
@@ -790,10 +770,7 @@ export async function runAgentLoopImpl(
|
|
|
790
770
|
// the post-compaction hook re-emits this same value during in-loop recovery
|
|
791
771
|
// instead of re-resolving against contact/member registry state that may
|
|
792
772
|
// have drifted mid-turn.
|
|
793
|
-
const actorContext = resolveTurnInboundActorContext(
|
|
794
|
-
ctx.trustContext,
|
|
795
|
-
ctx.assistantId,
|
|
796
|
-
);
|
|
773
|
+
const actorContext = resolveTurnInboundActorContext(ctx.trustContext);
|
|
797
774
|
ctx.currentTurnInboundActorContext = actorContext;
|
|
798
775
|
|
|
799
776
|
// Surface long gaps between user messages so the model can acknowledge
|
|
@@ -980,6 +957,7 @@ export async function runAgentLoopImpl(
|
|
|
980
957
|
compactInPlace,
|
|
981
958
|
isNonInteractive,
|
|
982
959
|
modelProfileKey,
|
|
960
|
+
...(ctx.modelOverride ? { model: ctx.modelOverride } : {}),
|
|
983
961
|
}),
|
|
984
962
|
abortController.signal,
|
|
985
963
|
watchdogMs,
|
|
@@ -1542,6 +1520,10 @@ export async function runAgentLoopImpl(
|
|
|
1542
1520
|
ctx.diskPressureCleanupModeActive = false;
|
|
1543
1521
|
ctx.preactivatedSkillIds = undefined;
|
|
1544
1522
|
ctx.currentTurnOverrideProfile = undefined;
|
|
1523
|
+
// Turn-scoped interactivity. Clear it so paths that bypass this loop (e.g.
|
|
1524
|
+
// opportunity wakes calling `agentLoop.run` directly) don't inherit a stale
|
|
1525
|
+
// value and instead fall back to live client state in the tool context.
|
|
1526
|
+
ctx.currentTurnIsNonInteractive = undefined;
|
|
1545
1527
|
// Channel command intents (e.g. Telegram /start) are single-turn metadata.
|
|
1546
1528
|
// Clear at turn end so they never leak into subsequent unrelated messages.
|
|
1547
1529
|
ctx.commandIntent = undefined;
|