@vellumai/assistant 0.4.3 → 0.4.4
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/.env.example +3 -0
- package/ARCHITECTURE.md +40 -3
- package/README.md +43 -35
- package/package.json +1 -1
- package/scripts/ipc/generate-swift.ts +1 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +58 -120
- package/src/__tests__/actor-token-service.test.ts +1099 -0
- package/src/__tests__/agent-loop.test.ts +51 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -5
- package/src/__tests__/assistant-id-boundary-guard.test.ts +125 -0
- package/src/__tests__/call-controller.test.ts +49 -0
- package/src/__tests__/call-pointer-message-composer.test.ts +171 -0
- package/src/__tests__/call-pointer-messages.test.ts +93 -3
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +42 -0
- package/src/__tests__/callback-handoff-copy.test.ts +186 -0
- package/src/__tests__/channel-approval-routes.test.ts +133 -12
- package/src/__tests__/channel-guardian.test.ts +0 -87
- package/src/__tests__/channel-readiness-service.test.ts +10 -16
- package/src/__tests__/checker.test.ts +33 -12
- package/src/__tests__/config-schema.test.ts +4 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +410 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +256 -0
- package/src/__tests__/conversation-routes.test.ts +12 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/daemon-server-session-init.test.ts +4 -0
- package/src/__tests__/guardian-actions-endpoint.test.ts +19 -14
- package/src/__tests__/guardian-dispatch.test.ts +8 -0
- package/src/__tests__/guardian-outbound-http.test.ts +4 -4
- package/src/__tests__/guardian-question-mode.test.ts +200 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +178 -0
- package/src/__tests__/guardian-routing-state.test.ts +525 -0
- package/src/__tests__/handle-user-message-secret-resume.test.ts +2 -0
- package/src/__tests__/handlers-telegram-config.test.ts +0 -83
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +55 -0
- package/src/__tests__/headless-browser-navigate.test.ts +2 -0
- package/src/__tests__/ipc-snapshot.test.ts +18 -51
- package/src/__tests__/non-member-access-request.test.ts +131 -8
- package/src/__tests__/notification-decision-fallback.test.ts +129 -4
- package/src/__tests__/notification-decision-strategy.test.ts +62 -2
- package/src/__tests__/notification-guardian-path.test.ts +3 -0
- package/src/__tests__/recording-intent-handler.test.ts +1 -0
- package/src/__tests__/relay-server.test.ts +841 -39
- package/src/__tests__/send-endpoint-busy.test.ts +5 -0
- package/src/__tests__/session-agent-loop.test.ts +1 -0
- package/src/__tests__/session-confirmation-signals.test.ts +523 -0
- package/src/__tests__/session-init.benchmark.test.ts +0 -1
- package/src/__tests__/session-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +81 -2
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +21 -2
- package/src/__tests__/tool-grant-request-escalation.test.ts +333 -27
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +678 -0
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1064 -0
- package/src/__tests__/twilio-config.test.ts +2 -13
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-decision-primitive.ts +10 -2
- package/src/approvals/guardian-request-resolvers.ts +128 -9
- package/src/calls/call-constants.ts +21 -0
- package/src/calls/call-controller.ts +9 -2
- package/src/calls/call-domain.ts +28 -7
- package/src/calls/call-pointer-message-composer.ts +154 -0
- package/src/calls/call-pointer-messages.ts +106 -27
- package/src/calls/guardian-dispatch.ts +4 -2
- package/src/calls/relay-server.ts +424 -12
- package/src/calls/twilio-config.ts +4 -11
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/types.ts +3 -1
- package/src/cli.ts +5 -4
- package/src/config/bundled-skills/agentmail/SKILL.md +4 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +146 -10
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -1
- package/src/config/bundled-skills/email-setup/SKILL.md +1 -1
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +105 -81
- package/src/config/bundled-skills/messaging/SKILL.md +61 -12
- package/src/config/bundled-skills/messaging/TOOLS.json +58 -0
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +6 -1
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +35 -0
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +52 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +30 -39
- package/src/config/bundled-skills/twitter/SKILL.md +3 -3
- package/src/config/bundled-skills/vercel-token-setup/SKILL.md +1 -0
- package/src/config/calls-schema.ts +24 -0
- package/src/config/env.ts +22 -0
- package/src/config/feature-flag-registry.json +8 -0
- package/src/config/schema.ts +2 -2
- package/src/config/skills.ts +11 -0
- package/src/config/system-prompt.ts +11 -1
- package/src/config/templates/SOUL.md +2 -0
- package/src/config/vellum-skills/sms-setup/SKILL.md +71 -82
- package/src/config/vellum-skills/trusted-contacts/SKILL.md +10 -9
- package/src/config/vellum-skills/twilio-setup/SKILL.md +88 -73
- package/src/daemon/call-pointer-generators.ts +59 -0
- package/src/daemon/computer-use-session.ts +2 -5
- package/src/daemon/handlers/apps.ts +76 -20
- package/src/daemon/handlers/config-channels.ts +5 -55
- package/src/daemon/handlers/config-inbox.ts +9 -3
- package/src/daemon/handlers/config-ingress.ts +28 -3
- package/src/daemon/handlers/config-telegram.ts +12 -0
- package/src/daemon/handlers/config.ts +2 -6
- package/src/daemon/handlers/pairing.ts +2 -0
- package/src/daemon/handlers/sessions.ts +48 -3
- package/src/daemon/handlers/shared.ts +17 -2
- package/src/daemon/ipc-contract/integrations.ts +1 -99
- package/src/daemon/ipc-contract/messages.ts +47 -1
- package/src/daemon/ipc-contract/notifications.ts +11 -0
- package/src/daemon/ipc-contract-inventory.json +2 -4
- package/src/daemon/lifecycle.ts +17 -0
- package/src/daemon/server.ts +14 -1
- package/src/daemon/session-agent-loop-handlers.ts +20 -0
- package/src/daemon/session-agent-loop.ts +22 -11
- package/src/daemon/session-lifecycle.ts +1 -1
- package/src/daemon/session-process.ts +11 -1
- package/src/daemon/session-runtime-assembly.ts +3 -0
- package/src/daemon/session-surfaces.ts +3 -2
- package/src/daemon/session.ts +88 -1
- package/src/daemon/tool-side-effects.ts +22 -0
- package/src/home-base/prebuilt/brain-graph.html +1483 -0
- package/src/home-base/prebuilt/index.html +40 -0
- package/src/inbound/platform-callback-registration.ts +157 -0
- package/src/memory/canonical-guardian-store.ts +1 -1
- package/src/memory/db-init.ts +4 -0
- package/src/memory/migrations/038-actor-token-records.ts +39 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema.ts +16 -0
- package/src/messaging/provider-types.ts +24 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/adapter.ts +127 -0
- package/src/messaging/providers/sms/adapter.ts +40 -37
- package/src/notifications/adapters/macos.ts +45 -2
- package/src/notifications/broadcaster.ts +16 -0
- package/src/notifications/copy-composer.ts +39 -1
- package/src/notifications/decision-engine.ts +22 -9
- package/src/notifications/destination-resolver.ts +16 -2
- package/src/notifications/emit-signal.ts +16 -8
- package/src/notifications/guardian-question-mode.ts +419 -0
- package/src/notifications/signal.ts +14 -3
- package/src/permissions/checker.ts +13 -1
- package/src/permissions/prompter.ts +14 -0
- package/src/providers/anthropic/client.ts +20 -0
- package/src/providers/provider-send-message.ts +15 -3
- package/src/runtime/access-request-helper.ts +71 -1
- package/src/runtime/actor-token-service.ts +234 -0
- package/src/runtime/actor-token-store.ts +236 -0
- package/src/runtime/channel-approvals.ts +5 -3
- package/src/runtime/channel-readiness-service.ts +23 -64
- package/src/runtime/channel-readiness-types.ts +3 -4
- package/src/runtime/channel-retry-sweep.ts +4 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +197 -0
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-context-resolver.ts +82 -0
- package/src/runtime/guardian-outbound-actions.ts +0 -3
- package/src/runtime/guardian-reply-router.ts +67 -30
- package/src/runtime/guardian-vellum-migration.ts +57 -0
- package/src/runtime/http-server.ts +65 -12
- package/src/runtime/http-types.ts +13 -0
- package/src/runtime/invite-redemption-service.ts +8 -0
- package/src/runtime/local-actor-identity.ts +76 -0
- package/src/runtime/middleware/actor-token.ts +271 -0
- package/src/runtime/routes/approval-routes.ts +82 -7
- package/src/runtime/routes/brain-graph-routes.ts +222 -0
- package/src/runtime/routes/channel-readiness-routes.ts +71 -0
- package/src/runtime/routes/conversation-routes.ts +140 -52
- package/src/runtime/routes/events-routes.ts +20 -5
- package/src/runtime/routes/guardian-action-routes.ts +45 -3
- package/src/runtime/routes/guardian-approval-interception.ts +29 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +145 -0
- package/src/runtime/routes/inbound-message-handler.ts +143 -2
- package/src/runtime/routes/integration-routes.ts +7 -15
- package/src/runtime/routes/pairing-routes.ts +163 -0
- package/src/runtime/routes/twilio-routes.ts +934 -0
- package/src/runtime/tool-grant-request-helper.ts +3 -1
- package/src/security/oauth2.ts +27 -2
- package/src/security/token-manager.ts +46 -10
- package/src/tools/browser/browser-execution.ts +4 -3
- package/src/tools/browser/browser-handoff.ts +10 -18
- package/src/tools/browser/browser-manager.ts +80 -25
- package/src/tools/browser/browser-screencast.ts +35 -119
- package/src/tools/permission-checker.ts +15 -4
- package/src/tools/tool-approval-handler.ts +242 -18
- package/src/__tests__/handlers-twilio-config.test.ts +0 -1928
- package/src/daemon/handlers/config-twilio.ts +0 -1082
|
@@ -2,47 +2,126 @@
|
|
|
2
2
|
* Concise pointer/status messages posted to the initiating conversation
|
|
3
3
|
* so the user sees call lifecycle events without the full transcript
|
|
4
4
|
* (which lives in the dedicated voice conversation).
|
|
5
|
+
*
|
|
6
|
+
* Trust-aware: trusted audiences receive assistant-generated copy when a
|
|
7
|
+
* generator is available; untrusted/unknown audiences always receive
|
|
8
|
+
* deterministic fallback text.
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import * as conversationStore from '../memory/conversation-store.js';
|
|
12
|
+
import type { PointerCopyGenerator } from '../runtime/http-types.js';
|
|
13
|
+
import { getLogger } from '../util/logger.js';
|
|
14
|
+
import {
|
|
15
|
+
type CallPointerMessageContext,
|
|
16
|
+
composeCallPointerMessageGenerative,
|
|
17
|
+
getPointerFallbackMessage,
|
|
18
|
+
} from './call-pointer-message-composer.js';
|
|
19
|
+
|
|
20
|
+
const log = getLogger('call-pointer-messages');
|
|
8
21
|
|
|
9
22
|
export type PointerEvent = 'started' | 'completed' | 'failed' | 'guardian_verification_succeeded' | 'guardian_verification_failed';
|
|
10
23
|
|
|
24
|
+
export type PointerAudienceMode = 'auto' | 'trusted' | 'untrusted';
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Module-level generator injection (set by daemon lifecycle at startup)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
let pointerCopyGenerator: PointerCopyGenerator | undefined;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Inject the daemon-provided pointer copy generator.
|
|
34
|
+
* Called from daemon/lifecycle.ts at startup, following the same pattern
|
|
35
|
+
* as setRelayBroadcast.
|
|
36
|
+
*/
|
|
37
|
+
export function setPointerCopyGenerator(generator: PointerCopyGenerator): void {
|
|
38
|
+
pointerCopyGenerator = generator;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** @internal Reset for tests. */
|
|
42
|
+
export function resetPointerCopyGenerator(): void {
|
|
43
|
+
pointerCopyGenerator = undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Trust resolution
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve whether the audience for a pointer message is trusted.
|
|
52
|
+
*
|
|
53
|
+
* Trusted when:
|
|
54
|
+
* - conversation threadType is 'private' (local desktop-origin context)
|
|
55
|
+
* - conversation origin channel is 'vellum' (desktop app)
|
|
56
|
+
*
|
|
57
|
+
* Untrusted by default when insufficient evidence.
|
|
58
|
+
*/
|
|
59
|
+
function resolvePointerAudienceTrust(conversationId: string): boolean {
|
|
60
|
+
try {
|
|
61
|
+
const threadType = conversationStore.getConversationThreadType(conversationId);
|
|
62
|
+
if (threadType === 'private') return true;
|
|
63
|
+
|
|
64
|
+
const originChannel = conversationStore.getConversationOriginChannel(conversationId);
|
|
65
|
+
if (originChannel === 'vellum') return true;
|
|
66
|
+
} catch {
|
|
67
|
+
// Conversation may not exist or DB may be unavailable — default untrusted.
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Public API
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
11
77
|
export async function addPointerMessage(
|
|
12
78
|
conversationId: string,
|
|
13
79
|
event: PointerEvent,
|
|
14
80
|
phoneNumber: string,
|
|
15
81
|
extra?: { duration?: string; reason?: string; verificationCode?: string; channel?: string },
|
|
82
|
+
audienceMode: PointerAudienceMode = 'auto',
|
|
16
83
|
): Promise<void> {
|
|
84
|
+
const context: CallPointerMessageContext = {
|
|
85
|
+
scenario: event,
|
|
86
|
+
phoneNumber,
|
|
87
|
+
duration: extra?.duration,
|
|
88
|
+
reason: extra?.reason,
|
|
89
|
+
verificationCode: extra?.verificationCode,
|
|
90
|
+
channel: extra?.channel,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Build required-facts list so generated text cannot drop key details.
|
|
94
|
+
const requiredFacts: string[] = [phoneNumber];
|
|
95
|
+
if (extra?.duration) requiredFacts.push(extra.duration);
|
|
96
|
+
if (extra?.verificationCode) requiredFacts.push(extra.verificationCode);
|
|
97
|
+
if (extra?.reason) requiredFacts.push(extra.reason);
|
|
98
|
+
|
|
99
|
+
// Enforce lifecycle outcome keywords so the LLM cannot rewrite e.g. a
|
|
100
|
+
// "failed" event as a success — the generated text must contain the
|
|
101
|
+
// outcome word verbatim.
|
|
102
|
+
const eventOutcomeKeywords: Record<PointerEvent, string | undefined> = {
|
|
103
|
+
started: 'started',
|
|
104
|
+
completed: 'completed',
|
|
105
|
+
failed: 'failed',
|
|
106
|
+
guardian_verification_succeeded: 'succeeded',
|
|
107
|
+
guardian_verification_failed: 'failed',
|
|
108
|
+
};
|
|
109
|
+
const outcomeKeyword = eventOutcomeKeywords[event];
|
|
110
|
+
if (outcomeKeyword) requiredFacts.push(outcomeKeyword);
|
|
111
|
+
|
|
17
112
|
let text: string;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
break;
|
|
29
|
-
case 'failed':
|
|
30
|
-
text = extra?.reason
|
|
31
|
-
? `\u{1F4DE} Call to ${phoneNumber} failed: ${extra.reason}.`
|
|
32
|
-
: `\u{1F4DE} Call to ${phoneNumber} failed.`;
|
|
33
|
-
break;
|
|
34
|
-
case 'guardian_verification_succeeded': {
|
|
35
|
-
const ch = extra?.channel ?? 'voice';
|
|
36
|
-
text = `\u{2705} Guardian verification (${ch}) for ${phoneNumber} succeeded.`;
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
case 'guardian_verification_failed': {
|
|
40
|
-
const ch = extra?.channel ?? 'voice';
|
|
41
|
-
text = extra?.reason
|
|
42
|
-
? `\u{274C} Guardian verification (${ch}) for ${phoneNumber} failed: ${extra.reason}.`
|
|
43
|
-
: `\u{274C} Guardian verification (${ch}) for ${phoneNumber} failed.`;
|
|
44
|
-
break;
|
|
113
|
+
|
|
114
|
+
const isTrusted =
|
|
115
|
+
audienceMode === 'trusted' ||
|
|
116
|
+
(audienceMode === 'auto' && resolvePointerAudienceTrust(conversationId));
|
|
117
|
+
|
|
118
|
+
if (isTrusted && pointerCopyGenerator) {
|
|
119
|
+
text = await composeCallPointerMessageGenerative(context, { requiredFacts }, pointerCopyGenerator);
|
|
120
|
+
} else {
|
|
121
|
+
if (!isTrusted && pointerCopyGenerator) {
|
|
122
|
+
log.debug({ event, conversationId }, 'Untrusted audience — using deterministic pointer copy');
|
|
45
123
|
}
|
|
124
|
+
text = getPointerFallbackMessage(context);
|
|
46
125
|
}
|
|
47
126
|
|
|
48
127
|
// Pointer messages are assistant-generated status updates in the initiating
|
|
@@ -149,6 +149,7 @@ async function dispatchGuardianQuestionInner(params: GuardianDispatchParams): Pr
|
|
|
149
149
|
// Route through the canonical notification pipeline. The paired vellum
|
|
150
150
|
// conversation from this pipeline is the canonical guardian thread.
|
|
151
151
|
let vellumDeliveryId: string | null = null;
|
|
152
|
+
const requestCode = request.requestCode ?? request.id.slice(0, 6).toUpperCase();
|
|
152
153
|
const signalResult = await emitNotificationSignal({
|
|
153
154
|
sourceEventName: 'guardian.question',
|
|
154
155
|
sourceChannel: 'voice',
|
|
@@ -163,10 +164,11 @@ async function dispatchGuardianQuestionInner(params: GuardianDispatchParams): Pr
|
|
|
163
164
|
},
|
|
164
165
|
contextPayload: {
|
|
165
166
|
requestId: request.id,
|
|
166
|
-
|
|
167
|
+
requestKind: 'pending_question',
|
|
168
|
+
requestCode,
|
|
167
169
|
callSessionId,
|
|
170
|
+
toolName,
|
|
168
171
|
questionText: pendingQuestion.questionText,
|
|
169
|
-
pendingQuestionId: pendingQuestion.id,
|
|
170
172
|
activeGuardianRequestCount,
|
|
171
173
|
},
|
|
172
174
|
conversationAffinityHint,
|