@vellumai/assistant 0.10.3 → 0.10.4-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/openapi.yaml +73 -56
- package/package.json +1 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +83 -31
- package/src/__tests__/assistant-stream-state.test.ts +3 -76
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -2
- package/src/__tests__/channel-approval-routes.test.ts +21 -26
- package/src/__tests__/channel-delivery-store.test.ts +28 -0
- package/src/__tests__/channel-guardian.test.ts +82 -32
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +11 -19
- package/src/__tests__/channel-reply-delivery.test.ts +6 -2
- package/src/__tests__/compaction-ledger-store.test.ts +128 -0
- package/src/__tests__/config-loader-backfill.test.ts +148 -0
- package/src/__tests__/consult-deadline.test.ts +60 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +156 -0
- package/src/__tests__/contact-store-user-file.test.ts +7 -10
- package/src/__tests__/contacts-relay-reads.test.ts +6 -9
- package/src/__tests__/contacts-write.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +4 -2
- package/src/__tests__/conversation-agent-loop.test.ts +98 -7
- package/src/__tests__/conversation-attention-telegram.test.ts +9 -11
- package/src/__tests__/conversation-error.test.ts +18 -0
- package/src/__tests__/conversation-fork-crud.test.ts +354 -24
- package/src/__tests__/conversation-title-service.test.ts +222 -201
- package/src/__tests__/db-compaction-events-migration.test.ts +129 -0
- package/src/__tests__/delete-propagation.test.ts +5 -3
- package/src/__tests__/dm-backfill.test.ts +6 -4
- package/src/__tests__/emit-signal-routing-intent.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +43 -23
- package/src/__tests__/guardian-dispatch.test.ts +50 -5
- package/src/__tests__/guardian-routing-state.test.ts +6 -10
- package/src/__tests__/helpers/channel-test-adapter.ts +45 -12
- package/src/__tests__/helpers/create-guardian-binding.ts +15 -23
- package/src/__tests__/helpers/mock-logger.ts +1 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +96 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +87 -10
- package/src/__tests__/invite-redemption-service.test.ts +273 -53
- package/src/__tests__/invite-routes-http.test.ts +34 -0
- package/src/__tests__/invite-service-ipc.test.ts +65 -2
- package/src/__tests__/list-messages-page-latest.test.ts +173 -4
- package/src/__tests__/mcp-config-secret-boundary.test.ts +3 -0
- package/src/__tests__/non-member-access-request.test.ts +15 -13
- package/src/__tests__/onboarding-persona-write.test.ts +52 -22
- package/src/__tests__/persist-onboarding-artifacts.test.ts +1 -0
- package/src/__tests__/persona-resolver.test.ts +75 -45
- package/src/__tests__/plugin-bootstrap.test.ts +13 -5
- package/src/__tests__/plugin-disabled-state.test.ts +190 -0
- package/src/__tests__/provider-usage-tracking.test.ts +1 -1
- package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +135 -0
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +158 -0
- package/src/__tests__/reaction-persistence.test.ts +51 -4
- package/src/__tests__/relay-server.test.ts +88 -31
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -11
- package/src/__tests__/settings-routes.test.ts +32 -0
- package/src/__tests__/slack-block-formatting.test.ts +1 -38
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +13 -36
- package/src/__tests__/stt-hints.test.ts +6 -3
- package/src/__tests__/subagent-fork-prompt-role.test.ts +195 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +6 -7
- package/src/__tests__/subagent-role-registry.test.ts +17 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +546 -0
- package/src/__tests__/subagent-tools.test.ts +398 -3
- package/src/__tests__/thread-backfill.test.ts +3 -3
- package/src/__tests__/tool-preview-lifecycle.test.ts +26 -10
- package/src/__tests__/tool-start-timestamp.test.ts +4 -3
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +37 -51
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -2
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -7
- package/src/__tests__/trusted-contact-multichannel.test.ts +16 -7
- package/src/__tests__/trusted-contact-verification.test.ts +79 -54
- package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +137 -0
- package/src/__tests__/voice-invite-redemption.test.ts +183 -20
- 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-112-remove-advisor-callsite-override.test.ts +170 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +196 -238
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +35 -47
- package/src/agent/loop-exclusive-tool.test.ts +19 -15
- package/src/agent/loop-native-web-search.test.ts +200 -0
- package/src/agent/loop.ts +108 -1
- package/src/api/responses/conversation-message.ts +9 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -4
- package/src/calls/__tests__/relay-setup-router.test.ts +10 -18
- package/src/calls/guardian-dispatch.ts +14 -11
- package/src/calls/inbound-trust-reader.ts +7 -1
- package/src/calls/relay-access-wait.ts +6 -6
- package/src/calls/relay-server.ts +22 -2
- package/src/calls/relay-setup-router.ts +10 -10
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
- package/src/cli/commands/contacts.ts +10 -7
- package/src/cli/commands/memory/__tests__/worker.test.ts +147 -17
- package/src/cli/commands/memory/worker.ts +97 -30
- package/src/cli/commands/plugins.ts +3 -146
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +17 -17
- package/src/cli/lib/__tests__/publish-plugin.test.ts +98 -0
- package/src/cli/lib/publish-plugin.ts +231 -1
- package/src/config/__tests__/sync-gated-profiles.test.ts +5 -7
- package/src/config/bundled-skills/subagent/SKILL.md +16 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -4
- package/src/config/call-site-defaults.ts +0 -6
- package/src/config/llm-resolver.ts +0 -3
- package/src/config/schemas/call-site-catalog.ts +0 -7
- package/src/config/schemas/heartbeat.ts +2 -5
- package/src/config/schemas/llm.ts +3 -12
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/seed-inference-profiles.ts +76 -35
- package/src/config/sync-gated-profiles.ts +0 -3
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +7 -8
- package/src/contacts/__tests__/member-write-relay.test.ts +35 -11
- package/src/contacts/contact-store.ts +27 -237
- package/src/contacts/contacts-write.ts +18 -58
- package/src/contacts/gateway-channel-read.ts +51 -0
- package/src/contacts/member-write-relay.ts +25 -31
- package/src/contacts/types.ts +3 -15
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +0 -44
- package/src/daemon/conversation-agent-loop-handlers.ts +29 -10
- package/src/daemon/conversation-agent-loop.ts +68 -61
- package/src/daemon/conversation-error.ts +7 -10
- package/src/daemon/conversation-tool-setup.ts +0 -10
- package/src/daemon/conversation.ts +10 -0
- package/src/daemon/external-plugins-bootstrap.ts +8 -2
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -2
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -2
- package/src/daemon/handlers/__tests__/config-channels.test.ts +9 -14
- package/src/daemon/handlers/config-channels.ts +14 -29
- package/src/daemon/lifecycle.ts +16 -4
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/heartbeat/heartbeat-service.ts +5 -0
- package/src/home/relationship-state-writer.ts +5 -0
- package/src/memory/__tests__/embedding-cache.test.ts +136 -0
- package/src/memory/compaction-ledger-store.ts +107 -0
- package/src/memory/conversation-crud.ts +136 -61
- package/src/memory/conversation-title-service.ts +173 -24
- package/src/memory/embedding-backend.ts +8 -1
- package/src/memory/embedding-cache.ts +139 -0
- package/src/memory/jobs-worker.ts +75 -29
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +27 -5
- package/src/memory/migrations/302-create-compaction-events.ts +107 -0
- package/src/memory/migrations/303-add-conversation-creation-seq.ts +33 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +79 -6
- package/src/memory/schema/contacts.ts +6 -2
- package/src/memory/schema/conversations.ts +39 -0
- package/src/memory/steps.ts +1090 -367
- package/src/memory/worker-control.ts +104 -18
- package/src/memory/worker-process.ts +17 -0
- package/src/messaging/channel-binding-metadata.ts +31 -0
- package/src/messaging/channel-binding-schema.ts +51 -0
- package/src/messaging/providers/__tests__/callback-routing.test.ts +45 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +195 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +11 -0
- package/src/messaging/providers/a2a/deliver.ts +5 -1
- package/src/messaging/providers/a2a/transport.ts +10 -0
- package/src/messaging/providers/callback-routing.ts +48 -0
- package/src/messaging/providers/channel-transport.ts +55 -0
- package/src/messaging/providers/index.ts +65 -241
- package/src/messaging/providers/slack/binding-metadata.ts +62 -0
- package/src/messaging/providers/slack/transport.ts +92 -0
- package/src/messaging/providers/telegram-bot/transport.ts +51 -0
- package/src/messaging/providers/whatsapp/transport.ts +38 -0
- package/src/notifications/__tests__/broadcaster.test.ts +0 -8
- package/src/notifications/__tests__/connected-channels.test.ts +8 -36
- package/src/notifications/__tests__/destination-resolver.test.ts +12 -117
- package/src/notifications/destination-resolver.ts +7 -23
- package/src/notifications/emit-signal.ts +5 -11
- package/src/plugins/defaults/index.ts +0 -35
- package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +11 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +243 -2
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +167 -14
- package/src/plugins/disabled-state.ts +31 -0
- package/src/plugins/registry.ts +55 -12
- package/src/prompts/persona-resolver.ts +43 -11
- package/src/providers/call-site-routing.ts +41 -0
- package/src/providers/provider-send-message.ts +6 -0
- package/src/providers/ratelimit.ts +6 -0
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +6 -0
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +6 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +30 -27
- package/src/runtime/__tests__/local-principal-trust.test.ts +16 -18
- package/src/runtime/__tests__/member-verdict-cache.test.ts +119 -0
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +115 -168
- package/src/runtime/access-request-helper.ts +1 -2
- package/src/runtime/actor-trust-resolver.ts +44 -17
- package/src/runtime/anchored-guardian.test.ts +7 -54
- package/src/runtime/anchored-guardian.ts +4 -53
- package/src/runtime/assistant-stream-state.ts +12 -74
- package/src/runtime/channel-reply-delivery.ts +3 -8
- package/src/runtime/guardian-vellum-migration.ts +18 -16
- package/src/runtime/invite-redemption-service.ts +25 -10
- package/src/runtime/local-actor-identity.test.ts +108 -0
- package/src/runtime/local-actor-identity.ts +27 -20
- package/src/runtime/member-verdict-cache.ts +0 -0
- package/src/runtime/routes/__tests__/contact-routes.test.ts +100 -7
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +1 -2
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +40 -25
- package/src/runtime/routes/conversation-list-routes.ts +1 -29
- package/src/runtime/routes/conversation-routes.ts +27 -7
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -10
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +19 -0
- package/src/runtime/routes/settings-routes.ts +8 -3
- package/src/runtime/services/conversation-serializer.ts +6 -49
- package/src/runtime/slack-block-formatting.ts +0 -15
- package/src/runtime/trust-verdict-consumer.ts +36 -41
- package/src/subagent/__tests__/consult-prompt.test.ts +35 -0
- package/src/{plugins/defaults/advisor/__tests__/transcript.test.ts → subagent/__tests__/consult-transcript.test.ts} +47 -10
- package/src/{plugins/defaults/advisor/steering.ts → subagent/consult-prompt.ts} +17 -39
- package/src/{plugins/defaults/advisor/transcript.ts → subagent/consult-transcript.ts} +18 -8
- package/src/subagent/index.ts +1 -1
- package/src/subagent/manager.ts +245 -33
- package/src/subagent/types.ts +8 -1
- package/src/tools/registry.ts +10 -3
- package/src/tools/subagent/consult-deadline.ts +49 -0
- package/src/tools/subagent/spawn.ts +234 -5
- package/src/util/logger.ts +9 -0
- package/src/util/platform.ts +14 -0
- package/src/workspace/migrations/031-drop-user-md.ts +232 -148
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +64 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +0 -56
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +0 -43
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +0 -137
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -314
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +0 -138
- package/src/plugins/defaults/advisor/advisor-gate.ts +0 -29
- package/src/plugins/defaults/advisor/advisor-state-store.ts +0 -94
- package/src/plugins/defaults/advisor/config.ts +0 -21
- package/src/plugins/defaults/advisor/consult.ts +0 -197
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +0 -34
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +0 -30
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +0 -19
- package/src/plugins/defaults/advisor/package.json +0 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +0 -92
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for getConnectedChannels connectivity resolution.
|
|
3
3
|
*
|
|
4
|
-
* Connectivity
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* channel from being marked connected when it can't be delivered (and
|
|
8
|
-
* vice-versa).
|
|
4
|
+
* Connectivity mirrors destination-resolver's `resolveGuardian`: guardian
|
|
5
|
+
* delivery is sourced solely from the gateway. A channel with no active gateway
|
|
6
|
+
* binding is not connected, keeping connectivity aligned with deliverability.
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
9
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
@@ -20,7 +18,6 @@ mock.module("../../util/logger.js", () => ({
|
|
|
20
18
|
|
|
21
19
|
let deliverableChannels: string[] = [];
|
|
22
20
|
let gatewayGuardians: GuardianDelivery[] | null = null;
|
|
23
|
-
let localChatId: string | null = null;
|
|
24
21
|
|
|
25
22
|
const realConfig = await import("../../channels/config.js");
|
|
26
23
|
|
|
@@ -36,16 +33,6 @@ mock.module("../../contacts/guardian-delivery-reader.js", () => ({
|
|
|
36
33
|
getGuardianDelivery: async () => gatewayGuardians,
|
|
37
34
|
}));
|
|
38
35
|
|
|
39
|
-
const realContactStore = await import("../../contacts/contact-store.js");
|
|
40
|
-
|
|
41
|
-
mock.module("../../contacts/contact-store.js", () => ({
|
|
42
|
-
...realContactStore,
|
|
43
|
-
findGuardianForChannel: (_channelType: string) =>
|
|
44
|
-
localChatId === null
|
|
45
|
-
? null
|
|
46
|
-
: { contact: { principalId: "p1" }, channel: { externalChatId: localChatId } },
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
36
|
const { getConnectedChannels } = await import("../emit-signal.js");
|
|
50
37
|
|
|
51
38
|
function gatewayBinding(channelType: string, externalChatId: string): GuardianDelivery {
|
|
@@ -55,43 +42,28 @@ function gatewayBinding(channelType: string, externalChatId: string): GuardianDe
|
|
|
55
42
|
beforeEach(() => {
|
|
56
43
|
deliverableChannels = [];
|
|
57
44
|
gatewayGuardians = null;
|
|
58
|
-
localChatId = null;
|
|
59
45
|
});
|
|
60
46
|
|
|
61
|
-
describe("getConnectedChannels gateway
|
|
62
|
-
test("marks telegram connected from a gateway
|
|
47
|
+
describe("getConnectedChannels gateway connectivity", () => {
|
|
48
|
+
test("marks telegram connected from a gateway binding", async () => {
|
|
63
49
|
deliverableChannels = ["telegram"];
|
|
64
50
|
gatewayGuardians = [gatewayBinding("telegram", "123")];
|
|
65
|
-
localChatId = null;
|
|
66
51
|
|
|
67
52
|
expect(await getConnectedChannels()).toContain("telegram");
|
|
68
53
|
});
|
|
69
54
|
|
|
70
|
-
test("
|
|
55
|
+
test("marks telegram disconnected when the gateway is unreachable (null)", async () => {
|
|
71
56
|
deliverableChannels = ["telegram"];
|
|
72
57
|
gatewayGuardians = null;
|
|
73
|
-
localChatId = "456";
|
|
74
|
-
|
|
75
|
-
expect(await getConnectedChannels()).toContain("telegram");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("marks telegram disconnected when neither source has a binding", async () => {
|
|
79
|
-
deliverableChannels = ["telegram"];
|
|
80
|
-
gatewayGuardians = null;
|
|
81
|
-
localChatId = null;
|
|
82
58
|
|
|
83
59
|
expect(await getConnectedChannels()).not.toContain("telegram");
|
|
84
60
|
});
|
|
85
61
|
|
|
86
|
-
test("
|
|
87
|
-
// Gateway present but with no active telegram entry ⇒ per-channel no-match,
|
|
88
|
-
// so connectivity falls back to the local mirror (mirrors
|
|
89
|
-
// destination-resolver's per-channel fallback).
|
|
62
|
+
test("marks telegram disconnected when the gateway has no binding", async () => {
|
|
90
63
|
deliverableChannels = ["telegram"];
|
|
91
64
|
gatewayGuardians = [];
|
|
92
|
-
localChatId = "789";
|
|
93
65
|
|
|
94
|
-
expect(await getConnectedChannels()).toContain("telegram");
|
|
66
|
+
expect(await getConnectedChannels()).not.toContain("telegram");
|
|
95
67
|
});
|
|
96
68
|
|
|
97
69
|
test("only marks slack connected for D-prefixed (DM) chat IDs", async () => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Verifies resolveDestinations resolves guardian delivery endpoints from the
|
|
3
|
-
* gateway-provided guardian list,
|
|
4
|
-
*
|
|
3
|
+
* gateway-provided guardian list, and omits a channel when the list is
|
|
4
|
+
* null/empty or carries no entry for it.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
8
8
|
|
|
9
9
|
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
10
10
|
|
|
@@ -15,15 +15,6 @@ mock.module("../../util/logger.js", () => ({
|
|
|
15
15
|
}),
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
|
-
// Local fallback read; mocked so the null-list path is deterministic.
|
|
19
|
-
let localGuardian:
|
|
20
|
-
| { contact: { principalId?: string }; channel: { address: string; externalChatId?: string } }
|
|
21
|
-
| null = null;
|
|
22
|
-
|
|
23
|
-
mock.module("../../contacts/contact-store.js", () => ({
|
|
24
|
-
findGuardianForChannel: (_channelType: string) => localGuardian,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
18
|
const { resolveDestinations } = await import("../destination-resolver.js");
|
|
28
19
|
|
|
29
20
|
function guardian(
|
|
@@ -37,10 +28,6 @@ function guardian(
|
|
|
37
28
|
}
|
|
38
29
|
|
|
39
30
|
describe("resolveDestinations — gateway guardian list", () => {
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
localGuardian = null;
|
|
42
|
-
});
|
|
43
|
-
|
|
44
31
|
test("vellum carries guardianPrincipalId from the gateway list", () => {
|
|
45
32
|
const list = [
|
|
46
33
|
guardian({ channelType: "vellum", address: "user@example.com", principalId: "prin-1" }),
|
|
@@ -137,120 +124,28 @@ describe("resolveDestinations — gateway guardian list", () => {
|
|
|
137
124
|
});
|
|
138
125
|
});
|
|
139
126
|
|
|
140
|
-
describe("resolveDestinations —
|
|
141
|
-
|
|
142
|
-
localGuardian = null;
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("telegram resolves from the local contacts read", () => {
|
|
146
|
-
localGuardian = {
|
|
147
|
-
contact: {},
|
|
148
|
-
channel: { address: "tg-user", externalChatId: "12345" },
|
|
149
|
-
};
|
|
127
|
+
describe("resolveDestinations — gateway empty or missing channel", () => {
|
|
128
|
+
test("null gateway list omits telegram", () => {
|
|
150
129
|
const result = resolveDestinations(["telegram"], null);
|
|
151
|
-
expect(result.
|
|
152
|
-
channel: "telegram",
|
|
153
|
-
endpoint: "12345",
|
|
154
|
-
metadata: { externalUserId: "tg-user" },
|
|
155
|
-
bindingContext: {
|
|
156
|
-
sourceChannel: "telegram",
|
|
157
|
-
externalChatId: "12345",
|
|
158
|
-
externalUserId: "tg-user",
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("slack DM resolves from the local contacts read", () => {
|
|
164
|
-
localGuardian = {
|
|
165
|
-
contact: {},
|
|
166
|
-
channel: { address: "slack-user", externalChatId: "D123" },
|
|
167
|
-
};
|
|
168
|
-
const result = resolveDestinations(["slack"], null);
|
|
169
|
-
expect(result.get("slack")).toEqual({
|
|
170
|
-
channel: "slack",
|
|
171
|
-
endpoint: "D123",
|
|
172
|
-
metadata: { externalUserId: "slack-user" },
|
|
173
|
-
bindingContext: {
|
|
174
|
-
sourceChannel: "slack",
|
|
175
|
-
externalChatId: "D123",
|
|
176
|
-
externalUserId: "slack-user",
|
|
177
|
-
},
|
|
178
|
-
});
|
|
130
|
+
expect(result.has("telegram")).toBe(false);
|
|
179
131
|
});
|
|
180
132
|
|
|
181
|
-
test("
|
|
182
|
-
localGuardian = {
|
|
183
|
-
contact: { principalId: "prin-1" },
|
|
184
|
-
channel: { address: "user@example.com" },
|
|
185
|
-
};
|
|
133
|
+
test("null gateway list omits vellum principalId metadata", () => {
|
|
186
134
|
const result = resolveDestinations(["vellum"], null);
|
|
187
|
-
expect(result.get("vellum")).toEqual({
|
|
188
|
-
channel: "vellum",
|
|
189
|
-
metadata: { guardianPrincipalId: "prin-1" },
|
|
190
|
-
});
|
|
135
|
+
expect(result.get("vellum")).toEqual({ channel: "vellum" });
|
|
191
136
|
});
|
|
192
|
-
});
|
|
193
137
|
|
|
194
|
-
|
|
195
|
-
beforeEach(() => {
|
|
196
|
-
localGuardian = null;
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("empty gateway list falls back to local telegram binding", () => {
|
|
200
|
-
localGuardian = {
|
|
201
|
-
contact: {},
|
|
202
|
-
channel: { address: "tg-user", externalChatId: "12345" },
|
|
203
|
-
};
|
|
138
|
+
test("empty gateway list omits telegram", () => {
|
|
204
139
|
const result = resolveDestinations(["telegram"], []);
|
|
205
|
-
expect(result.
|
|
206
|
-
channel: "telegram",
|
|
207
|
-
endpoint: "12345",
|
|
208
|
-
metadata: { externalUserId: "tg-user" },
|
|
209
|
-
bindingContext: {
|
|
210
|
-
sourceChannel: "telegram",
|
|
211
|
-
externalChatId: "12345",
|
|
212
|
-
externalUserId: "tg-user",
|
|
213
|
-
},
|
|
214
|
-
});
|
|
140
|
+
expect(result.has("telegram")).toBe(false);
|
|
215
141
|
});
|
|
216
142
|
|
|
217
|
-
test("gateway list missing the channel
|
|
218
|
-
localGuardian = {
|
|
219
|
-
contact: {},
|
|
220
|
-
channel: { address: "slack-user", externalChatId: "D123" },
|
|
221
|
-
};
|
|
143
|
+
test("gateway list missing the channel omits slack", () => {
|
|
222
144
|
// Gateway returns a telegram guardian but no slack entry.
|
|
223
145
|
const list = [
|
|
224
146
|
guardian({ channelType: "telegram", address: "tg", externalChatId: "999" }),
|
|
225
147
|
];
|
|
226
148
|
const result = resolveDestinations(["slack"], list);
|
|
227
|
-
expect(result.
|
|
228
|
-
channel: "slack",
|
|
229
|
-
endpoint: "D123",
|
|
230
|
-
metadata: { externalUserId: "slack-user" },
|
|
231
|
-
bindingContext: {
|
|
232
|
-
sourceChannel: "slack",
|
|
233
|
-
externalChatId: "D123",
|
|
234
|
-
externalUserId: "slack-user",
|
|
235
|
-
},
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
test("empty gateway list falls back to local vellum principalId", () => {
|
|
240
|
-
localGuardian = {
|
|
241
|
-
contact: { principalId: "prin-1" },
|
|
242
|
-
channel: { address: "user@example.com" },
|
|
243
|
-
};
|
|
244
|
-
const result = resolveDestinations(["vellum"], []);
|
|
245
|
-
expect(result.get("vellum")).toEqual({
|
|
246
|
-
channel: "vellum",
|
|
247
|
-
metadata: { guardianPrincipalId: "prin-1" },
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
test("empty gateway list with no local binding omits telegram", () => {
|
|
252
|
-
localGuardian = null;
|
|
253
|
-
const result = resolveDestinations(["telegram"], []);
|
|
254
|
-
expect(result.has("telegram")).toBe(false);
|
|
149
|
+
expect(result.has("slack")).toBe(false);
|
|
255
150
|
});
|
|
256
151
|
});
|
|
@@ -15,7 +15,6 @@ import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
|
15
15
|
|
|
16
16
|
import { isNotificationDeliverable } from "../channels/config.js";
|
|
17
17
|
import type { ChannelId } from "../channels/types.js";
|
|
18
|
-
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
19
18
|
import { guardianForChannel } from "../contacts/guardian-delivery-reader.js";
|
|
20
19
|
import { getLogger } from "../util/logger.js";
|
|
21
20
|
import type { ChannelDestination, NotificationChannel } from "./types.js";
|
|
@@ -29,13 +28,7 @@ interface ResolvedGuardian {
|
|
|
29
28
|
externalChatId?: string;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
/**
|
|
33
|
-
* Resolve the guardian delivery endpoint for a channel: gateway list first,
|
|
34
|
-
* else the local contacts read. The local read is the transitional
|
|
35
|
-
* dual-written mirror and covers a transient gateway failure (null list) or a
|
|
36
|
-
* gateway list missing this channel, so a soft-failed gateway read does not
|
|
37
|
-
* drop a binding the local store still holds. Removed in Combo 11.
|
|
38
|
-
*/
|
|
31
|
+
/** Resolve the guardian delivery endpoint for a channel from the gateway list. */
|
|
39
32
|
function resolveGuardian(
|
|
40
33
|
guardians: GuardianDelivery[] | null,
|
|
41
34
|
channelType: string,
|
|
@@ -43,19 +36,11 @@ function resolveGuardian(
|
|
|
43
36
|
const g = guardians
|
|
44
37
|
? guardianForChannel(guardians, channelType)
|
|
45
38
|
: undefined;
|
|
46
|
-
if (g)
|
|
47
|
-
return {
|
|
48
|
-
principalId: g.principalId ?? undefined,
|
|
49
|
-
address: g.address,
|
|
50
|
-
externalChatId: g.externalChatId ?? undefined,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const local = findGuardianForChannel(channelType);
|
|
54
|
-
if (!local) return undefined;
|
|
39
|
+
if (!g) return undefined;
|
|
55
40
|
return {
|
|
56
|
-
principalId:
|
|
57
|
-
address:
|
|
58
|
-
externalChatId:
|
|
41
|
+
principalId: g.principalId ?? undefined,
|
|
42
|
+
address: g.address,
|
|
43
|
+
externalChatId: g.externalChatId ?? undefined,
|
|
59
44
|
};
|
|
60
45
|
}
|
|
61
46
|
|
|
@@ -67,9 +52,8 @@ function resolveGuardian(
|
|
|
67
52
|
* Returns a map keyed by `NotificationChannel`. Channels that cannot be
|
|
68
53
|
* resolved (e.g. no Telegram binding configured) are omitted from the result.
|
|
69
54
|
*
|
|
70
|
-
* `guardians` is the gateway-resolved guardian list;
|
|
71
|
-
*
|
|
72
|
-
* contacts read for this release.
|
|
55
|
+
* `guardians` is the gateway-resolved guardian list; a channel with no entry
|
|
56
|
+
* in the list is omitted from the result.
|
|
73
57
|
*/
|
|
74
58
|
export function resolveDestinations(
|
|
75
59
|
channels: readonly (ChannelId | NotificationChannel)[],
|
|
@@ -13,7 +13,6 @@ import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
|
13
13
|
import { v4 as uuid } from "uuid";
|
|
14
14
|
|
|
15
15
|
import { getDeliverableChannels } from "../channels/config.js";
|
|
16
|
-
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
17
16
|
import {
|
|
18
17
|
getGuardianDelivery,
|
|
19
18
|
guardianForChannel,
|
|
@@ -96,22 +95,17 @@ export function getBroadcaster(): NotificationBroadcaster {
|
|
|
96
95
|
|
|
97
96
|
/**
|
|
98
97
|
* Resolve a binding-based channel's delivery endpoint (externalChatId) the
|
|
99
|
-
* SAME way destination-resolver's `resolveGuardian` does:
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* Keeping connectivity aligned with delivery prevents a channel being marked
|
|
104
|
-
* connected but then skipped with no destination (or vice-versa).
|
|
98
|
+
* SAME way destination-resolver's `resolveGuardian` does: from the gateway
|
|
99
|
+
* guardian delivery for this channel. Keeping connectivity aligned with
|
|
100
|
+
* delivery prevents a channel being marked connected but then skipped with no
|
|
101
|
+
* destination (or vice-versa).
|
|
105
102
|
*/
|
|
106
103
|
function resolveChannelChatId(
|
|
107
104
|
guardians: GuardianDelivery[] | null,
|
|
108
105
|
channelType: string,
|
|
109
106
|
): string | undefined {
|
|
110
107
|
const g = guardians ? guardianForChannel(guardians, channelType) : undefined;
|
|
111
|
-
|
|
112
|
-
return g.externalChatId ?? undefined;
|
|
113
|
-
}
|
|
114
|
-
return findGuardianForChannel(channelType)?.channel.externalChatId ?? undefined;
|
|
108
|
+
return g?.externalChatId ?? undefined;
|
|
115
109
|
}
|
|
116
110
|
|
|
117
111
|
export async function getConnectedChannels(): Promise<NotificationChannel[]> {
|
|
@@ -24,15 +24,8 @@
|
|
|
24
24
|
* {@link registerDefaultPlugins} at call time.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { finalizeTool } from "../../tools/tool-defaults.js";
|
|
28
27
|
import { registerPlugin, resetPluginRegistryForTests } from "../registry.js";
|
|
29
28
|
import { type Plugin, PluginExecutionError } from "../types.js";
|
|
30
|
-
import { resetAdvisorStateForTests } from "./advisor/advisor-state-store.js";
|
|
31
|
-
import advisorPostModelCall from "./advisor/hooks/post-model-call.js";
|
|
32
|
-
import advisorPreModelCall from "./advisor/hooks/pre-model-call.js";
|
|
33
|
-
import advisorUserPromptSubmit from "./advisor/hooks/user-prompt-submit.js";
|
|
34
|
-
import advisorPkg from "./advisor/package.json" with { type: "json" };
|
|
35
|
-
import advisorTool from "./advisor/tools/advisor.js";
|
|
36
29
|
import compactionPkg from "./compaction/package.json" with { type: "json" };
|
|
37
30
|
import emptyResponsePostModelCall from "./empty-response/hooks/post-model-call.js";
|
|
38
31
|
import emptyResponseStop from "./empty-response/hooks/stop.js";
|
|
@@ -329,30 +322,6 @@ export const defaultToolResultTruncatePlugin: Plugin = {
|
|
|
329
322
|
},
|
|
330
323
|
};
|
|
331
324
|
|
|
332
|
-
/**
|
|
333
|
-
* `advisor` — adds the model-visible `advisor` tool: a no-argument tool the
|
|
334
|
-
* model calls to consult a stronger inference profile (the `inference` call
|
|
335
|
-
* site with a `quality-optimized` override) on the full transcript, routed
|
|
336
|
-
* through the assistant's own inference. Three hooks feed it: `user-prompt-submit`
|
|
337
|
-
* seeds the capture, `pre-model-call` records the executor's system prompt and
|
|
338
|
-
* injects the steering that nudges the model to consult, and `post-model-call`
|
|
339
|
-
* snapshots the transcript the tool reads. `finalizeTool` fills the tool's
|
|
340
|
-
* defaults so it satisfies `Tool`, and `bootstrapPlugins` registers it into the
|
|
341
|
-
* catalog.
|
|
342
|
-
*/
|
|
343
|
-
export const defaultAdvisorPlugin: Plugin = {
|
|
344
|
-
manifest: {
|
|
345
|
-
name: advisorPkg.name,
|
|
346
|
-
version: advisorPkg.version,
|
|
347
|
-
},
|
|
348
|
-
hooks: {
|
|
349
|
-
"user-prompt-submit": advisorUserPromptSubmit,
|
|
350
|
-
"pre-model-call": advisorPreModelCall,
|
|
351
|
-
"post-model-call": advisorPostModelCall,
|
|
352
|
-
},
|
|
353
|
-
tools: [finalizeTool(advisorTool, "advisor")],
|
|
354
|
-
};
|
|
355
|
-
|
|
356
325
|
/**
|
|
357
326
|
* Full set of first-party default plugins. Used by
|
|
358
327
|
* {@link registerDefaultPlugins} to drive the registration loop; the array
|
|
@@ -375,9 +344,6 @@ function getAllDefaultPlugins(): readonly Plugin[] {
|
|
|
375
344
|
defaultCompactionPlugin,
|
|
376
345
|
defaultTitleGeneratePlugin,
|
|
377
346
|
memoryV3ShadowPlugin,
|
|
378
|
-
// Registered last so its capture hooks observe the fully-processed turn
|
|
379
|
-
// (memory injections, history repair) that the executor actually sees.
|
|
380
|
-
defaultAdvisorPlugin,
|
|
381
347
|
];
|
|
382
348
|
}
|
|
383
349
|
|
|
@@ -424,7 +390,6 @@ export function resetPluginRegistryAndRegisterDefaults(): void {
|
|
|
424
390
|
resetExplorationDriftStateForTests();
|
|
425
391
|
resetTaskProgressNudgeStateForTests();
|
|
426
392
|
resetSurfaceCompletionNudgeStoreForTests();
|
|
427
|
-
resetAdvisorStateForTests();
|
|
428
393
|
resetCaptionCacheForTests();
|
|
429
394
|
registerDefaultPlugins();
|
|
430
395
|
}
|
|
@@ -7,17 +7,28 @@ mock.module("../../../../util/logger.js", () => ({
|
|
|
7
7
|
getLogger: () => makeMockLogger(),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
+
// Keep the real exports (e.g. getQdrantClient) so this partial mock is harmless
|
|
11
|
+
// when section-dense-store's transitive imports pull them in; only
|
|
12
|
+
// resolveQdrantUrl is pinned to a fixed URL.
|
|
13
|
+
const realQdrantClient = await import("../../../../memory/qdrant-client.js");
|
|
10
14
|
mock.module("../../../../memory/qdrant-client.js", () => ({
|
|
15
|
+
...realQdrantClient,
|
|
11
16
|
resolveQdrantUrl: () => "http://127.0.0.1:6333",
|
|
12
17
|
}));
|
|
13
18
|
|
|
14
19
|
// Stub the shared embedding backend. Records the queries it was asked to embed
|
|
15
20
|
// and returns one deterministic vector so `denseLane` can issue the search.
|
|
21
|
+
// Keep the real exports (e.g. generateSparseEmbedding) so this partial mock is
|
|
22
|
+
// harmless when section-dense-store's transitive imports pull them in; only
|
|
23
|
+
// embedWithBackend is replaced.
|
|
24
|
+
const realEmbeddingBackend =
|
|
25
|
+
await import("../../../../memory/embedding-backend.js");
|
|
16
26
|
const embedState = {
|
|
17
27
|
calls: [] as string[][],
|
|
18
28
|
throws: null as Error | null,
|
|
19
29
|
};
|
|
20
30
|
mock.module("../../../../memory/embedding-backend.js", () => ({
|
|
31
|
+
...realEmbeddingBackend,
|
|
21
32
|
embedWithBackend: async (_config: unknown, inputs: string[]) => {
|
|
22
33
|
embedState.calls.push(inputs);
|
|
23
34
|
if (embedState.throws) throw embedState.throws;
|