@vellumai/assistant 0.10.12-dev.202607250140.9979030 → 0.10.12-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/README.md +1 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/openapi.yaml +4 -14
- package/package.json +1 -1
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +11 -13
- package/src/__tests__/assistant-event-hub.test.ts +11 -13
- package/src/__tests__/assistant-event.test.ts +9 -12
- package/src/__tests__/assistant-id-boundary-guard.test.ts +58 -0
- package/src/__tests__/assistant-stream-state.test.ts +3 -5
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/channel-approvals.test.ts +27 -0
- package/src/__tests__/channel-guardian.test.ts +512 -85
- package/src/__tests__/channel-readiness-slack-remote.test.ts +3 -151
- package/src/__tests__/channel-setup-panel-ack.test.ts +9 -12
- package/src/__tests__/chat-reveal-guard-priming.test.ts +28 -28
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-backfill.test.ts +5 -4
- package/src/__tests__/config-loader-platform-defaults.test.ts +28 -54
- package/src/__tests__/config-model-image-provider.test.ts +0 -20
- package/src/__tests__/config-schema.test.ts +1 -12
- package/src/__tests__/config-set-platform-guard.test.ts +12 -11
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +3 -3
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +12 -12
- package/src/__tests__/conversation-agent-loop.test.ts +29 -29
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +4 -4
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-runtime-assembly.test.ts +0 -27
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +16 -18
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +4 -7
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -8
- package/src/__tests__/conversation-surfaces-table-action.test.ts +3 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/daemon-assistant-events.test.ts +15 -15
- package/src/__tests__/emit-event-signal.test.ts +6 -6
- package/src/__tests__/events-tail-route.test.ts +4 -6
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +8 -65
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/log-redact.test.ts +0 -18
- package/src/__tests__/managed-profile-guard.test.ts +0 -27
- package/src/__tests__/media-generate-image.test.ts +11 -62
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/plugin-event-hub-facade.test.ts +15 -18
- package/src/__tests__/provider-platform-proxy-integration.test.ts +1 -0
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +3 -3
- package/src/__tests__/runtime-events-sse-parity.test.ts +10 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +2 -2
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/secret-patterns.test.ts +27 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-scanner.test.ts +0 -36
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/starter-task-flow.test.ts +3 -6
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +10 -10
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +10 -10
- package/src/__tests__/subagent-spawn-and-await.test.ts +13 -13
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/tool-preview-lifecycle.test.ts +28 -28
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/voice-session-bridge.ts +7 -7
- package/src/cli/commands/config.ts +8 -23
- package/src/cli/lib/bundled-marketplace.json +0 -12
- package/src/cli.ts +109 -2
- package/src/config/__tests__/default-profile-catalog.test.ts +0 -9
- package/src/config/__tests__/deployment-context-defaults.test.ts +0 -9
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -13
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/loader.ts +1 -7
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-v3.ts +0 -8
- package/src/config/schemas/services.ts +2 -10
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +0 -23
- package/src/daemon/conversation-agent-loop-handlers.ts +3 -3
- package/src/daemon/conversation-agent-loop.ts +4 -4
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +4 -4
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +0 -11
- package/src/daemon/conversation-surfaces.ts +4 -4
- package/src/daemon/conversation-tool-setup.ts +3 -3
- package/src/daemon/conversation-usage.ts +11 -11
- package/src/daemon/conversation.ts +11 -11
- package/src/daemon/handlers/config-channels.ts +134 -40
- package/src/daemon/handlers/config-model.ts +7 -15
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/message-protocol.ts +143 -16
- package/src/daemon/message-types/acp.ts +20 -0
- package/src/daemon/message-types/apps.ts +11 -0
- package/src/daemon/message-types/background-tools.ts +14 -0
- package/src/daemon/message-types/bookmarks.ts +13 -0
- package/src/daemon/message-types/computer-use.ts +12 -0
- package/src/daemon/message-types/contacts.ts +13 -0
- package/src/daemon/message-types/conversations.ts +345 -9
- package/src/daemon/message-types/document-comments.ts +14 -0
- package/src/daemon/message-types/documents.ts +13 -0
- package/src/daemon/message-types/home.ts +15 -0
- package/src/daemon/message-types/host-app-control.ts +9 -0
- package/src/daemon/message-types/host-bash.ts +12 -0
- package/src/daemon/message-types/host-browser.ts +7 -0
- package/src/daemon/message-types/host-cu.ts +10 -0
- package/src/daemon/message-types/host-file.ts +12 -0
- package/src/daemon/message-types/host-transfer.ts +12 -0
- package/src/daemon/message-types/host-ui-snapshot.ts +7 -0
- package/src/daemon/message-types/integrations.ts +90 -0
- package/src/daemon/message-types/memory.ts +10 -0
- package/src/daemon/message-types/messages.ts +48 -0
- package/src/daemon/message-types/notifications.ts +7 -0
- package/src/daemon/message-types/schedules.ts +14 -0
- package/src/daemon/message-types/settings.ts +17 -0
- package/src/daemon/message-types/skills.ts +5 -0
- package/src/daemon/message-types/subagents.ts +63 -0
- package/src/daemon/message-types/surfaces.ts +9 -0
- package/src/daemon/message-types/sync.ts +2 -0
- package/src/daemon/message-types/upgrades.ts +14 -0
- package/src/daemon/message-types/workflows.ts +25 -0
- package/src/daemon/message-types/workspace.ts +137 -0
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/tool-side-effects.ts +10 -10
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/events-ipc-routes.ts +3 -3
- package/src/media/app-icon-generator.ts +8 -15
- package/src/media/avatar-router.ts +5 -9
- package/src/media/image-credentials.ts +10 -42
- package/src/media/image-service.ts +13 -1
- package/src/media/types.ts +3 -26
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +4 -6
- package/src/plugin-api/index.ts +4 -17
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +28 -28
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +2 -180
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +0 -3
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +0 -1
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +0 -1
- package/src/plugins/defaults/memory/v3/orchestrate.ts +15 -97
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +0 -1
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +0 -3
- package/src/plugins/defaults/memory/v3/types.ts +1 -4
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +12 -104
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +12 -104
- package/src/plugins/types.ts +2 -2
- package/src/providers/__tests__/registry-native-web-search.test.ts +1 -0
- package/src/providers/anthropic/client.ts +9 -11
- package/src/providers/inference/connections.ts +14 -30
- package/src/providers/model-catalog.ts +0 -51
- package/src/providers/registry.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +18 -18
- package/src/runtime/assistant-event.ts +11 -23
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +25 -0
- package/src/runtime/channel-readiness-service.ts +7 -105
- package/src/runtime/channel-retry-sweep.ts +2 -2
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/conversation-query-routes.ts +6 -35
- package/src/runtime/routes/conversation-routes.ts +2 -8
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +9 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/workspace-routes.test.ts +2 -2
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +5 -7
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +0 -17
- package/src/security/secret-ingress.ts +105 -14
- package/src/security/secret-patterns.ts +139 -8
- package/src/security/secret-scanner.ts +3 -8
- package/src/signals/emit-event.ts +3 -3
- package/src/signals/event-stream.ts +5 -5
- package/src/subagent/manager.ts +15 -15
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/util/log-redact.ts +3 -7
- package/src/workflows/leaf-runner.ts +5 -5
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
- package/src/__tests__/slack-required-scopes-mirror.test.ts +0 -81
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +0 -284
- package/src/daemon/__tests__/channel-ui-capability.test.ts +0 -26
- package/src/plugin-api/__tests__/publish-event.test.ts +0 -54
- package/src/plugin-api/publish-event.ts +0 -39
- package/src/plugins/defaults/memory/v3/span-query.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/span-query.ts +0 -71
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +0 -87
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +0 -128
package/README.md
CHANGED
|
@@ -145,7 +145,7 @@ All approval prompt delivery paths use a **fail-closed** policy -- if the prompt
|
|
|
145
145
|
|
|
146
146
|
### Plain-Text Fallback for Non-Rich Channels
|
|
147
147
|
|
|
148
|
-
Channels that do not support rich inline approval UI (e.g., inline keyboards) receive plain-text instructions embedded in the message body. The `
|
|
148
|
+
Channels that do not support rich inline approval UI (e.g., inline keyboards) receive plain-text instructions embedded in the message body. The `channelSupportsRichApprovalUI()` check determines whether to send the structured `promptText` (for rich channels like Telegram) or the `plainTextFallback` string (for all other channels). The fallback text includes instructions so the user can respond via text; the conversational approval engine then classifies the free-text response.
|
|
149
149
|
|
|
150
150
|
### Key modules
|
|
151
151
|
|
package/openapi.yaml
CHANGED
|
@@ -19356,12 +19356,6 @@ paths:
|
|
|
19356
19356
|
- low
|
|
19357
19357
|
- medium
|
|
19358
19358
|
- high
|
|
19359
|
-
bypassSecretCheck:
|
|
19360
|
-
description:
|
|
19361
|
-
When true, skip the secret-ingress scan for this message only. Set exclusively when the user explicitly
|
|
19362
|
-
confirms a client-side blocked send (the composer's "Send anyway" action); it is per-message and
|
|
19363
|
-
never persisted.
|
|
19364
|
-
type: boolean
|
|
19365
19359
|
hidden:
|
|
19366
19360
|
description:
|
|
19367
19361
|
"When true, persist the user message but suppress it from the UI transcript (it stays in LLM-side history
|
|
@@ -32459,10 +32453,8 @@ components:
|
|
|
32459
32453
|
anyOf:
|
|
32460
32454
|
- type: object
|
|
32461
32455
|
properties:
|
|
32462
|
-
|
|
32463
|
-
|
|
32464
|
-
model:
|
|
32465
|
-
type: string
|
|
32456
|
+
mode:
|
|
32457
|
+
$ref: "#/components/schemas/ServiceMode"
|
|
32466
32458
|
additionalProperties: {}
|
|
32467
32459
|
- type: "null"
|
|
32468
32460
|
inference:
|
|
@@ -33273,10 +33265,8 @@ components:
|
|
|
33273
33265
|
image-generation:
|
|
33274
33266
|
type: object
|
|
33275
33267
|
properties:
|
|
33276
|
-
|
|
33277
|
-
|
|
33278
|
-
model:
|
|
33279
|
-
type: string
|
|
33268
|
+
mode:
|
|
33269
|
+
$ref: "#/components/schemas/ServiceMode"
|
|
33280
33270
|
additionalProperties: {}
|
|
33281
33271
|
inference:
|
|
33282
33272
|
type: object
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import { VellumAcpClientHandler } from "../acp/client-handler.js";
|
|
4
4
|
import { AcpSessionManager } from "../acp/session-manager.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
6
6
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
7
7
|
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
@@ -10,8 +10,8 @@ import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
|
|
12
12
|
describe("VellumAcpClientHandler", () => {
|
|
13
|
-
let sent:
|
|
14
|
-
let sendToVellum: (msg:
|
|
13
|
+
let sent: ServerMessage[];
|
|
14
|
+
let sendToVellum: (msg: ServerMessage) => void;
|
|
15
15
|
let handler: VellumAcpClientHandler;
|
|
16
16
|
|
|
17
17
|
beforeEach(() => {
|
|
@@ -11,7 +11,7 @@ import { Minimatch } from "minimatch";
|
|
|
11
11
|
import { CompactionCircuit } from "../agent/compaction-circuit.js";
|
|
12
12
|
import type { AgentEvent } from "../agent/loop.js";
|
|
13
13
|
import type { ConfirmationStateChangedEvent } from "../api/events/confirmation-state-changed.js";
|
|
14
|
-
import type {
|
|
14
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
15
15
|
import type { Message, ProviderResponse } from "../providers/types.js";
|
|
16
16
|
import type { ConfirmationDetails } from "../runtime/pending-interactions.js";
|
|
17
17
|
|
|
@@ -188,7 +188,7 @@ function makeProvider() {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function makeConversation(
|
|
191
|
-
sendToClient?: (msg:
|
|
191
|
+
sendToClient?: (msg: ServerMessage) => void,
|
|
192
192
|
conversationId = CONV_ID,
|
|
193
193
|
): Conversation {
|
|
194
194
|
return new Conversation(
|
|
@@ -257,7 +257,7 @@ beforeEach(() => {
|
|
|
257
257
|
|
|
258
258
|
describe("approval cascading", () => {
|
|
259
259
|
test("allow (one-time) does NOT cascade", () => {
|
|
260
|
-
const emitted:
|
|
260
|
+
const emitted: ServerMessage[] = [];
|
|
261
261
|
const conversationObj = makeConversation(
|
|
262
262
|
(msg) => emitted.push(msg),
|
|
263
263
|
CONV_ID,
|
|
@@ -291,7 +291,7 @@ describe("approval cascading", () => {
|
|
|
291
291
|
});
|
|
292
292
|
|
|
293
293
|
test("deny (one-time) does NOT cascade", () => {
|
|
294
|
-
const emitted:
|
|
294
|
+
const emitted: ServerMessage[] = [];
|
|
295
295
|
const conversationObj = makeConversation(
|
|
296
296
|
(msg) => emitted.push(msg),
|
|
297
297
|
CONV_ID,
|
|
@@ -325,7 +325,7 @@ describe("approval cascading", () => {
|
|
|
325
325
|
});
|
|
326
326
|
|
|
327
327
|
test("already-resolved request handled gracefully", () => {
|
|
328
|
-
const emitted:
|
|
328
|
+
const emitted: ServerMessage[] = [];
|
|
329
329
|
const conversationObj = makeConversation(
|
|
330
330
|
(msg) => emitted.push(msg),
|
|
331
331
|
CONV_ID,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
8
8
|
|
|
9
9
|
import type { Conversation } from "../daemon/conversation.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
11
11
|
import type { SecretPromptResult } from "../permissions/secret-prompt-types.js";
|
|
12
12
|
|
|
13
13
|
mock.module("../config/env.js", () => ({
|
|
@@ -123,7 +123,7 @@ function makeIdleSession(opts?: {
|
|
|
123
123
|
runAgentLoop: async (
|
|
124
124
|
_content: string,
|
|
125
125
|
_messageId: string,
|
|
126
|
-
options?: { onEvent?: (msg:
|
|
126
|
+
options?: { onEvent?: (msg: ServerMessage) => void },
|
|
127
127
|
) => {
|
|
128
128
|
const onEvent = options?.onEvent ?? (() => {});
|
|
129
129
|
onEvent({ type: "assistant_text_delta", text: "Hello!" });
|
|
@@ -186,7 +186,7 @@ function makeConfirmationEmittingSession(opts?: {
|
|
|
186
186
|
runAgentLoop: async (
|
|
187
187
|
_content: string,
|
|
188
188
|
_messageId: string,
|
|
189
|
-
options?: { onEvent?: (msg:
|
|
189
|
+
options?: { onEvent?: (msg: ServerMessage) => void },
|
|
190
190
|
) => {
|
|
191
191
|
const onEvent = options?.onEvent ?? (() => {});
|
|
192
192
|
// Simulate PermissionPrompter.prompt(): self-register in pendingInteractions
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { describe, expect, test } from "bun:test";
|
|
16
16
|
|
|
17
|
-
import type {
|
|
17
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
18
18
|
import {
|
|
19
19
|
AssistantEventHub,
|
|
20
20
|
assistantEventHub,
|
|
21
21
|
broadcastMessage,
|
|
22
22
|
} from "../runtime/assistant-event-hub.js";
|
|
23
23
|
|
|
24
|
-
function makeSyncChangedEvent(originClientId?: string):
|
|
24
|
+
function makeSyncChangedEvent(originClientId?: string): AssistantEvent {
|
|
25
25
|
return {
|
|
26
26
|
id: "evt_test_sync",
|
|
27
27
|
conversationId: undefined,
|
|
@@ -37,9 +37,9 @@ function makeSyncChangedEvent(originClientId?: string): AssistantEventEnvelope {
|
|
|
37
37
|
describe("AssistantEventHub — self-echo suppression (excludeClientId)", () => {
|
|
38
38
|
test("skips the named client and delivers to every other client", async () => {
|
|
39
39
|
const hub = new AssistantEventHub();
|
|
40
|
-
const receivedA:
|
|
41
|
-
const receivedB:
|
|
42
|
-
const receivedC:
|
|
40
|
+
const receivedA: AssistantEvent[] = [];
|
|
41
|
+
const receivedB: AssistantEvent[] = [];
|
|
42
|
+
const receivedC: AssistantEvent[] = [];
|
|
43
43
|
|
|
44
44
|
hub.subscribe({
|
|
45
45
|
type: "client",
|
|
@@ -82,8 +82,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
82
82
|
|
|
83
83
|
test("delivers to every subscriber when excludeClientId is omitted", async () => {
|
|
84
84
|
const hub = new AssistantEventHub();
|
|
85
|
-
const receivedA:
|
|
86
|
-
const receivedB:
|
|
85
|
+
const receivedA: AssistantEvent[] = [];
|
|
86
|
+
const receivedB: AssistantEvent[] = [];
|
|
87
87
|
|
|
88
88
|
hub.subscribe({
|
|
89
89
|
type: "client",
|
|
@@ -112,7 +112,7 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
112
112
|
|
|
113
113
|
test("excludeClientId does not match process-type subscribers", async () => {
|
|
114
114
|
const hub = new AssistantEventHub();
|
|
115
|
-
const receivedProcess:
|
|
115
|
+
const receivedProcess: AssistantEvent[] = [];
|
|
116
116
|
|
|
117
117
|
// A process subscriber sits in the same hub as a client whose id
|
|
118
118
|
// matches `excludeClientId`. It must never be suppressed because
|
|
@@ -134,8 +134,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
134
134
|
|
|
135
135
|
test("excludeClientId composes with conversation-scoped subscribers", async () => {
|
|
136
136
|
const hub = new AssistantEventHub();
|
|
137
|
-
const receivedA:
|
|
138
|
-
const receivedB:
|
|
137
|
+
const receivedA: AssistantEvent[] = [];
|
|
138
|
+
const receivedB: AssistantEvent[] = [];
|
|
139
139
|
|
|
140
140
|
hub.subscribe({
|
|
141
141
|
type: "client",
|
|
@@ -159,7 +159,7 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
// Scoped event for sess_x; both clients filter to sess_x; exclude A.
|
|
162
|
-
const event:
|
|
162
|
+
const event: AssistantEvent = {
|
|
163
163
|
id: "evt_scoped",
|
|
164
164
|
conversationId: "sess_x",
|
|
165
165
|
emittedAt: "2026-05-03T00:00:00.000Z",
|
|
@@ -179,8 +179,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
179
179
|
|
|
180
180
|
describe("broadcastMessage — derives excludeClientId from sync_changed.originClientId", () => {
|
|
181
181
|
test("skips the originating client when originClientId is present", async () => {
|
|
182
|
-
const receivedA:
|
|
183
|
-
const receivedB:
|
|
182
|
+
const receivedA: AssistantEvent[] = [];
|
|
183
|
+
const receivedB: AssistantEvent[] = [];
|
|
184
184
|
|
|
185
185
|
const subA = assistantEventHub.subscribe({
|
|
186
186
|
type: "client",
|
|
@@ -221,8 +221,8 @@ describe("broadcastMessage — derives excludeClientId from sync_changed.originC
|
|
|
221
221
|
});
|
|
222
222
|
|
|
223
223
|
test("fans out to every client when originClientId is absent", async () => {
|
|
224
|
-
const receivedA:
|
|
225
|
-
const receivedB:
|
|
224
|
+
const receivedA: AssistantEvent[] = [];
|
|
225
|
+
const receivedB: AssistantEvent[] = [];
|
|
226
226
|
|
|
227
227
|
const subA = assistantEventHub.subscribe({
|
|
228
228
|
type: "client",
|
|
@@ -260,7 +260,7 @@ describe("broadcastMessage — derives excludeClientId from sync_changed.originC
|
|
|
260
260
|
});
|
|
261
261
|
|
|
262
262
|
test("ignores an empty-string originClientId (treats as absent)", async () => {
|
|
263
|
-
const receivedA:
|
|
263
|
+
const receivedA: AssistantEvent[] = [];
|
|
264
264
|
|
|
265
265
|
const subA = assistantEventHub.subscribe({
|
|
266
266
|
type: "client",
|
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { describe, expect, test } from "bun:test";
|
|
15
15
|
|
|
16
|
-
import type {
|
|
16
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
17
17
|
import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
18
18
|
|
|
19
|
-
function makeEvent(
|
|
20
|
-
overrides: Partial<AssistantEventEnvelope> = {},
|
|
21
|
-
): AssistantEventEnvelope {
|
|
19
|
+
function makeEvent(overrides: Partial<AssistantEvent> = {}): AssistantEvent {
|
|
22
20
|
return {
|
|
23
21
|
id: "evt_test",
|
|
24
22
|
conversationId: "sess_web",
|
|
@@ -37,8 +35,8 @@ function makeEvent(
|
|
|
37
35
|
describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
38
36
|
test("delivers only to the named client, bypassing conversation filter", async () => {
|
|
39
37
|
const hub = new AssistantEventHub();
|
|
40
|
-
const receivedA:
|
|
41
|
-
const receivedB:
|
|
38
|
+
const receivedA: AssistantEvent[] = [];
|
|
39
|
+
const receivedB: AssistantEvent[] = [];
|
|
42
40
|
|
|
43
41
|
// client-a is subscribed to "sess_macos" — different from the event's "sess_web"
|
|
44
42
|
hub.subscribe({
|
|
@@ -77,8 +75,8 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
77
75
|
|
|
78
76
|
test("does not deliver to a client with a different clientId", async () => {
|
|
79
77
|
const hub = new AssistantEventHub();
|
|
80
|
-
const receivedA:
|
|
81
|
-
const receivedB:
|
|
78
|
+
const receivedA: AssistantEvent[] = [];
|
|
79
|
+
const receivedB: AssistantEvent[] = [];
|
|
82
80
|
|
|
83
81
|
hub.subscribe({
|
|
84
82
|
type: "client",
|
|
@@ -108,7 +106,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
108
106
|
|
|
109
107
|
test("targeted delivery with wrong capability does not deliver", async () => {
|
|
110
108
|
const hub = new AssistantEventHub();
|
|
111
|
-
const receivedA:
|
|
109
|
+
const receivedA: AssistantEvent[] = [];
|
|
112
110
|
|
|
113
111
|
// client-a only has host_file capability, NOT host_bash
|
|
114
112
|
hub.subscribe({
|
|
@@ -132,7 +130,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
132
130
|
|
|
133
131
|
test("targeted delivery with matching capability delivers", async () => {
|
|
134
132
|
const hub = new AssistantEventHub();
|
|
135
|
-
const receivedA:
|
|
133
|
+
const receivedA: AssistantEvent[] = [];
|
|
136
134
|
|
|
137
135
|
hub.subscribe({
|
|
138
136
|
type: "client",
|
|
@@ -154,7 +152,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
154
152
|
|
|
155
153
|
test("process-type subscriber is never matched by targetClientId", async () => {
|
|
156
154
|
const hub = new AssistantEventHub();
|
|
157
|
-
const received:
|
|
155
|
+
const received: AssistantEvent[] = [];
|
|
158
156
|
|
|
159
157
|
hub.subscribe({
|
|
160
158
|
type: "process",
|
|
@@ -175,8 +173,8 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
175
173
|
describe("AssistantEventHub — untargeted capability targeting is unchanged", () => {
|
|
176
174
|
test("targetCapability without targetClientId still applies conversation scoping", async () => {
|
|
177
175
|
const hub = new AssistantEventHub();
|
|
178
|
-
const receivedA:
|
|
179
|
-
const receivedB:
|
|
176
|
+
const receivedA: AssistantEvent[] = [];
|
|
177
|
+
const receivedB: AssistantEvent[] = [];
|
|
180
178
|
|
|
181
179
|
hub.subscribe({
|
|
182
180
|
type: "client",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
4
4
|
import {
|
|
5
5
|
AssistantEventHub,
|
|
6
6
|
broadcastMessage,
|
|
@@ -12,9 +12,7 @@ import {
|
|
|
12
12
|
} from "../runtime/assistant-stream-state.js";
|
|
13
13
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
14
14
|
|
|
15
|
-
function makeEvent(
|
|
16
|
-
overrides: Partial<AssistantEventEnvelope> = {},
|
|
17
|
-
): AssistantEventEnvelope {
|
|
15
|
+
function makeEvent(overrides: Partial<AssistantEvent> = {}): AssistantEvent {
|
|
18
16
|
return {
|
|
19
17
|
id: "evt_test",
|
|
20
18
|
conversationId: "sess_1",
|
|
@@ -33,7 +31,7 @@ function makeEvent(
|
|
|
33
31
|
describe("AssistantEventHub — fanout", () => {
|
|
34
32
|
test("delivers event to a single matching subscriber", async () => {
|
|
35
33
|
const hub = new AssistantEventHub();
|
|
36
|
-
const received:
|
|
34
|
+
const received: AssistantEvent[] = [];
|
|
37
35
|
|
|
38
36
|
hub.subscribe({
|
|
39
37
|
type: "process",
|
|
@@ -77,8 +75,8 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
77
75
|
|
|
78
76
|
test("conversationId filter further restricts delivery", async () => {
|
|
79
77
|
const hub = new AssistantEventHub();
|
|
80
|
-
const receivedA:
|
|
81
|
-
const receivedB:
|
|
78
|
+
const receivedA: AssistantEvent[] = [];
|
|
79
|
+
const receivedB: AssistantEvent[] = [];
|
|
82
80
|
|
|
83
81
|
hub.subscribe({
|
|
84
82
|
type: "process",
|
|
@@ -103,7 +101,7 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
103
101
|
|
|
104
102
|
test("subscriber without conversationId filter receives all conversations", async () => {
|
|
105
103
|
const hub = new AssistantEventHub();
|
|
106
|
-
const received:
|
|
104
|
+
const received: AssistantEvent[] = [];
|
|
107
105
|
|
|
108
106
|
hub.subscribe({
|
|
109
107
|
type: "process",
|
|
@@ -161,7 +159,7 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
161
159
|
describe("AssistantEventHub — unsubscribe cleanup", () => {
|
|
162
160
|
test("dispose stops event delivery", async () => {
|
|
163
161
|
const hub = new AssistantEventHub();
|
|
164
|
-
const received:
|
|
162
|
+
const received: AssistantEvent[] = [];
|
|
165
163
|
|
|
166
164
|
const s = hub.subscribe({
|
|
167
165
|
type: "process",
|
|
@@ -236,8 +234,8 @@ describe("AssistantEventHub — unsubscribe cleanup", () => {
|
|
|
236
234
|
|
|
237
235
|
test("disposing one subscription does not affect others", async () => {
|
|
238
236
|
const hub = new AssistantEventHub();
|
|
239
|
-
const received1:
|
|
240
|
-
const received2:
|
|
237
|
+
const received1: AssistantEvent[] = [];
|
|
238
|
+
const received2: AssistantEvent[] = [];
|
|
241
239
|
|
|
242
240
|
const s1 = hub.subscribe({
|
|
243
241
|
type: "process",
|
|
@@ -343,7 +341,7 @@ describe("AssistantEventHub — exception isolation", () => {
|
|
|
343
341
|
describe("AssistantEventHub — re-entrancy / snapshot isolation", () => {
|
|
344
342
|
test("subscriber added during publish does not receive the in-flight event", async () => {
|
|
345
343
|
const hub = new AssistantEventHub();
|
|
346
|
-
const lateReceived:
|
|
344
|
+
const lateReceived: AssistantEvent[] = [];
|
|
347
345
|
|
|
348
346
|
hub.subscribe({
|
|
349
347
|
type: "process",
|
|
@@ -365,7 +363,7 @@ describe("AssistantEventHub — re-entrancy / snapshot isolation", () => {
|
|
|
365
363
|
|
|
366
364
|
test("subscriber that disposes itself mid-publish does not affect remaining subscribers", async () => {
|
|
367
365
|
const hub = new AssistantEventHub();
|
|
368
|
-
const received:
|
|
366
|
+
const received: AssistantEvent[] = [];
|
|
369
367
|
let s: ReturnType<typeof hub.subscribe>;
|
|
370
368
|
|
|
371
369
|
// eslint-disable-next-line prefer-const
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
4
4
|
import {
|
|
5
5
|
formatSseFrame,
|
|
6
6
|
formatSseHeartbeat,
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// ── Type / shape tests ────────────────────────────────────────────────────────
|
|
10
10
|
|
|
11
|
-
describe("
|
|
11
|
+
describe("AssistantEvent shape", () => {
|
|
12
12
|
test("accepts a minimal valid event", () => {
|
|
13
|
-
const event:
|
|
13
|
+
const event: AssistantEvent = {
|
|
14
14
|
id: "evt_001",
|
|
15
15
|
emittedAt: "2026-02-18T21:20:00.000Z",
|
|
16
16
|
message: {
|
|
@@ -27,7 +27,7 @@ describe("AssistantEventEnvelope shape", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
test("accepts a full event with conversationId", () => {
|
|
30
|
-
const event:
|
|
30
|
+
const event: AssistantEvent = {
|
|
31
31
|
id: "evt_002",
|
|
32
32
|
conversationId: "conv_456",
|
|
33
33
|
emittedAt: "2026-02-18T21:20:00.000Z",
|
|
@@ -45,7 +45,7 @@ describe("AssistantEventEnvelope shape", () => {
|
|
|
45
45
|
// ── SSE framing tests ─────────────────────────────────────────────────────────
|
|
46
46
|
|
|
47
47
|
describe("formatSseFrame", () => {
|
|
48
|
-
const baseEvent:
|
|
48
|
+
const baseEvent: AssistantEvent = {
|
|
49
49
|
id: "evt_003",
|
|
50
50
|
conversationId: "sess_xyz",
|
|
51
51
|
emittedAt: "2026-02-18T00:00:00.000Z",
|
|
@@ -73,7 +73,7 @@ describe("formatSseFrame", () => {
|
|
|
73
73
|
const dataLine = frame.split("\n").find((l) => l.startsWith("data: "))!;
|
|
74
74
|
const parsed = JSON.parse(
|
|
75
75
|
dataLine.slice("data: ".length),
|
|
76
|
-
) as
|
|
76
|
+
) as AssistantEvent;
|
|
77
77
|
|
|
78
78
|
expect(parsed.id).toBe(baseEvent.id);
|
|
79
79
|
expect(parsed.conversationId).toBe(baseEvent.conversationId);
|
|
@@ -82,16 +82,13 @@ describe("formatSseFrame", () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
test("id line uses the event id verbatim", () => {
|
|
85
|
-
const event:
|
|
86
|
-
...baseEvent,
|
|
87
|
-
id: "unique-evt-id-xyz",
|
|
88
|
-
};
|
|
85
|
+
const event: AssistantEvent = { ...baseEvent, id: "unique-evt-id-xyz" };
|
|
89
86
|
const frame = formatSseFrame(event);
|
|
90
87
|
expect(frame).toContain("id: unique-evt-id-xyz\n");
|
|
91
88
|
});
|
|
92
89
|
|
|
93
90
|
test("strips newline characters from event.id to prevent SSE frame injection", () => {
|
|
94
|
-
const event:
|
|
91
|
+
const event: AssistantEvent = {
|
|
95
92
|
...baseEvent,
|
|
96
93
|
id: 'foo\ndata: {"injected":true}',
|
|
97
94
|
};
|
|
@@ -116,7 +113,7 @@ describe("formatSseFrame", () => {
|
|
|
116
113
|
});
|
|
117
114
|
|
|
118
115
|
test("seq lands in the JSON payload (envelope) when set, never in SSE id", () => {
|
|
119
|
-
const event:
|
|
116
|
+
const event: AssistantEvent = {
|
|
120
117
|
...baseEvent,
|
|
121
118
|
id: "uuid-event-id",
|
|
122
119
|
seq: 42,
|
|
@@ -312,6 +312,64 @@ describe("assistant ID boundary", () => {
|
|
|
312
312
|
// surfaces invites callers to pass external IDs into daemon scoping.
|
|
313
313
|
// -------------------------------------------------------------------------
|
|
314
314
|
|
|
315
|
+
test("message contract types do not contain assistantId for guardian requests", () => {
|
|
316
|
+
const contractPath = join(
|
|
317
|
+
import.meta.dir,
|
|
318
|
+
"..",
|
|
319
|
+
"daemon",
|
|
320
|
+
"message-types",
|
|
321
|
+
"integrations.ts",
|
|
322
|
+
);
|
|
323
|
+
const content = readFileSync(contractPath, "utf-8");
|
|
324
|
+
|
|
325
|
+
// Extract the interface blocks for the request types and verify
|
|
326
|
+
// none of them declare an assistantId property.
|
|
327
|
+
const requestTypeNames = ["ChannelVerificationSessionRequest"];
|
|
328
|
+
|
|
329
|
+
for (const typeName of requestTypeNames) {
|
|
330
|
+
// Find the interface/type block — match from the type name to the next
|
|
331
|
+
// closing brace at the same indentation level. We use a simple heuristic:
|
|
332
|
+
// find the line declaring the type, then scan forward to the closing '}'.
|
|
333
|
+
const typeIndex = content.indexOf(typeName);
|
|
334
|
+
expect(
|
|
335
|
+
typeIndex,
|
|
336
|
+
`Expected to find ${typeName} in message contract`,
|
|
337
|
+
).toBeGreaterThan(-1);
|
|
338
|
+
|
|
339
|
+
// Extract from the type declaration to the next '}' line
|
|
340
|
+
const blockStart = content.indexOf("{", typeIndex);
|
|
341
|
+
if (blockStart === -1) continue;
|
|
342
|
+
let braceDepth = 0;
|
|
343
|
+
let blockEnd = blockStart;
|
|
344
|
+
for (let i = blockStart; i < content.length; i++) {
|
|
345
|
+
if (content[i] === "{") braceDepth++;
|
|
346
|
+
if (content[i] === "}") braceDepth--;
|
|
347
|
+
if (braceDepth === 0) {
|
|
348
|
+
blockEnd = i + 1;
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const block = content.slice(blockStart, blockEnd);
|
|
353
|
+
|
|
354
|
+
// The block should not contain an assistantId property declaration
|
|
355
|
+
// (matches "assistantId?" or "assistantId:" on a non-comment line)
|
|
356
|
+
const lines = block.split("\n");
|
|
357
|
+
for (const line of lines) {
|
|
358
|
+
const trimmed = line.trim();
|
|
359
|
+
if (
|
|
360
|
+
trimmed.startsWith("//") ||
|
|
361
|
+
trimmed.startsWith("*") ||
|
|
362
|
+
trimmed.startsWith("/*")
|
|
363
|
+
)
|
|
364
|
+
continue;
|
|
365
|
+
expect(
|
|
366
|
+
/\bassistantId\s*[?:]/.test(trimmed),
|
|
367
|
+
`${typeName} must not declare an assistantId property. Found: "${trimmed}"`,
|
|
368
|
+
).toBe(false);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
315
373
|
test("guardian outbound param interfaces do not contain assistantId", () => {
|
|
316
374
|
const actionsPath = join(
|
|
317
375
|
import.meta.dir,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
12
12
|
import type {
|
|
13
13
|
EventTargeting,
|
|
14
14
|
ReplaySubscriber,
|
|
@@ -26,9 +26,7 @@ import {
|
|
|
26
26
|
|
|
27
27
|
const CONV = "conv_test";
|
|
28
28
|
|
|
29
|
-
function mkEvent(
|
|
30
|
-
overrides: Partial<AssistantEventEnvelope> = {},
|
|
31
|
-
): AssistantEventEnvelope {
|
|
29
|
+
function mkEvent(overrides: Partial<AssistantEvent> = {}): AssistantEvent {
|
|
32
30
|
const conversationId =
|
|
33
31
|
"conversationId" in overrides ? overrides.conversationId : CONV;
|
|
34
32
|
return {
|
|
@@ -41,7 +39,7 @@ function mkEvent(
|
|
|
41
39
|
text: "x",
|
|
42
40
|
},
|
|
43
41
|
...overrides,
|
|
44
|
-
} as
|
|
42
|
+
} as AssistantEvent;
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
describe("assistant-stream-state", () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { SYNC_TAGS } from "../daemon/message-types/sync.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
5
5
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
6
6
|
import { ROUTES as AVATAR_ROUTES } from "../runtime/routes/avatar-routes.js";
|
|
7
7
|
import { publishIdentityChanged } from "../runtime/sync/resource-sync-events.js";
|
|
@@ -19,7 +19,7 @@ async function waitFor(predicate: () => boolean): Promise<void> {
|
|
|
19
19
|
|
|
20
20
|
describe("avatar and identity sync events", () => {
|
|
21
21
|
test("notify_avatar_updated emits legacy avatar event and sync tag", async () => {
|
|
22
|
-
const received:
|
|
22
|
+
const received: AssistantEvent[] = [];
|
|
23
23
|
const subscription = assistantEventHub.subscribe({
|
|
24
24
|
type: "process",
|
|
25
25
|
callback: (event) => {
|
|
@@ -50,7 +50,7 @@ describe("avatar and identity sync events", () => {
|
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
test("identity changes emit legacy identity event and identity sync tags", async () => {
|
|
53
|
-
const received:
|
|
53
|
+
const received: AssistantEvent[] = [];
|
|
54
54
|
const subscription = assistantEventHub.subscribe({
|
|
55
55
|
type: "process",
|
|
56
56
|
callback: (event) => {
|