@vellumai/assistant 0.10.3-dev.202606260318.2a238d5 → 0.10.3-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/openapi.yaml +55 -72
- package/package.json +1 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +31 -83
- package/src/__tests__/assistant-stream-state.test.ts +76 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -4
- package/src/__tests__/channel-approval-routes.test.ts +26 -21
- package/src/__tests__/channel-delivery-store.test.ts +0 -28
- package/src/__tests__/channel-guardian.test.ts +32 -82
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +19 -11
- package/src/__tests__/channel-reply-delivery.test.ts +2 -6
- package/src/__tests__/config-loader-backfill.test.ts +0 -148
- package/src/__tests__/contact-store-user-file.test.ts +10 -7
- package/src/__tests__/contacts-relay-reads.test.ts +9 -6
- package/src/__tests__/contacts-write.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -4
- package/src/__tests__/conversation-agent-loop.test.ts +7 -98
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -9
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +24 -354
- package/src/__tests__/delete-propagation.test.ts +3 -5
- package/src/__tests__/dm-backfill.test.ts +4 -6
- package/src/__tests__/emit-signal-routing-intent.test.ts +6 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +23 -43
- package/src/__tests__/guardian-dispatch.test.ts +5 -50
- package/src/__tests__/guardian-routing-state.test.ts +10 -6
- package/src/__tests__/helpers/channel-test-adapter.ts +12 -45
- package/src/__tests__/helpers/create-guardian-binding.ts +23 -15
- package/src/__tests__/helpers/mock-logger.ts +0 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +10 -87
- package/src/__tests__/invite-redemption-service.test.ts +53 -273
- package/src/__tests__/invite-routes-http.test.ts +0 -34
- package/src/__tests__/invite-service-ipc.test.ts +2 -65
- package/src/__tests__/list-messages-page-latest.test.ts +4 -173
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +13 -15
- package/src/__tests__/onboarding-persona-write.test.ts +22 -52
- package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +45 -75
- package/src/__tests__/plugin-bootstrap.test.ts +5 -13
- package/src/__tests__/provider-usage-tracking.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +4 -51
- package/src/__tests__/relay-server.test.ts +31 -88
- package/src/__tests__/runtime-attachment-metadata.test.ts +11 -9
- package/src/__tests__/settings-routes.test.ts +0 -32
- package/src/__tests__/slack-block-formatting.test.ts +38 -1
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +36 -13
- package/src/__tests__/stt-hints.test.ts +3 -6
- package/src/__tests__/subagent-fork-spawn.test.ts +7 -6
- package/src/__tests__/subagent-role-registry.test.ts +4 -17
- package/src/__tests__/subagent-tools.test.ts +3 -398
- package/src/__tests__/thread-backfill.test.ts +3 -3
- package/src/__tests__/tool-preview-lifecycle.test.ts +10 -26
- package/src/__tests__/tool-start-timestamp.test.ts +3 -4
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +51 -37
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -2
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +7 -9
- package/src/__tests__/trusted-contact-multichannel.test.ts +7 -16
- package/src/__tests__/trusted-contact-verification.test.ts +54 -79
- package/src/__tests__/voice-invite-redemption.test.ts +20 -183
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +3 -3
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +2 -2
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +238 -196
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +47 -35
- package/src/agent/loop-exclusive-tool.test.ts +15 -19
- package/src/agent/loop.ts +1 -108
- package/src/api/responses/conversation-message.ts +0 -9
- package/src/approvals/guardian-request-resolvers.ts +4 -16
- package/src/calls/__tests__/relay-setup-router.test.ts +18 -10
- package/src/calls/guardian-dispatch.ts +11 -14
- package/src/calls/inbound-trust-reader.ts +1 -7
- package/src/calls/relay-access-wait.ts +6 -6
- package/src/calls/relay-server.ts +2 -22
- package/src/calls/relay-setup-router.ts +10 -10
- package/src/cli/commands/__tests__/conversations-slack.test.ts +0 -1
- package/src/cli/commands/contacts.ts +7 -10
- package/src/cli/commands/memory/__tests__/worker.test.ts +17 -147
- package/src/cli/commands/memory/worker.ts +30 -97
- package/src/cli/commands/plugins.ts +146 -3
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +17 -17
- package/src/cli/lib/__tests__/publish-plugin.test.ts +0 -98
- package/src/cli/lib/publish-plugin.ts +1 -231
- package/src/config/__tests__/sync-gated-profiles.test.ts +7 -5
- package/src/config/bundled-skills/subagent/SKILL.md +1 -16
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -5
- package/src/config/call-site-defaults.ts +6 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/heartbeat.ts +5 -2
- package/src/config/schemas/llm.ts +12 -3
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/seed-inference-profiles.ts +35 -76
- package/src/config/sync-gated-profiles.ts +3 -0
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +8 -7
- package/src/contacts/__tests__/member-write-relay.test.ts +11 -35
- package/src/contacts/contact-store.ts +237 -27
- package/src/contacts/contacts-write.ts +58 -18
- package/src/contacts/member-write-relay.ts +31 -25
- package/src/contacts/types.ts +15 -3
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -29
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +10 -7
- package/src/daemon/conversation-tool-setup.ts +10 -0
- package/src/daemon/conversation.ts +0 -10
- package/src/daemon/external-plugins-bootstrap.ts +2 -8
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -0
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +2 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +2 -0
- package/src/daemon/handlers/__tests__/config-channels.test.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +29 -14
- package/src/daemon/lifecycle.ts +4 -16
- package/src/daemon/message-types/surfaces.ts +0 -2
- package/src/heartbeat/heartbeat-service.ts +0 -5
- package/src/home/relationship-state-writer.ts +0 -5
- package/src/memory/conversation-crud.ts +61 -136
- package/src/memory/jobs-worker.ts +29 -75
- package/src/memory/memory-retrospective-job.ts +0 -5
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +5 -27
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +6 -79
- package/src/memory/schema/contacts.ts +2 -6
- package/src/memory/schema/conversations.ts +0 -39
- package/src/memory/steps.ts +367 -1090
- package/src/memory/worker-control.ts +18 -104
- package/src/memory/worker-process.ts +0 -17
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +0 -11
- package/src/messaging/providers/a2a/deliver.ts +1 -5
- package/src/messaging/providers/index.ts +241 -65
- package/src/notifications/__tests__/broadcaster.test.ts +8 -0
- package/src/notifications/__tests__/connected-channels.test.ts +36 -8
- package/src/notifications/__tests__/destination-resolver.test.ts +117 -12
- package/src/notifications/destination-resolver.ts +23 -7
- package/src/notifications/emit-signal.ts +11 -5
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +314 -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/__tests__/hooks.test.ts +138 -0
- package/src/{subagent/__tests__/consult-transcript.test.ts → plugins/defaults/advisor/__tests__/transcript.test.ts} +10 -47
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +197 -0
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/{subagent/consult-prompt.ts → plugins/defaults/advisor/steering.ts} +39 -17
- package/src/plugins/defaults/advisor/tools/advisor.ts +92 -0
- package/src/{subagent/consult-transcript.ts → plugins/defaults/advisor/transcript.ts} +8 -18
- package/src/plugins/defaults/index.ts +35 -0
- package/src/plugins/registry.ts +12 -55
- package/src/prompts/persona-resolver.ts +11 -43
- package/src/providers/call-site-routing.ts +0 -41
- package/src/providers/provider-send-message.ts +0 -6
- package/src/providers/ratelimit.ts +0 -6
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +0 -6
- package/src/providers/types.ts +0 -13
- package/src/providers/usage-tracking.ts +0 -6
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +27 -30
- package/src/runtime/__tests__/local-principal-trust.test.ts +18 -16
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +168 -115
- package/src/runtime/access-request-helper.ts +2 -1
- package/src/runtime/actor-trust-resolver.ts +17 -44
- package/src/runtime/anchored-guardian.test.ts +54 -7
- package/src/runtime/anchored-guardian.ts +53 -4
- package/src/runtime/assistant-stream-state.ts +74 -12
- package/src/runtime/channel-reply-delivery.ts +8 -3
- package/src/runtime/guardian-vellum-migration.ts +16 -18
- package/src/runtime/invite-redemption-service.ts +10 -25
- package/src/runtime/local-actor-identity.ts +20 -27
- package/src/runtime/routes/__tests__/contact-routes.test.ts +7 -100
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +2 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -2
- package/src/runtime/routes/contact-routes.ts +25 -40
- package/src/runtime/routes/conversation-list-routes.ts +29 -1
- package/src/runtime/routes/conversation-routes.ts +7 -27
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +10 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +8 -4
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +0 -19
- package/src/runtime/routes/settings-routes.ts +3 -8
- package/src/runtime/services/conversation-serializer.ts +49 -6
- package/src/runtime/slack-block-formatting.ts +15 -0
- package/src/runtime/trust-verdict-consumer.ts +41 -36
- package/src/subagent/index.ts +1 -1
- package/src/subagent/manager.ts +33 -245
- package/src/subagent/types.ts +1 -8
- package/src/tools/registry.ts +3 -10
- package/src/tools/subagent/spawn.ts +5 -234
- package/src/util/logger.ts +0 -9
- package/src/util/platform.ts +0 -14
- package/src/workspace/migrations/031-drop-user-md.ts +148 -232
- package/src/workspace/migrations/registry.ts +0 -2
- package/src/__tests__/compaction-ledger-store.test.ts +0 -128
- package/src/__tests__/consult-deadline.test.ts +0 -60
- package/src/__tests__/contact-store-interaction-info.test.ts +0 -156
- package/src/__tests__/db-compaction-events-migration.test.ts +0 -129
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -96
- package/src/__tests__/plugin-disabled-state.test.ts +0 -190
- package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +0 -135
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -158
- package/src/__tests__/subagent-fork-prompt-role.test.ts +0 -195
- package/src/__tests__/subagent-spawn-and-await.test.ts +0 -546
- package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +0 -137
- package/src/__tests__/workspace-migration-112-remove-advisor-callsite-override.test.ts +0 -170
- package/src/agent/loop-native-web-search.test.ts +0 -200
- package/src/contacts/gateway-channel-read.ts +0 -51
- package/src/memory/compaction-ledger-store.ts +0 -107
- package/src/memory/migrations/302-create-compaction-events.ts +0 -107
- package/src/memory/migrations/303-add-conversation-creation-seq.ts +0 -33
- package/src/messaging/channel-binding-metadata.ts +0 -31
- package/src/messaging/channel-binding-schema.ts +0 -51
- package/src/messaging/providers/__tests__/callback-routing.test.ts +0 -45
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +0 -195
- package/src/messaging/providers/a2a/transport.ts +0 -10
- package/src/messaging/providers/callback-routing.ts +0 -48
- package/src/messaging/providers/channel-transport.ts +0 -55
- package/src/messaging/providers/slack/binding-metadata.ts +0 -62
- package/src/messaging/providers/slack/transport.ts +0 -92
- package/src/messaging/providers/telegram-bot/transport.ts +0 -51
- package/src/messaging/providers/whatsapp/transport.ts +0 -38
- package/src/plugins/disabled-state.ts +0 -31
- package/src/runtime/__tests__/member-verdict-cache.test.ts +0 -119
- package/src/runtime/local-actor-identity.test.ts +0 -108
- package/src/runtime/member-verdict-cache.ts +0 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +0 -35
- package/src/tools/subagent/consult-deadline.ts +0 -49
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +0 -64
package/openapi.yaml
CHANGED
|
@@ -4841,18 +4841,14 @@ paths:
|
|
|
4841
4841
|
type: string
|
|
4842
4842
|
role:
|
|
4843
4843
|
type: string
|
|
4844
|
-
enum:
|
|
4845
|
-
- guardian
|
|
4846
|
-
- contact
|
|
4847
4844
|
notes:
|
|
4848
4845
|
anyOf:
|
|
4849
4846
|
- type: string
|
|
4850
4847
|
- type: "null"
|
|
4851
4848
|
contactType:
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
-
|
|
4855
|
-
- assistant
|
|
4849
|
+
anyOf:
|
|
4850
|
+
- type: string
|
|
4851
|
+
- type: "null"
|
|
4856
4852
|
lastInteraction:
|
|
4857
4853
|
anyOf:
|
|
4858
4854
|
- type: number
|
|
@@ -4919,15 +4915,20 @@ paths:
|
|
|
4919
4915
|
- address
|
|
4920
4916
|
- isPrimary
|
|
4921
4917
|
- externalUserId
|
|
4918
|
+
- status
|
|
4919
|
+
- policy
|
|
4920
|
+
- verifiedAt
|
|
4921
|
+
- verifiedVia
|
|
4922
4922
|
- lastSeenAt
|
|
4923
4923
|
- interactionCount
|
|
4924
4924
|
- lastInteraction
|
|
4925
|
+
- revokedReason
|
|
4926
|
+
- blockedReason
|
|
4925
4927
|
additionalProperties: false
|
|
4926
4928
|
required:
|
|
4927
4929
|
- id
|
|
4928
4930
|
- displayName
|
|
4929
4931
|
- role
|
|
4930
|
-
- contactType
|
|
4931
4932
|
- interactionCount
|
|
4932
4933
|
- createdAt
|
|
4933
4934
|
- updatedAt
|
|
@@ -5001,18 +5002,14 @@ paths:
|
|
|
5001
5002
|
type: string
|
|
5002
5003
|
role:
|
|
5003
5004
|
type: string
|
|
5004
|
-
enum:
|
|
5005
|
-
- guardian
|
|
5006
|
-
- contact
|
|
5007
5005
|
notes:
|
|
5008
5006
|
anyOf:
|
|
5009
5007
|
- type: string
|
|
5010
5008
|
- type: "null"
|
|
5011
5009
|
contactType:
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
-
|
|
5015
|
-
- assistant
|
|
5010
|
+
anyOf:
|
|
5011
|
+
- type: string
|
|
5012
|
+
- type: "null"
|
|
5016
5013
|
lastInteraction:
|
|
5017
5014
|
anyOf:
|
|
5018
5015
|
- type: number
|
|
@@ -5079,15 +5076,20 @@ paths:
|
|
|
5079
5076
|
- address
|
|
5080
5077
|
- isPrimary
|
|
5081
5078
|
- externalUserId
|
|
5079
|
+
- status
|
|
5080
|
+
- policy
|
|
5081
|
+
- verifiedAt
|
|
5082
|
+
- verifiedVia
|
|
5082
5083
|
- lastSeenAt
|
|
5083
5084
|
- interactionCount
|
|
5084
5085
|
- lastInteraction
|
|
5086
|
+
- revokedReason
|
|
5087
|
+
- blockedReason
|
|
5085
5088
|
additionalProperties: false
|
|
5086
5089
|
required:
|
|
5087
5090
|
- id
|
|
5088
5091
|
- displayName
|
|
5089
5092
|
- role
|
|
5090
|
-
- contactType
|
|
5091
5093
|
- interactionCount
|
|
5092
5094
|
- createdAt
|
|
5093
5095
|
- updatedAt
|
|
@@ -5130,18 +5132,14 @@ paths:
|
|
|
5130
5132
|
type: string
|
|
5131
5133
|
role:
|
|
5132
5134
|
type: string
|
|
5133
|
-
enum:
|
|
5134
|
-
- guardian
|
|
5135
|
-
- contact
|
|
5136
5135
|
notes:
|
|
5137
5136
|
anyOf:
|
|
5138
5137
|
- type: string
|
|
5139
5138
|
- type: "null"
|
|
5140
5139
|
contactType:
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
-
|
|
5144
|
-
- assistant
|
|
5140
|
+
anyOf:
|
|
5141
|
+
- type: string
|
|
5142
|
+
- type: "null"
|
|
5145
5143
|
lastInteraction:
|
|
5146
5144
|
anyOf:
|
|
5147
5145
|
- type: number
|
|
@@ -5208,15 +5206,20 @@ paths:
|
|
|
5208
5206
|
- address
|
|
5209
5207
|
- isPrimary
|
|
5210
5208
|
- externalUserId
|
|
5209
|
+
- status
|
|
5210
|
+
- policy
|
|
5211
|
+
- verifiedAt
|
|
5212
|
+
- verifiedVia
|
|
5211
5213
|
- lastSeenAt
|
|
5212
5214
|
- interactionCount
|
|
5213
5215
|
- lastInteraction
|
|
5216
|
+
- revokedReason
|
|
5217
|
+
- blockedReason
|
|
5214
5218
|
additionalProperties: false
|
|
5215
5219
|
required:
|
|
5216
5220
|
- id
|
|
5217
5221
|
- displayName
|
|
5218
5222
|
- role
|
|
5219
|
-
- contactType
|
|
5220
5223
|
- interactionCount
|
|
5221
5224
|
- createdAt
|
|
5222
5225
|
- updatedAt
|
|
@@ -5504,18 +5507,14 @@ paths:
|
|
|
5504
5507
|
type: string
|
|
5505
5508
|
role:
|
|
5506
5509
|
type: string
|
|
5507
|
-
enum:
|
|
5508
|
-
- guardian
|
|
5509
|
-
- contact
|
|
5510
5510
|
notes:
|
|
5511
5511
|
anyOf:
|
|
5512
5512
|
- type: string
|
|
5513
5513
|
- type: "null"
|
|
5514
5514
|
contactType:
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
-
|
|
5518
|
-
- assistant
|
|
5515
|
+
anyOf:
|
|
5516
|
+
- type: string
|
|
5517
|
+
- type: "null"
|
|
5519
5518
|
lastInteraction:
|
|
5520
5519
|
anyOf:
|
|
5521
5520
|
- type: number
|
|
@@ -5582,15 +5581,20 @@ paths:
|
|
|
5582
5581
|
- address
|
|
5583
5582
|
- isPrimary
|
|
5584
5583
|
- externalUserId
|
|
5584
|
+
- status
|
|
5585
|
+
- policy
|
|
5586
|
+
- verifiedAt
|
|
5587
|
+
- verifiedVia
|
|
5585
5588
|
- lastSeenAt
|
|
5586
5589
|
- interactionCount
|
|
5587
5590
|
- lastInteraction
|
|
5591
|
+
- revokedReason
|
|
5592
|
+
- blockedReason
|
|
5588
5593
|
additionalProperties: false
|
|
5589
5594
|
required:
|
|
5590
5595
|
- id
|
|
5591
5596
|
- displayName
|
|
5592
5597
|
- role
|
|
5593
|
-
- contactType
|
|
5594
5598
|
- interactionCount
|
|
5595
5599
|
- createdAt
|
|
5596
5600
|
- updatedAt
|
|
@@ -5698,18 +5702,14 @@ paths:
|
|
|
5698
5702
|
type: string
|
|
5699
5703
|
role:
|
|
5700
5704
|
type: string
|
|
5701
|
-
enum:
|
|
5702
|
-
- guardian
|
|
5703
|
-
- contact
|
|
5704
5705
|
notes:
|
|
5705
5706
|
anyOf:
|
|
5706
5707
|
- type: string
|
|
5707
5708
|
- type: "null"
|
|
5708
5709
|
contactType:
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
-
|
|
5712
|
-
- assistant
|
|
5710
|
+
anyOf:
|
|
5711
|
+
- type: string
|
|
5712
|
+
- type: "null"
|
|
5713
5713
|
lastInteraction:
|
|
5714
5714
|
anyOf:
|
|
5715
5715
|
- type: number
|
|
@@ -5776,15 +5776,20 @@ paths:
|
|
|
5776
5776
|
- address
|
|
5777
5777
|
- isPrimary
|
|
5778
5778
|
- externalUserId
|
|
5779
|
+
- status
|
|
5780
|
+
- policy
|
|
5781
|
+
- verifiedAt
|
|
5782
|
+
- verifiedVia
|
|
5779
5783
|
- lastSeenAt
|
|
5780
5784
|
- interactionCount
|
|
5781
5785
|
- lastInteraction
|
|
5786
|
+
- revokedReason
|
|
5787
|
+
- blockedReason
|
|
5782
5788
|
additionalProperties: false
|
|
5783
5789
|
required:
|
|
5784
5790
|
- id
|
|
5785
5791
|
- displayName
|
|
5786
5792
|
- role
|
|
5787
|
-
- contactType
|
|
5788
5793
|
- interactionCount
|
|
5789
5794
|
- createdAt
|
|
5790
5795
|
- updatedAt
|
|
@@ -17426,30 +17431,6 @@ paths:
|
|
|
17426
17431
|
webUrl:
|
|
17427
17432
|
type: string
|
|
17428
17433
|
additionalProperties: false
|
|
17429
|
-
eventKind:
|
|
17430
|
-
type: string
|
|
17431
|
-
enum:
|
|
17432
|
-
- message
|
|
17433
|
-
- reaction
|
|
17434
|
-
reaction:
|
|
17435
|
-
type: object
|
|
17436
|
-
properties:
|
|
17437
|
-
emoji:
|
|
17438
|
-
type: string
|
|
17439
|
-
op:
|
|
17440
|
-
type: string
|
|
17441
|
-
enum:
|
|
17442
|
-
- added
|
|
17443
|
-
- removed
|
|
17444
|
-
actorDisplayName:
|
|
17445
|
-
type: string
|
|
17446
|
-
targetChannelTs:
|
|
17447
|
-
type: string
|
|
17448
|
-
required:
|
|
17449
|
-
- emoji
|
|
17450
|
-
- op
|
|
17451
|
-
- targetChannelTs
|
|
17452
|
-
additionalProperties: false
|
|
17453
17434
|
required:
|
|
17454
17435
|
- channelId
|
|
17455
17436
|
- channelTs
|
|
@@ -17486,14 +17467,6 @@ paths:
|
|
|
17486
17467
|
anyOf:
|
|
17487
17468
|
- type: number
|
|
17488
17469
|
- type: "null"
|
|
17489
|
-
processing:
|
|
17490
|
-
description:
|
|
17491
|
-
"Whether the agent is currently mid-turn for this conversation, sourced authoritatively from the persisted
|
|
17492
|
-
`processing_started_at` column. `true` means a turn is in flight; `false` means the conversation
|
|
17493
|
-
is idle. Clients use this to recover from a dropped SSE stream: if a turn appears to be running
|
|
17494
|
-
locally but the server reports `processing: false`, the turn has ended (or died) and the UI should
|
|
17495
|
-
stop waiting rather than spin indefinitely. Absent on older daemons that predate this field."
|
|
17496
|
-
type: boolean
|
|
17497
17470
|
required:
|
|
17498
17471
|
- messages
|
|
17499
17472
|
additionalProperties: false
|
|
@@ -29715,6 +29688,12 @@ components:
|
|
|
29715
29688
|
- $ref: "#/components/schemas/ProfileStatus"
|
|
29716
29689
|
- type: "null"
|
|
29717
29690
|
- type: "null"
|
|
29691
|
+
advisorEnabled:
|
|
29692
|
+
anyOf:
|
|
29693
|
+
- anyOf:
|
|
29694
|
+
- type: boolean
|
|
29695
|
+
- type: "null"
|
|
29696
|
+
- type: "null"
|
|
29718
29697
|
mix:
|
|
29719
29698
|
anyOf:
|
|
29720
29699
|
- minItems: 2
|
|
@@ -30442,6 +30421,10 @@ components:
|
|
|
30442
30421
|
anyOf:
|
|
30443
30422
|
- $ref: "#/components/schemas/ProfileStatus"
|
|
30444
30423
|
- type: "null"
|
|
30424
|
+
advisorEnabled:
|
|
30425
|
+
anyOf:
|
|
30426
|
+
- type: boolean
|
|
30427
|
+
- type: "null"
|
|
30445
30428
|
mix:
|
|
30446
30429
|
minItems: 2
|
|
30447
30430
|
type: array
|
package/package.json
CHANGED
|
@@ -7,18 +7,12 @@
|
|
|
7
7
|
* and are discovered through the same path as every other channel.
|
|
8
8
|
*
|
|
9
9
|
* This suite verifies that address-based lookup returns the correct
|
|
10
|
-
* `memberRecord` with the right
|
|
10
|
+
* `memberRecord` with the right channel/status so relay-setup-router
|
|
11
11
|
* can emit the appropriate outcome (e.g. `unverified_caller`).
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
15
15
|
|
|
16
|
-
import type {
|
|
17
|
-
ChannelPolicy,
|
|
18
|
-
ChannelStatus,
|
|
19
|
-
ContactRole,
|
|
20
|
-
} from "../contacts/types.js";
|
|
21
|
-
|
|
22
16
|
// ── Logger mock (suppress output) ───────────────────────────────────────────
|
|
23
17
|
mock.module("../util/logger.js", () => ({
|
|
24
18
|
getLogger: () =>
|
|
@@ -29,45 +23,18 @@ mock.module("../util/logger.js", () => ({
|
|
|
29
23
|
let _byAddress: ReturnType<
|
|
30
24
|
(typeof import("../contacts/contact-store.js"))["findContactByAddress"]
|
|
31
25
|
> = null;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{ status: "unverified", policy: "allow", role: "contact" };
|
|
26
|
+
let _guardian: ReturnType<
|
|
27
|
+
(typeof import("../contacts/contact-store.js"))["findGuardianForChannel"]
|
|
28
|
+
> = null;
|
|
36
29
|
|
|
37
30
|
mock.module("../contacts/contact-store.js", () => ({
|
|
38
31
|
findContactByAddress: (_type: string, _addr: string) => _byAddress,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// Guardian resolution reads the gateway delivery cache; these suites only
|
|
42
|
-
// exercise the member/address path, so the cache peek stays empty.
|
|
43
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
44
|
-
peekCachedGuardianDelivery: () => undefined,
|
|
45
|
-
guardianForChannel: () => undefined,
|
|
32
|
+
findGuardianForChannel: (_channel: string) => _guardian,
|
|
46
33
|
}));
|
|
47
34
|
|
|
48
35
|
// ── Real import after mocks ───────────────────────────────────────────────────
|
|
49
36
|
import type { ContactWithChannels } from "../contacts/types.js";
|
|
50
37
|
import { resolveActorTrust } from "../runtime/actor-trust-resolver.js";
|
|
51
|
-
import {
|
|
52
|
-
__resetMemberVerdictCacheForTest,
|
|
53
|
-
setMemberVerdict,
|
|
54
|
-
} from "../runtime/member-verdict-cache.js";
|
|
55
|
-
|
|
56
|
-
const CHANNEL_ID = "ch-test";
|
|
57
|
-
const CONTACT_ID = "contact-test";
|
|
58
|
-
|
|
59
|
-
// Seed the member-verdict cache so the sync fallback resolves the member with
|
|
60
|
-
// the configured ACL view (mirrors a warmed gateway verdict).
|
|
61
|
-
function seedAcl(): void {
|
|
62
|
-
setMemberVerdict("phone", PHONE, {
|
|
63
|
-
trustClass: _acl.role === "guardian" ? "guardian" : "unknown",
|
|
64
|
-
canonicalSenderId: PHONE,
|
|
65
|
-
contactId: CONTACT_ID,
|
|
66
|
-
channelId: CHANNEL_ID,
|
|
67
|
-
status: _acl.status,
|
|
68
|
-
policy: _acl.policy,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
38
|
|
|
72
39
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
73
40
|
|
|
@@ -77,14 +44,13 @@ function makeContact(
|
|
|
77
44
|
role: "guardian" | "contact" = "contact",
|
|
78
45
|
status: "unverified" | "active" = "unverified",
|
|
79
46
|
): ContactWithChannels {
|
|
80
|
-
|
|
81
|
-
// record the intended view so seedAcl() warms it before resolution.
|
|
82
|
-
_acl = { status, policy: "allow", role };
|
|
47
|
+
const channelId = "ch-test";
|
|
83
48
|
return {
|
|
84
|
-
id:
|
|
49
|
+
id: "contact-test",
|
|
85
50
|
displayName: "Patrick Test",
|
|
86
|
-
notes: null,
|
|
87
51
|
role,
|
|
52
|
+
principalId: null,
|
|
53
|
+
notes: null,
|
|
88
54
|
lastInteraction: null,
|
|
89
55
|
interactionCount: 0,
|
|
90
56
|
contactType: "human" as const,
|
|
@@ -93,16 +59,22 @@ function makeContact(
|
|
|
93
59
|
updatedAt: 0,
|
|
94
60
|
channels: [
|
|
95
61
|
{
|
|
96
|
-
id:
|
|
97
|
-
contactId:
|
|
62
|
+
id: channelId,
|
|
63
|
+
contactId: "contact-test",
|
|
98
64
|
type: "phone",
|
|
99
65
|
address: PHONE,
|
|
100
66
|
externalChatId: null,
|
|
101
67
|
isPrimary: true,
|
|
102
|
-
|
|
103
|
-
|
|
68
|
+
status,
|
|
69
|
+
policy: "allow",
|
|
70
|
+
verifiedAt: null,
|
|
71
|
+
verifiedVia: null,
|
|
72
|
+
revokedReason: null,
|
|
73
|
+
blockedReason: null,
|
|
104
74
|
interactionCount: 0,
|
|
105
75
|
lastInteraction: null,
|
|
76
|
+
lastSeenAt: null,
|
|
77
|
+
inviteId: null,
|
|
106
78
|
createdAt: 0,
|
|
107
79
|
updatedAt: 0,
|
|
108
80
|
},
|
|
@@ -115,14 +87,12 @@ function makeContact(
|
|
|
115
87
|
describe("resolveActorTrust — address fallback", () => {
|
|
116
88
|
beforeEach(() => {
|
|
117
89
|
_byAddress = null;
|
|
118
|
-
|
|
119
|
-
__resetMemberVerdictCacheForTest();
|
|
90
|
+
_guardian = null;
|
|
120
91
|
});
|
|
121
92
|
|
|
122
93
|
test("finds unverified channel via address when externalUserId is null", () => {
|
|
123
94
|
// Simulate a contact registered by name-capture: address set, externalUserId null.
|
|
124
95
|
_byAddress = makeContact("contact", "unverified");
|
|
125
|
-
seedAcl();
|
|
126
96
|
|
|
127
97
|
const result = resolveActorTrust({
|
|
128
98
|
assistantId: "asst-1",
|
|
@@ -133,7 +103,7 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
133
103
|
|
|
134
104
|
expect(result.memberRecord).not.toBeNull();
|
|
135
105
|
expect(result.memberRecord?.contact.displayName).toBe("Patrick Test");
|
|
136
|
-
expect(result.memberRecord?.status).toBe("unverified");
|
|
106
|
+
expect(result.memberRecord?.channel.status).toBe("unverified");
|
|
137
107
|
// trustClass is 'unverified_contact' for a member whose channel is
|
|
138
108
|
// pending or unverified — known to the guardian but not yet verified.
|
|
139
109
|
expect(result.trustClass).toBe("unverified_contact");
|
|
@@ -141,7 +111,6 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
141
111
|
|
|
142
112
|
test("address lookup is the sole member resolution path", () => {
|
|
143
113
|
_byAddress = makeContact("contact", "active");
|
|
144
|
-
seedAcl();
|
|
145
114
|
|
|
146
115
|
const result = resolveActorTrust({
|
|
147
116
|
assistantId: "asst-1",
|
|
@@ -150,7 +119,7 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
150
119
|
actorExternalId: PHONE,
|
|
151
120
|
});
|
|
152
121
|
|
|
153
|
-
expect(result.memberRecord?.status).toBe("active");
|
|
122
|
+
expect(result.memberRecord?.channel.status).toBe("active");
|
|
154
123
|
expect(result.memberRecord?.channel.address).toBe(PHONE);
|
|
155
124
|
});
|
|
156
125
|
|
|
@@ -168,28 +137,10 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
168
137
|
expect(result.trustClass).toBe("unknown");
|
|
169
138
|
});
|
|
170
139
|
|
|
171
|
-
test("fail-closed: contact found but verdict cache miss → unknown", () => {
|
|
172
|
-
// The sync fallback runs only when there is no live verdict; with no cached
|
|
173
|
-
// verdict either, the member stays unresolved and trust is fail-closed.
|
|
174
|
-
_byAddress = makeContact("contact", "active");
|
|
175
|
-
// No seedAcl() — the cache is a miss for this sender.
|
|
176
|
-
|
|
177
|
-
const result = resolveActorTrust({
|
|
178
|
-
assistantId: "asst-1",
|
|
179
|
-
sourceChannel: "phone",
|
|
180
|
-
conversationExternalId: PHONE,
|
|
181
|
-
actorExternalId: PHONE,
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
expect(result.memberRecord).toBeNull();
|
|
185
|
-
expect(result.trustClass).toBe("unknown");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
140
|
test("address-found active channel elevates trust to trusted_contact", () => {
|
|
189
141
|
// An active channel found via address (e.g. after manual verify without externalUserId set)
|
|
190
142
|
// should still yield trusted_contact trust class.
|
|
191
143
|
_byAddress = makeContact("contact", "active");
|
|
192
|
-
seedAcl();
|
|
193
144
|
|
|
194
145
|
const result = resolveActorTrust({
|
|
195
146
|
assistantId: "asst-1",
|
|
@@ -199,7 +150,7 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
199
150
|
});
|
|
200
151
|
|
|
201
152
|
expect(result.memberRecord).not.toBeNull();
|
|
202
|
-
expect(result.memberRecord?.status).toBe("active");
|
|
153
|
+
expect(result.memberRecord?.channel.status).toBe("active");
|
|
203
154
|
expect(result.trustClass).toBe("trusted_contact");
|
|
204
155
|
});
|
|
205
156
|
|
|
@@ -207,10 +158,9 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
207
158
|
// Mirrors the unverified branch but for `pending` status (e.g. a phone
|
|
208
159
|
// contact registered by name-capture awaiting the DTMF challenge).
|
|
209
160
|
const contact = makeContact("contact", "unverified");
|
|
210
|
-
// Override
|
|
211
|
-
|
|
161
|
+
// Override status to "pending" — makeContact only accepts unverified/active
|
|
162
|
+
contact.channels[0]!.status = "pending";
|
|
212
163
|
_byAddress = contact;
|
|
213
|
-
seedAcl();
|
|
214
164
|
|
|
215
165
|
const result = resolveActorTrust({
|
|
216
166
|
assistantId: "asst-1",
|
|
@@ -219,17 +169,16 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
219
169
|
actorExternalId: PHONE,
|
|
220
170
|
});
|
|
221
171
|
|
|
222
|
-
expect(result.memberRecord?.status).toBe("pending");
|
|
172
|
+
expect(result.memberRecord?.channel.status).toBe("pending");
|
|
223
173
|
expect(result.trustClass).toBe("unverified_contact");
|
|
224
174
|
});
|
|
225
175
|
|
|
226
176
|
test("blocked-status member is classified as unknown (not unverified_contact)", () => {
|
|
227
177
|
// Hard-deny statuses (blocked, revoked) stay `unknown` — admission-layer
|
|
228
|
-
// re-checks channel
|
|
178
|
+
// re-checks channel.status and emits the hard-deny reasons.
|
|
229
179
|
const contact = makeContact("contact", "unverified");
|
|
230
|
-
|
|
180
|
+
contact.channels[0]!.status = "blocked";
|
|
231
181
|
_byAddress = contact;
|
|
232
|
-
seedAcl();
|
|
233
182
|
|
|
234
183
|
const result = resolveActorTrust({
|
|
235
184
|
assistantId: "asst-1",
|
|
@@ -238,15 +187,14 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
238
187
|
actorExternalId: PHONE,
|
|
239
188
|
});
|
|
240
189
|
|
|
241
|
-
expect(result.memberRecord?.status).toBe("blocked");
|
|
190
|
+
expect(result.memberRecord?.channel.status).toBe("blocked");
|
|
242
191
|
expect(result.trustClass).toBe("unknown");
|
|
243
192
|
});
|
|
244
193
|
|
|
245
194
|
test("revoked-status member is classified as unknown", () => {
|
|
246
195
|
const contact = makeContact("contact", "unverified");
|
|
247
|
-
|
|
196
|
+
contact.channels[0]!.status = "revoked";
|
|
248
197
|
_byAddress = contact;
|
|
249
|
-
seedAcl();
|
|
250
198
|
|
|
251
199
|
const result = resolveActorTrust({
|
|
252
200
|
assistantId: "asst-1",
|
|
@@ -255,7 +203,7 @@ describe("resolveActorTrust — address fallback", () => {
|
|
|
255
203
|
actorExternalId: PHONE,
|
|
256
204
|
});
|
|
257
205
|
|
|
258
|
-
expect(result.memberRecord?.status).toBe("revoked");
|
|
206
|
+
expect(result.memberRecord?.channel.status).toBe("revoked");
|
|
259
207
|
expect(result.trustClass).toBe("unknown");
|
|
260
208
|
});
|
|
261
209
|
});
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
_resetStreamStateForTesting,
|
|
13
13
|
_simulateRestartForTesting,
|
|
14
14
|
getCurrentSeq,
|
|
15
|
+
getPersistedSeq,
|
|
15
16
|
getReplayWindow,
|
|
17
|
+
recordPersistedSeq,
|
|
16
18
|
stampAndBuffer,
|
|
17
19
|
} from "../runtime/assistant-stream-state.js";
|
|
18
20
|
|
|
@@ -569,9 +571,80 @@ describe("assistant-stream-state", () => {
|
|
|
569
571
|
});
|
|
570
572
|
});
|
|
571
573
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
574
|
+
describe("persisted seq", () => {
|
|
575
|
+
test("getPersistedSeq is null for an unknown conversation", () => {
|
|
576
|
+
expect(getPersistedSeq("conv_unknown")).toBeNull();
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
test("records and retrieves a per-conversation value", () => {
|
|
580
|
+
recordPersistedSeq("conv_a", 7);
|
|
581
|
+
expect(getPersistedSeq("conv_a")).toBe(7);
|
|
582
|
+
expect(getPersistedSeq("conv_b")).toBeNull();
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test("tracks conversations independently", () => {
|
|
586
|
+
recordPersistedSeq("conv_a", 3);
|
|
587
|
+
recordPersistedSeq("conv_b", 9);
|
|
588
|
+
expect(getPersistedSeq("conv_a")).toBe(3);
|
|
589
|
+
expect(getPersistedSeq("conv_b")).toBe(9);
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
test("advances monotonically and never regresses", () => {
|
|
593
|
+
recordPersistedSeq("conv_a", 5);
|
|
594
|
+
recordPersistedSeq("conv_a", 12);
|
|
595
|
+
expect(getPersistedSeq("conv_a")).toBe(12);
|
|
596
|
+
|
|
597
|
+
// A lower seq (e.g. an out-of-order async commit) is clamped.
|
|
598
|
+
recordPersistedSeq("conv_a", 8);
|
|
599
|
+
expect(getPersistedSeq("conv_a")).toBe(12);
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
test("ignores non-positive and non-finite seq values", () => {
|
|
603
|
+
recordPersistedSeq("conv_a", 0);
|
|
604
|
+
recordPersistedSeq("conv_a", -3);
|
|
605
|
+
recordPersistedSeq("conv_a", Number.NaN);
|
|
606
|
+
recordPersistedSeq("conv_a", Number.POSITIVE_INFINITY);
|
|
607
|
+
expect(getPersistedSeq("conv_a")).toBeNull();
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
test("is cleared by reset", () => {
|
|
611
|
+
recordPersistedSeq("conv_a", 4);
|
|
612
|
+
_resetStreamStateForTesting();
|
|
613
|
+
expect(getPersistedSeq("conv_a")).toBeNull();
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test("evicts the least-recently-recorded conversation past the cap", () => {
|
|
617
|
+
// The map is LRU-bounded at 1024 conversations. Fill to the cap,
|
|
618
|
+
// then one more insert evicts the oldest key.
|
|
619
|
+
const CAP = 1024;
|
|
620
|
+
for (let i = 0; i < CAP; i++) {
|
|
621
|
+
recordPersistedSeq(`conv_${i}`, i + 1);
|
|
622
|
+
}
|
|
623
|
+
// All present at the cap.
|
|
624
|
+
expect(getPersistedSeq("conv_0")).toBe(1);
|
|
625
|
+
expect(getPersistedSeq(`conv_${CAP - 1}`)).toBe(CAP);
|
|
626
|
+
|
|
627
|
+
// One more distinct conversation evicts the oldest (conv_0).
|
|
628
|
+
recordPersistedSeq("conv_overflow", 9999);
|
|
629
|
+
expect(getPersistedSeq("conv_0")).toBeNull();
|
|
630
|
+
expect(getPersistedSeq("conv_1")).toBe(2);
|
|
631
|
+
expect(getPersistedSeq("conv_overflow")).toBe(9999);
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
test("re-recording refreshes recency so a kept key is not evicted first", () => {
|
|
635
|
+
const CAP = 1024;
|
|
636
|
+
for (let i = 0; i < CAP; i++) {
|
|
637
|
+
recordPersistedSeq(`conv_${i}`, i + 1);
|
|
638
|
+
}
|
|
639
|
+
// Touch the oldest key so it moves to the most-recent end.
|
|
640
|
+
recordPersistedSeq("conv_0", 5000);
|
|
641
|
+
|
|
642
|
+
// The next insert now evicts conv_1 (the new oldest), not conv_0.
|
|
643
|
+
recordPersistedSeq("conv_overflow", 9999);
|
|
644
|
+
expect(getPersistedSeq("conv_0")).toBe(5000);
|
|
645
|
+
expect(getPersistedSeq("conv_1")).toBeNull();
|
|
646
|
+
});
|
|
647
|
+
});
|
|
575
648
|
|
|
576
649
|
describe("seq persistence across restarts", () => {
|
|
577
650
|
test("counter resumes above the persisted reservation after a restart", () => {
|
|
@@ -100,10 +100,8 @@ mock.module("../daemon/process-message.js", () => ({
|
|
|
100
100
|
|
|
101
101
|
const createdConversations: Array<{ conversationType: string }> = [];
|
|
102
102
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
recordConversationPersistedSeq: () => {},
|
|
106
|
-
getConversationPersistedSeq: () => null,
|
|
103
|
+
setConversationProcessingStartedAt: () => {},
|
|
104
|
+
isConversationProcessing: () => false,
|
|
107
105
|
addMessage: mock(() => ({ id: "msg-1" })),
|
|
108
106
|
archiveConversation: mock(() => true),
|
|
109
107
|
batchSetDisplayOrders: mock(() => {}),
|