@vellumai/assistant 0.10.0 → 0.10.1-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +36 -37
- package/bun.lock +3 -0
- package/docs/workflows.md +12 -7
- package/eslint-rules/cli-no-daemon-internals.js +6 -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__/trust-verdict-contract.test.ts +65 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -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 +78 -0
- package/openapi.yaml +345 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- 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 +3 -3
- 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 +143 -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 +1 -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__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +265 -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 +183 -51
- package/src/__tests__/config-schema.test.ts +34 -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 +3 -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 +6 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- 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 +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- 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 +26 -8
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/dm-backfill.test.ts +1 -1
- package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -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 +1 -1
- 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 +1 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -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 +98 -0
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- 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-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-usage-store.test.ts +40 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- 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 +1 -2
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -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__/persist-unsendable-image-downscale.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image.test.ts +1 -1
- package/src/__tests__/persona-resolver.test.ts +39 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
- package/src/__tests__/plugin-bootstrap.test.ts +78 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
- package/src/__tests__/provider-usage-tracking.test.ts +1 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/relay-server.test.ts +357 -56
- package/src/__tests__/runtime-attachment-metadata.test.ts +10 -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-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +1 -1
- 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__/slack-inbound-verification.test.ts +1 -3
- 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__/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 +32 -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 +2 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
- package/src/__tests__/usage-routes.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +34 -29
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +134 -36
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-git-service.test.ts +114 -1
- package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
- package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
- package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
- package/src/a2a/__tests__/task-store.test.ts +1 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
- package/src/acp/__tests__/session-manager.test.ts +72 -1
- package/src/acp/index.ts +10 -0
- package/src/acp/session-manager.ts +35 -0
- package/src/agent/loop.ts +45 -27
- package/src/api/index.ts +0 -6
- 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 +88 -62
- package/src/calls/inbound-trust-reader.ts +40 -0
- package/src/calls/relay-server.ts +65 -23
- package/src/calls/relay-setup-router.ts +20 -6
- package/src/calls/relay-verification.ts +7 -7
- 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/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/index.ts +2 -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/plugins.ts +268 -11
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- 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/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__/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/profile-dispatchability.ts +11 -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 +5 -3
- package/src/config/schemas/timeouts.ts +24 -0
- package/src/config/seed-inference-profiles.ts +133 -45
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/contact-store.ts +21 -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 +9 -36
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-tool-setup.ts +20 -63
- package/src/daemon/conversation.ts +144 -52
- package/src/daemon/event-loop-watchdog.test.ts +85 -0
- package/src/daemon/event-loop-watchdog.ts +133 -0
- package/src/daemon/external-plugins-bootstrap.ts +26 -80
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
- package/src/daemon/handlers/config-channels.ts +32 -18
- package/src/daemon/handlers/conversations.ts +7 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +16 -3
- 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 +18 -8
- package/src/daemon/server.ts +0 -4
- package/src/daemon/tool-setup-types.ts +0 -7
- 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__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +8 -0
- 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__/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/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 +31 -1
- 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/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 +227 -230
- 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 +50 -57
- 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__/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/validate-migration-state.ts +50 -145
- 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__/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__/sweep-job.test.ts +2 -2
- 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/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +14 -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__/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/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/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +29 -1
- 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 +146 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +21 -0
- 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 +149 -0
- package/src/plugin-api/vision-support.ts +78 -0
- package/src/plugins/defaults/compaction/window-manager.ts +45 -64
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +302 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +23 -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/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 +254 -185
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +6 -1
- package/src/providers/model-catalog.ts +37 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +10 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/guardian-decision-types.ts +3 -22
- 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/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- 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/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 +12 -1
- 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 +24 -3
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/inbound-message-handler.ts +20 -15
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/log-export-routes.ts +2 -2
- 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/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 +172 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
- package/src/tools/ask-question/ask-question-tool.ts +14 -73
- package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
- package/src/tools/browser/browser-execution.ts +16 -4
- package/src/tools/document/document-comment-tool.test.ts +1 -1
- package/src/tools/executor.ts +15 -3
- package/src/tools/host-terminal/host-shell.ts +28 -9
- package/src/tools/memory/register.test.ts +32 -0
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +4 -10
- package/src/tools/terminal/shell.ts +16 -5
- package/src/tools/types.ts +1 -0
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -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
|
@@ -224,8 +224,8 @@ function makePrompter(): PermissionPrompter {
|
|
|
224
224
|
|
|
225
225
|
import { initializeDb } from "../memory/db-init.js";
|
|
226
226
|
|
|
227
|
-
beforeAll(() => {
|
|
228
|
-
initializeDb();
|
|
227
|
+
beforeAll(async () => {
|
|
228
|
+
await initializeDb();
|
|
229
229
|
});
|
|
230
230
|
afterAll(() => {
|
|
231
231
|
mock.restore();
|
|
@@ -7,6 +7,36 @@ mock.module("../util/logger.js", () => ({
|
|
|
7
7
|
}),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
+
const gatewayIpc = {
|
|
11
|
+
claim: { ok: true, updated: true, mirrored: true } as {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
updated: boolean;
|
|
14
|
+
mirrored: boolean;
|
|
15
|
+
},
|
|
16
|
+
claimThrows: false,
|
|
17
|
+
calls: [] as { method: string; params?: Record<string, unknown> }[],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
mock.module("../ipc/gateway-client.js", () => ({
|
|
21
|
+
ipcCallPersistent: async (
|
|
22
|
+
method: string,
|
|
23
|
+
params?: Record<string, unknown>,
|
|
24
|
+
) => {
|
|
25
|
+
gatewayIpc.calls.push({ method, params });
|
|
26
|
+
if (method === "record_invite_redemption") {
|
|
27
|
+
if (gatewayIpc.claimThrows) throw new Error("gateway unreachable");
|
|
28
|
+
return gatewayIpc.claim;
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
function resetGatewayIpc() {
|
|
35
|
+
gatewayIpc.claim = { ok: true, updated: true, mirrored: true };
|
|
36
|
+
gatewayIpc.claimThrows = false;
|
|
37
|
+
gatewayIpc.calls = [];
|
|
38
|
+
}
|
|
39
|
+
|
|
10
40
|
import {
|
|
11
41
|
findContactChannel,
|
|
12
42
|
getContact,
|
|
@@ -19,7 +49,7 @@ import { createInvite, revokeInvite } from "../memory/invite-store.js";
|
|
|
19
49
|
import { redeemVoiceInviteCode } from "../runtime/invite-redemption-service.js";
|
|
20
50
|
import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
|
|
21
51
|
|
|
22
|
-
initializeDb();
|
|
52
|
+
await initializeDb();
|
|
23
53
|
|
|
24
54
|
function resetTables() {
|
|
25
55
|
getSqlite().run("DELETE FROM assistant_ingress_invites");
|
|
@@ -37,13 +67,13 @@ function createTargetContact(displayName = "Target Contact"): string {
|
|
|
37
67
|
// ---------------------------------------------------------------------------
|
|
38
68
|
|
|
39
69
|
describe("generateVoiceCode", () => {
|
|
40
|
-
test("generates a code with the default 6 digits", () => {
|
|
70
|
+
test("generates a code with the default 6 digits", async () => {
|
|
41
71
|
const code = generateVoiceCode();
|
|
42
72
|
expect(code.length).toBe(6);
|
|
43
73
|
expect(/^\d{6}$/.test(code)).toBe(true);
|
|
44
74
|
});
|
|
45
75
|
|
|
46
|
-
test("generates a code with the requested digit count", () => {
|
|
76
|
+
test("generates a code with the requested digit count", async () => {
|
|
47
77
|
for (const digits of [4, 5, 6, 7, 8, 9, 10]) {
|
|
48
78
|
const code = generateVoiceCode(digits);
|
|
49
79
|
expect(code.length).toBe(digits);
|
|
@@ -51,15 +81,15 @@ describe("generateVoiceCode", () => {
|
|
|
51
81
|
}
|
|
52
82
|
});
|
|
53
83
|
|
|
54
|
-
test("throws for digit count below 4", () => {
|
|
84
|
+
test("throws for digit count below 4", async () => {
|
|
55
85
|
expect(() => generateVoiceCode(3)).toThrow(/between 4 and 10/);
|
|
56
86
|
});
|
|
57
87
|
|
|
58
|
-
test("throws for digit count above 10", () => {
|
|
88
|
+
test("throws for digit count above 10", async () => {
|
|
59
89
|
expect(() => generateVoiceCode(11)).toThrow(/between 4 and 10/);
|
|
60
90
|
});
|
|
61
91
|
|
|
62
|
-
test("produces different codes across multiple calls (randomness)", () => {
|
|
92
|
+
test("produces different codes across multiple calls (randomness)", async () => {
|
|
63
93
|
// Generate many codes and check that we don't get the same one every time.
|
|
64
94
|
// With 6 digits there are 900,000 possibilities, so getting 10 identical
|
|
65
95
|
// codes would be astronomically unlikely.
|
|
@@ -71,7 +101,7 @@ describe("generateVoiceCode", () => {
|
|
|
71
101
|
expect(codes.size).toBeGreaterThanOrEqual(2);
|
|
72
102
|
});
|
|
73
103
|
|
|
74
|
-
test("generated code is within the valid numeric range", () => {
|
|
104
|
+
test("generated code is within the valid numeric range", async () => {
|
|
75
105
|
for (let i = 0; i < 20; i++) {
|
|
76
106
|
const code = generateVoiceCode(6);
|
|
77
107
|
const num = parseInt(code, 10);
|
|
@@ -87,20 +117,20 @@ describe("generateVoiceCode", () => {
|
|
|
87
117
|
// ---------------------------------------------------------------------------
|
|
88
118
|
|
|
89
119
|
describe("hashVoiceCode", () => {
|
|
90
|
-
test("produces a deterministic hash", () => {
|
|
120
|
+
test("produces a deterministic hash", async () => {
|
|
91
121
|
const code = "123456";
|
|
92
122
|
const hash1 = hashVoiceCode(code);
|
|
93
123
|
const hash2 = hashVoiceCode(code);
|
|
94
124
|
expect(hash1).toBe(hash2);
|
|
95
125
|
});
|
|
96
126
|
|
|
97
|
-
test("produces a hex-encoded SHA-256 hash (64 chars)", () => {
|
|
127
|
+
test("produces a hex-encoded SHA-256 hash (64 chars)", async () => {
|
|
98
128
|
const hash = hashVoiceCode("654321");
|
|
99
129
|
expect(hash.length).toBe(64);
|
|
100
130
|
expect(/^[0-9a-f]{64}$/.test(hash)).toBe(true);
|
|
101
131
|
});
|
|
102
132
|
|
|
103
|
-
test("different codes produce different hashes", () => {
|
|
133
|
+
test("different codes produce different hashes", async () => {
|
|
104
134
|
const hash1 = hashVoiceCode("111111");
|
|
105
135
|
const hash2 = hashVoiceCode("222222");
|
|
106
136
|
expect(hash1).not.toBe(hash2);
|
|
@@ -112,7 +142,10 @@ describe("hashVoiceCode", () => {
|
|
|
112
142
|
// ---------------------------------------------------------------------------
|
|
113
143
|
|
|
114
144
|
describe("redeemVoiceInviteCode", () => {
|
|
115
|
-
beforeEach(
|
|
145
|
+
beforeEach(() => {
|
|
146
|
+
resetTables();
|
|
147
|
+
resetGatewayIpc();
|
|
148
|
+
});
|
|
116
149
|
|
|
117
150
|
/**
|
|
118
151
|
* Helper: create a voice invite with a known code and return the
|
|
@@ -147,11 +180,11 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
147
180
|
return { invite, code };
|
|
148
181
|
}
|
|
149
182
|
|
|
150
|
-
test("happy path: correct caller + correct code redeems successfully", () => {
|
|
183
|
+
test("happy path: correct caller + correct code redeems successfully", async () => {
|
|
151
184
|
const phone = "+15551234567";
|
|
152
185
|
const { code } = createVoiceInvite({ callerPhone: phone });
|
|
153
186
|
|
|
154
|
-
const result = redeemVoiceInviteCode({
|
|
187
|
+
const result = await redeemVoiceInviteCode({
|
|
155
188
|
callerExternalUserId: phone,
|
|
156
189
|
sourceChannel: "phone",
|
|
157
190
|
code,
|
|
@@ -164,13 +197,73 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
164
197
|
memberId: expect.any(String),
|
|
165
198
|
inviteId: expect.any(String),
|
|
166
199
|
});
|
|
200
|
+
|
|
201
|
+
// The redemption claimed the gateway-canonical row before mutating.
|
|
202
|
+
const claim = gatewayIpc.calls.find(
|
|
203
|
+
(c) => c.method === "record_invite_redemption",
|
|
204
|
+
);
|
|
205
|
+
expect(claim).toBeDefined();
|
|
206
|
+
expect(claim!.params).toMatchObject({ redeemedByExternalUserId: phone });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("rejects voice redemption when the gateway claim is not consumable (no mutation)", async () => {
|
|
210
|
+
const phone = "+15551234567";
|
|
211
|
+
const { code } = createVoiceInvite({ callerPhone: phone });
|
|
212
|
+
|
|
213
|
+
// Gateway row exists but was NOT consumable (revoked/exhausted/raced).
|
|
214
|
+
gatewayIpc.claim = { ok: true, updated: false, mirrored: true };
|
|
215
|
+
|
|
216
|
+
const result = await redeemVoiceInviteCode({
|
|
217
|
+
callerExternalUserId: phone,
|
|
218
|
+
sourceChannel: "phone",
|
|
219
|
+
code,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
223
|
+
expect(findContactChannel({ channelType: "phone", address: phone })).toBeNull();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("proceeds for a legacy voice invite the gateway has never seen (mirrored:false)", async () => {
|
|
227
|
+
const phone = "+15551234567";
|
|
228
|
+
const { code } = createVoiceInvite({ callerPhone: phone });
|
|
229
|
+
|
|
230
|
+
gatewayIpc.claim = { ok: true, updated: false, mirrored: false };
|
|
231
|
+
|
|
232
|
+
const result = await redeemVoiceInviteCode({
|
|
233
|
+
callerExternalUserId: phone,
|
|
234
|
+
sourceChannel: "phone",
|
|
235
|
+
code,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
expect(result.ok).toBe(true);
|
|
239
|
+
expect(
|
|
240
|
+
findContactChannel({ channelType: "phone", address: phone }),
|
|
241
|
+
).not.toBeNull();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("fails open when the gateway claim throws on voice redemption", async () => {
|
|
245
|
+
const phone = "+15551234567";
|
|
246
|
+
const { code } = createVoiceInvite({ callerPhone: phone });
|
|
247
|
+
|
|
248
|
+
gatewayIpc.claimThrows = true;
|
|
249
|
+
|
|
250
|
+
const result = await redeemVoiceInviteCode({
|
|
251
|
+
callerExternalUserId: phone,
|
|
252
|
+
sourceChannel: "phone",
|
|
253
|
+
code,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
expect(result.ok).toBe(true);
|
|
257
|
+
expect(
|
|
258
|
+
findContactChannel({ channelType: "phone", address: phone }),
|
|
259
|
+
).not.toBeNull();
|
|
167
260
|
});
|
|
168
261
|
|
|
169
|
-
test("marks channel as verified via invite on voice redemption", () => {
|
|
262
|
+
test("marks channel as verified via invite on voice redemption", async () => {
|
|
170
263
|
const phone = "+15551234567";
|
|
171
264
|
const { code } = createVoiceInvite({ callerPhone: phone });
|
|
172
265
|
|
|
173
|
-
const result = redeemVoiceInviteCode({
|
|
266
|
+
const result = await redeemVoiceInviteCode({
|
|
174
267
|
callerExternalUserId: phone,
|
|
175
268
|
sourceChannel: "phone",
|
|
176
269
|
code,
|
|
@@ -189,10 +282,10 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
189
282
|
expect(channelResult!.channel.status).toBe("active");
|
|
190
283
|
});
|
|
191
284
|
|
|
192
|
-
test("wrong caller identity fails with generic error", () => {
|
|
285
|
+
test("wrong caller identity fails with generic error", async () => {
|
|
193
286
|
const { code } = createVoiceInvite({ callerPhone: "+15551234567" });
|
|
194
287
|
|
|
195
|
-
const result = redeemVoiceInviteCode({
|
|
288
|
+
const result = await redeemVoiceInviteCode({
|
|
196
289
|
callerExternalUserId: "+19999999999",
|
|
197
290
|
sourceChannel: "phone",
|
|
198
291
|
code,
|
|
@@ -201,10 +294,10 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
201
294
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
202
295
|
});
|
|
203
296
|
|
|
204
|
-
test("wrong code fails with generic error", () => {
|
|
297
|
+
test("wrong code fails with generic error", async () => {
|
|
205
298
|
createVoiceInvite({ callerPhone: "+15551234567" });
|
|
206
299
|
|
|
207
|
-
const result = redeemVoiceInviteCode({
|
|
300
|
+
const result = await redeemVoiceInviteCode({
|
|
208
301
|
callerExternalUserId: "+15551234567",
|
|
209
302
|
sourceChannel: "phone",
|
|
210
303
|
code: "000000",
|
|
@@ -213,11 +306,11 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
213
306
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
214
307
|
});
|
|
215
308
|
|
|
216
|
-
test("expired invite fails", () => {
|
|
309
|
+
test("expired invite fails", async () => {
|
|
217
310
|
const phone = "+15551234567";
|
|
218
311
|
const { code } = createVoiceInvite({ callerPhone: phone, expiresInMs: -1 });
|
|
219
312
|
|
|
220
|
-
const result = redeemVoiceInviteCode({
|
|
313
|
+
const result = await redeemVoiceInviteCode({
|
|
221
314
|
callerExternalUserId: phone,
|
|
222
315
|
sourceChannel: "phone",
|
|
223
316
|
code,
|
|
@@ -226,12 +319,12 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
226
319
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
227
320
|
});
|
|
228
321
|
|
|
229
|
-
test("max uses exhausted fails", () => {
|
|
322
|
+
test("max uses exhausted fails", async () => {
|
|
230
323
|
const phone = "+15551234567";
|
|
231
324
|
const { code } = createVoiceInvite({ callerPhone: phone, maxUses: 1 });
|
|
232
325
|
|
|
233
326
|
// First redemption succeeds
|
|
234
|
-
const first = redeemVoiceInviteCode({
|
|
327
|
+
const first = await redeemVoiceInviteCode({
|
|
235
328
|
callerExternalUserId: phone,
|
|
236
329
|
sourceChannel: "phone",
|
|
237
330
|
code,
|
|
@@ -239,7 +332,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
239
332
|
expect(first.ok).toBe(true);
|
|
240
333
|
|
|
241
334
|
// Second redemption fails — max uses exhausted
|
|
242
|
-
const second = redeemVoiceInviteCode({
|
|
335
|
+
const second = await redeemVoiceInviteCode({
|
|
243
336
|
callerExternalUserId: phone,
|
|
244
337
|
sourceChannel: "phone",
|
|
245
338
|
code,
|
|
@@ -247,13 +340,13 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
247
340
|
expect(second).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
248
341
|
});
|
|
249
342
|
|
|
250
|
-
test("revoked invite fails", () => {
|
|
343
|
+
test("revoked invite fails", async () => {
|
|
251
344
|
const phone = "+15551234567";
|
|
252
345
|
const { invite, code } = createVoiceInvite({ callerPhone: phone });
|
|
253
346
|
|
|
254
347
|
revokeInvite(invite.id);
|
|
255
348
|
|
|
256
|
-
const result = redeemVoiceInviteCode({
|
|
349
|
+
const result = await redeemVoiceInviteCode({
|
|
257
350
|
callerExternalUserId: phone,
|
|
258
351
|
sourceChannel: "phone",
|
|
259
352
|
code,
|
|
@@ -262,7 +355,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
262
355
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
263
356
|
});
|
|
264
357
|
|
|
265
|
-
test("voice-only invite cannot be redeemed if sourceChannel on invite is not voice", () => {
|
|
358
|
+
test("voice-only invite cannot be redeemed if sourceChannel on invite is not voice", async () => {
|
|
266
359
|
// Create a non-voice invite with voice code metadata to simulate a
|
|
267
360
|
// hypothetical misconfiguration. The redemption service filters by
|
|
268
361
|
// sourceChannel='phone', so non-phone invites are invisible.
|
|
@@ -279,7 +372,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
279
372
|
voiceCodeDigits: 6,
|
|
280
373
|
});
|
|
281
374
|
|
|
282
|
-
const result = redeemVoiceInviteCode({
|
|
375
|
+
const result = await redeemVoiceInviteCode({
|
|
283
376
|
callerExternalUserId: "+15551234567",
|
|
284
377
|
sourceChannel: "phone",
|
|
285
378
|
code,
|
|
@@ -290,7 +383,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
290
383
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
291
384
|
});
|
|
292
385
|
|
|
293
|
-
test("already-member caller gets already_member outcome", () => {
|
|
386
|
+
test("already-member caller gets already_member outcome", async () => {
|
|
294
387
|
const phone = "+15551234567";
|
|
295
388
|
|
|
296
389
|
// Pre-create an active member for this phone on voice channel
|
|
@@ -307,7 +400,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
307
400
|
contactId: member!.contact.id,
|
|
308
401
|
});
|
|
309
402
|
|
|
310
|
-
const result = redeemVoiceInviteCode({
|
|
403
|
+
const result = await redeemVoiceInviteCode({
|
|
311
404
|
callerExternalUserId: phone,
|
|
312
405
|
sourceChannel: "phone",
|
|
313
406
|
code,
|
|
@@ -319,9 +412,14 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
319
412
|
type: "already_member",
|
|
320
413
|
memberId: expect.any(String),
|
|
321
414
|
});
|
|
415
|
+
|
|
416
|
+
// No gateway claim — already_member must not consume a use.
|
|
417
|
+
expect(
|
|
418
|
+
gatewayIpc.calls.some((c) => c.method === "record_invite_redemption"),
|
|
419
|
+
).toBe(false);
|
|
322
420
|
});
|
|
323
421
|
|
|
324
|
-
test("blocked member gets generic failure to avoid leaking membership status", () => {
|
|
422
|
+
test("blocked member gets generic failure to avoid leaking membership status", async () => {
|
|
325
423
|
const phone = "+15551234567";
|
|
326
424
|
|
|
327
425
|
// Pre-create a blocked member and find their contact
|
|
@@ -338,7 +436,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
338
436
|
contactId: member!.contact.id,
|
|
339
437
|
});
|
|
340
438
|
|
|
341
|
-
const result = redeemVoiceInviteCode({
|
|
439
|
+
const result = await redeemVoiceInviteCode({
|
|
342
440
|
callerExternalUserId: phone,
|
|
343
441
|
sourceChannel: "phone",
|
|
344
442
|
code,
|
|
@@ -347,8 +445,8 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
347
445
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
348
446
|
});
|
|
349
447
|
|
|
350
|
-
test("empty callerExternalUserId fails", () => {
|
|
351
|
-
const result = redeemVoiceInviteCode({
|
|
448
|
+
test("empty callerExternalUserId fails", async () => {
|
|
449
|
+
const result = await redeemVoiceInviteCode({
|
|
352
450
|
callerExternalUserId: "",
|
|
353
451
|
sourceChannel: "phone",
|
|
354
452
|
code: "123456",
|
|
@@ -357,7 +455,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
357
455
|
expect(result).toEqual({ ok: false, reason: "invalid_or_expired" });
|
|
358
456
|
});
|
|
359
457
|
|
|
360
|
-
test("binds redeemer to the invite's target contact, not the guardian, on voice redemption", () => {
|
|
458
|
+
test("binds redeemer to the invite's target contact, not the guardian, on voice redemption", async () => {
|
|
361
459
|
const phone = "+15559998888";
|
|
362
460
|
|
|
363
461
|
// Pre-create a guardian contact with a revoked phone channel
|
|
@@ -385,7 +483,7 @@ describe("redeemVoiceInviteCode", () => {
|
|
|
385
483
|
contactId: momContact.id,
|
|
386
484
|
});
|
|
387
485
|
|
|
388
|
-
const result = redeemVoiceInviteCode({
|
|
486
|
+
const result = await redeemVoiceInviteCode({
|
|
389
487
|
callerExternalUserId: phone,
|
|
390
488
|
sourceChannel: "phone",
|
|
391
489
|
code,
|
|
@@ -95,7 +95,7 @@ const { createScopedApprovalGrant } = _internal;
|
|
|
95
95
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
96
96
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
97
97
|
|
|
98
|
-
initializeDb();
|
|
98
|
+
await initializeDb();
|
|
99
99
|
|
|
100
100
|
// ---------------------------------------------------------------------------
|
|
101
101
|
// Mock session that triggers a confirmation_request on processMessage
|
|
@@ -47,7 +47,7 @@ import { initializeDb } from "../memory/db-init.js";
|
|
|
47
47
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
48
48
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
49
49
|
|
|
50
|
-
initializeDb();
|
|
50
|
+
await initializeDb();
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Build a session that emits multiple events via the onEvent callback,
|
|
@@ -69,6 +69,7 @@ describe("WorkspaceGitService", () => {
|
|
|
69
69
|
expect(content).toContain("*.sock");
|
|
70
70
|
expect(content).toContain("*.pid");
|
|
71
71
|
expect(content).toContain("session-token");
|
|
72
|
+
expect(content).toContain("plugins/*/node_modules/");
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
test("sets git identity correctly", async () => {
|
|
@@ -401,6 +402,30 @@ describe("WorkspaceGitService", () => {
|
|
|
401
402
|
expect(status.clean).toBe(false);
|
|
402
403
|
expect(status.staged).toContain("file.txt");
|
|
403
404
|
});
|
|
405
|
+
|
|
406
|
+
test("tolerates porcelain output larger than 1 MB without throwing", async () => {
|
|
407
|
+
const service = new WorkspaceGitService(testDir);
|
|
408
|
+
await service.ensureInitialized();
|
|
409
|
+
|
|
410
|
+
// git status --porcelain prints one line per untracked entry. Enough
|
|
411
|
+
// long-named entries push the output well past Node's 1 MB execFile
|
|
412
|
+
// maxBuffer; the streamed read must handle it without surfacing
|
|
413
|
+
// ERR_CHILD_PROCESS_STDIO_MAXBUFFER. Files live in the (tracked) root
|
|
414
|
+
// so git reports them individually instead of collapsing a dir.
|
|
415
|
+
const fileCount = 6000;
|
|
416
|
+
const pad = "a".repeat(200);
|
|
417
|
+
for (let i = 0; i < fileCount; i++) {
|
|
418
|
+
writeFileSync(
|
|
419
|
+
join(testDir, `f${String(i).padStart(6, "0")}-${pad}`),
|
|
420
|
+
"",
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const status = await service.getStatus();
|
|
425
|
+
|
|
426
|
+
expect(status.clean).toBe(false);
|
|
427
|
+
expect(status.untracked.length).toBe(fileCount);
|
|
428
|
+
});
|
|
404
429
|
});
|
|
405
430
|
|
|
406
431
|
describe("mutex locking", () => {
|
|
@@ -805,7 +830,7 @@ describe("WorkspaceGitService", () => {
|
|
|
805
830
|
cwd: testDir,
|
|
806
831
|
});
|
|
807
832
|
const gitignoreContent =
|
|
808
|
-
"# Runtime state - excluded from git tracking\ndata/db/\ndata/qdrant/\nlogs/\n*.log\n*.sock\n*.pid\n*.sqlite\n*.sqlite-journal\n*.sqlite-wal\n*.sqlite-shm\n*.db\n*.db-journal\n*.db-wal\n*.db-shm\nvellum.pid\nsession-token\n";
|
|
833
|
+
"# Runtime state - excluded from git tracking\ndata/db/\ndata/qdrant/\nplugins/*/node_modules/\nlogs/\n*.log\n*.sock\n*.pid\n*.sqlite\n*.sqlite-journal\n*.sqlite-wal\n*.sqlite-shm\n*.db\n*.db-journal\n*.db-wal\n*.db-shm\nvellum.pid\nsession-token\n";
|
|
809
834
|
writeFileSync(join(testDir, ".gitignore"), gitignoreContent);
|
|
810
835
|
writeFileSync(join(testDir, "file.txt"), "content");
|
|
811
836
|
execFileSync("git", ["add", "-A"], { cwd: testDir });
|
|
@@ -906,6 +931,54 @@ describe("WorkspaceGitService", () => {
|
|
|
906
931
|
expect(status.untracked).toContain("config.json");
|
|
907
932
|
expect(status.untracked).toContain("README.md");
|
|
908
933
|
});
|
|
934
|
+
|
|
935
|
+
test("excludes plugin node_modules from computed status", async () => {
|
|
936
|
+
const service = new WorkspaceGitService(testDir);
|
|
937
|
+
await service.ensureInitialized();
|
|
938
|
+
|
|
939
|
+
// Track the plugin dir first so git reports finer-grained untracked
|
|
940
|
+
// entries — an entirely-untracked dir collapses to a single line and
|
|
941
|
+
// would hide whether node_modules was filtered.
|
|
942
|
+
mkdirSync(join(testDir, "plugins", "image-fallback"), {
|
|
943
|
+
recursive: true,
|
|
944
|
+
});
|
|
945
|
+
writeFileSync(
|
|
946
|
+
join(testDir, "plugins", "image-fallback", "index.js"),
|
|
947
|
+
"x",
|
|
948
|
+
);
|
|
949
|
+
await service.commitChanges("add plugin");
|
|
950
|
+
|
|
951
|
+
// Plugin dependencies (ignored) alongside a real source change.
|
|
952
|
+
mkdirSync(
|
|
953
|
+
join(testDir, "plugins", "image-fallback", "node_modules", "dep"),
|
|
954
|
+
{ recursive: true },
|
|
955
|
+
);
|
|
956
|
+
writeFileSync(
|
|
957
|
+
join(
|
|
958
|
+
testDir,
|
|
959
|
+
"plugins",
|
|
960
|
+
"image-fallback",
|
|
961
|
+
"node_modules",
|
|
962
|
+
"dep",
|
|
963
|
+
"big.js",
|
|
964
|
+
),
|
|
965
|
+
"module.exports = {}",
|
|
966
|
+
);
|
|
967
|
+
writeFileSync(
|
|
968
|
+
join(testDir, "plugins", "image-fallback", "other.js"),
|
|
969
|
+
"y",
|
|
970
|
+
);
|
|
971
|
+
|
|
972
|
+
const status = await service.getStatus();
|
|
973
|
+
|
|
974
|
+
const allEntries = [
|
|
975
|
+
...status.staged,
|
|
976
|
+
...status.modified,
|
|
977
|
+
...status.untracked,
|
|
978
|
+
];
|
|
979
|
+
expect(allEntries.some((f) => f.includes("node_modules"))).toBe(false);
|
|
980
|
+
expect(status.untracked).toContain("plugins/image-fallback/other.js");
|
|
981
|
+
});
|
|
909
982
|
});
|
|
910
983
|
|
|
911
984
|
describe("deadline-aware commitIfDirty", () => {
|
|
@@ -1102,6 +1175,46 @@ describe("WorkspaceGitService", () => {
|
|
|
1102
1175
|
});
|
|
1103
1176
|
});
|
|
1104
1177
|
|
|
1178
|
+
describe("commitIfDirty status read resilience", () => {
|
|
1179
|
+
test("status read failure does not trip the circuit breaker", async () => {
|
|
1180
|
+
const service = new WorkspaceGitService(testDir);
|
|
1181
|
+
await service.ensureInitialized();
|
|
1182
|
+
|
|
1183
|
+
writeFileSync(join(testDir, "test.txt"), "content");
|
|
1184
|
+
|
|
1185
|
+
// Simulate an oversized/failed `git status` read by making the streamed
|
|
1186
|
+
// status call throw the way Node's maxBuffer overflow would.
|
|
1187
|
+
const proto = Object.getPrototypeOf(service);
|
|
1188
|
+
const originalStreaming = proto.execGitStreaming;
|
|
1189
|
+
proto.execGitStreaming = async function () {
|
|
1190
|
+
const err = new Error(
|
|
1191
|
+
"Git command failed: git status --porcelain\n" +
|
|
1192
|
+
"Error: stdout maxBuffer length exceeded",
|
|
1193
|
+
) as Error & { code?: string };
|
|
1194
|
+
err.code = "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
1195
|
+
throw err;
|
|
1196
|
+
};
|
|
1197
|
+
|
|
1198
|
+
try {
|
|
1199
|
+
const result = await service.commitIfDirty(() => ({
|
|
1200
|
+
message: "should not commit",
|
|
1201
|
+
}));
|
|
1202
|
+
// Degrades to "no commit this tick" rather than throwing.
|
|
1203
|
+
expect(result.committed).toBe(false);
|
|
1204
|
+
// Breaker stays closed so the next cycle still runs.
|
|
1205
|
+
expect(_getConsecutiveFailures(service)).toBe(0);
|
|
1206
|
+
} finally {
|
|
1207
|
+
proto.execGitStreaming = originalStreaming;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Once status recovers, auto-commit proceeds — it was never disabled.
|
|
1211
|
+
const recovered = await service.commitIfDirty(() => ({
|
|
1212
|
+
message: "after status recovery",
|
|
1213
|
+
}));
|
|
1214
|
+
expect(recovered.committed).toBe(true);
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1105
1218
|
describe("commitIfDirty diff error handling", () => {
|
|
1106
1219
|
test("non-1 exit code from git diff --cached --quiet is treated as an error", async () => {
|
|
1107
1220
|
const service = new WorkspaceGitService(testDir);
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
CommitMessageResult,
|
|
22
22
|
} from "../workspace/commit-message-provider.js";
|
|
23
23
|
import {
|
|
24
|
+
_getConsecutiveFailures,
|
|
24
25
|
_resetGitServiceRegistry,
|
|
25
26
|
WorkspaceGitService,
|
|
26
27
|
} from "../workspace/git-service.js";
|
|
@@ -89,6 +90,50 @@ describe("WorkspaceHeartbeatService", () => {
|
|
|
89
90
|
expect(result.skipped).toBe(1);
|
|
90
91
|
});
|
|
91
92
|
|
|
93
|
+
test("continues (does not circuit-break) when a status read fails", async () => {
|
|
94
|
+
writeFileSync(join(testDir, "dirty.txt"), "content");
|
|
95
|
+
|
|
96
|
+
// Force the streamed status read to fail the way a maxBuffer overflow
|
|
97
|
+
// over a bloated working tree would.
|
|
98
|
+
const proto = Object.getPrototypeOf(service);
|
|
99
|
+
const originalStreaming = proto.execGitStreaming;
|
|
100
|
+
proto.execGitStreaming = async function () {
|
|
101
|
+
const err = new Error("stdout maxBuffer length exceeded") as Error & {
|
|
102
|
+
code?: string;
|
|
103
|
+
};
|
|
104
|
+
err.code = "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
105
|
+
throw err;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const heartbeat = new WorkspaceHeartbeatService({
|
|
110
|
+
ageThresholdMs: 0,
|
|
111
|
+
fileThreshold: 1,
|
|
112
|
+
getServices: () => services,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const result = await heartbeat.check();
|
|
116
|
+
|
|
117
|
+
// The cycle is skipped, not failed — and the breaker stays closed.
|
|
118
|
+
expect(result.checked).toBe(1);
|
|
119
|
+
expect(result.failed).toBe(0);
|
|
120
|
+
expect(result.committed).toBe(0);
|
|
121
|
+
expect(_getConsecutiveFailures(service)).toBe(0);
|
|
122
|
+
} finally {
|
|
123
|
+
proto.execGitStreaming = originalStreaming;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Once status recovers, the still-dirty workspace auto-commits — the
|
|
127
|
+
// heartbeat was never disabled.
|
|
128
|
+
const recovered = new WorkspaceHeartbeatService({
|
|
129
|
+
ageThresholdMs: 0,
|
|
130
|
+
fileThreshold: 1,
|
|
131
|
+
getServices: () => services,
|
|
132
|
+
});
|
|
133
|
+
const recoveredResult = await recovered.check();
|
|
134
|
+
expect(recoveredResult.committed).toBe(1);
|
|
135
|
+
});
|
|
136
|
+
|
|
92
137
|
test("does not commit when changes are below age and file thresholds", async () => {
|
|
93
138
|
writeFileSync(join(testDir, "file.txt"), "content");
|
|
94
139
|
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
} from "../memory/schema.js";
|
|
51
51
|
import { backfillConversationDiskViewMigration } from "../workspace/migrations/009-backfill-conversation-disk-view.js";
|
|
52
52
|
|
|
53
|
-
initializeDb();
|
|
53
|
+
await initializeDb();
|
|
54
54
|
|
|
55
55
|
function resetTables() {
|
|
56
56
|
const db = getDb();
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
} from "../memory/schema.js";
|
|
52
52
|
import { repairConversationDiskViewMigration } from "../workspace/migrations/013-repair-conversation-disk-view.js";
|
|
53
53
|
|
|
54
|
-
initializeDb();
|
|
54
|
+
await initializeDb();
|
|
55
55
|
|
|
56
56
|
function resetTables() {
|
|
57
57
|
const db = getDb();
|