@vellumai/assistant 0.3.19 → 0.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +151 -15
- package/Dockerfile +1 -0
- package/README.md +40 -4
- package/docs/architecture/integrations.md +7 -11
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +54 -0
- package/src/__tests__/approval-primitive.test.ts +540 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +206 -0
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +198 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +272 -0
- package/src/__tests__/call-controller.test.ts +439 -108
- package/src/__tests__/channel-invite-transport.test.ts +264 -0
- package/src/__tests__/cli.test.ts +42 -1
- package/src/__tests__/config-schema.test.ts +11 -127
- package/src/__tests__/config-watcher.test.ts +0 -8
- package/src/__tests__/daemon-lifecycle.test.ts +1 -0
- package/src/__tests__/daemon-server-session-init.test.ts +8 -2
- package/src/__tests__/diff.test.ts +22 -0
- package/src/__tests__/guardian-action-copy-generator.test.ts +5 -0
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +300 -32
- package/src/__tests__/guardian-action-late-reply.test.ts +546 -1
- package/src/__tests__/guardian-actions-endpoint.test.ts +774 -0
- package/src/__tests__/guardian-control-plane-policy.test.ts +36 -3
- package/src/__tests__/guardian-dispatch.test.ts +124 -0
- package/src/__tests__/guardian-grant-minting.test.ts +6 -17
- package/src/__tests__/inbound-invite-redemption.test.ts +367 -0
- package/src/__tests__/invite-redemption-service.test.ts +306 -0
- package/src/__tests__/ipc-snapshot.test.ts +57 -0
- package/src/__tests__/notification-decision-fallback.test.ts +88 -0
- package/src/__tests__/sandbox-diagnostics.test.ts +6 -249
- package/src/__tests__/sandbox-host-parity.test.ts +6 -13
- package/src/__tests__/scoped-approval-grants.test.ts +6 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -4
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -19
- package/src/__tests__/session-load-history-repair.test.ts +169 -2
- package/src/__tests__/session-runtime-assembly.test.ts +33 -5
- package/src/__tests__/skill-feature-flags-integration.test.ts +171 -0
- package/src/__tests__/skill-feature-flags.test.ts +188 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +141 -0
- package/src/__tests__/skill-mirror-parity.test.ts +1 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +363 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/terminal-sandbox.test.ts +142 -9
- package/src/__tests__/terminal-tools.test.ts +2 -93
- package/src/__tests__/thread-seed-composer.test.ts +18 -0
- package/src/__tests__/tool-approval-handler.test.ts +350 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +8 -10
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +46 -84
- package/src/agent/loop.ts +36 -1
- package/src/approvals/approval-primitive.ts +381 -0
- package/src/approvals/guardian-decision-primitive.ts +191 -0
- package/src/calls/call-controller.ts +252 -209
- package/src/calls/call-domain.ts +44 -6
- package/src/calls/guardian-dispatch.ts +48 -0
- package/src/calls/types.ts +1 -1
- package/src/calls/voice-session-bridge.ts +46 -30
- package/src/cli/core-commands.ts +0 -4
- package/src/cli.ts +76 -34
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +179 -0
- package/src/config/assistant-feature-flags.ts +162 -0
- package/src/config/bundled-skills/api-mapping/icon.svg +18 -0
- package/src/config/bundled-skills/messaging/TOOLS.json +30 -0
- package/src/config/bundled-skills/messaging/tools/slack-delete-message.ts +24 -0
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/reminder/SKILL.md +49 -2
- package/src/config/bundled-skills/time-based-actions/SKILL.md +49 -2
- package/src/config/bundled-skills/voice-setup/SKILL.md +122 -0
- package/src/config/core-schema.ts +1 -1
- package/src/config/env-registry.ts +10 -0
- package/src/config/feature-flag-registry.json +61 -0
- package/src/config/loader.ts +22 -1
- package/src/config/sandbox-schema.ts +0 -39
- package/src/config/schema.ts +6 -2
- package/src/config/skill-state.ts +34 -0
- package/src/config/skills-schema.ts +0 -1
- package/src/config/skills.ts +9 -0
- package/src/config/system-prompt.ts +110 -46
- package/src/config/templates/SOUL.md +1 -1
- package/src/config/types.ts +19 -1
- package/src/config/vellum-skills/catalog.json +1 -1
- package/src/config/vellum-skills/guardian-verify-setup/SKILL.md +1 -0
- package/src/config/vellum-skills/sms-setup/SKILL.md +1 -1
- package/src/config/vellum-skills/telegram-setup/SKILL.md +1 -1
- package/src/config/vellum-skills/trusted-contacts/SKILL.md +104 -3
- package/src/config/vellum-skills/twilio-setup/SKILL.md +1 -1
- package/src/daemon/config-watcher.ts +0 -1
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/guardian-invite-intent.ts +124 -0
- package/src/daemon/handlers/avatar.ts +68 -0
- package/src/daemon/handlers/browser.ts +2 -2
- package/src/daemon/handlers/guardian-actions.ts +120 -0
- package/src/daemon/handlers/index.ts +4 -0
- package/src/daemon/handlers/sessions.ts +19 -0
- package/src/daemon/handlers/shared.ts +3 -1
- package/src/daemon/install-cli-launchers.ts +58 -13
- package/src/daemon/ipc-contract/guardian-actions.ts +53 -0
- package/src/daemon/ipc-contract/sessions.ts +8 -2
- package/src/daemon/ipc-contract/settings.ts +25 -2
- package/src/daemon/ipc-contract-inventory.json +10 -0
- package/src/daemon/ipc-contract.ts +4 -0
- package/src/daemon/lifecycle.ts +6 -2
- package/src/daemon/main.ts +1 -0
- package/src/daemon/server.ts +1 -0
- package/src/daemon/session-lifecycle.ts +52 -7
- package/src/daemon/session-memory.ts +45 -0
- package/src/daemon/session-process.ts +258 -432
- package/src/daemon/session-runtime-assembly.ts +12 -0
- package/src/daemon/session-skill-tools.ts +14 -1
- package/src/daemon/session-tool-setup.ts +5 -0
- package/src/daemon/session.ts +11 -0
- package/src/daemon/tool-side-effects.ts +35 -9
- package/src/index.ts +0 -2
- package/src/memory/conversation-display-order-migration.ts +44 -0
- package/src/memory/conversation-queries.ts +2 -0
- package/src/memory/conversation-store.ts +91 -0
- package/src/memory/db-init.ts +5 -1
- package/src/memory/embedding-local.ts +13 -8
- package/src/memory/guardian-action-store.ts +125 -2
- package/src/memory/ingress-invite-store.ts +95 -1
- package/src/memory/migrations/035-guardian-action-supersession.ts +23 -0
- package/src/memory/migrations/index.ts +2 -1
- package/src/memory/schema.ts +5 -1
- package/src/memory/scoped-approval-grants.ts +14 -5
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/types.ts +5 -0
- package/src/notifications/decision-engine.ts +49 -12
- package/src/notifications/emit-signal.ts +7 -0
- package/src/notifications/signal.ts +7 -0
- package/src/notifications/thread-seed-composer.ts +2 -1
- package/src/runtime/channel-approval-types.ts +16 -6
- package/src/runtime/channel-approvals.ts +19 -15
- package/src/runtime/channel-invite-transport.ts +85 -0
- package/src/runtime/channel-invite-transports/telegram.ts +105 -0
- package/src/runtime/guardian-action-grant-minter.ts +92 -35
- package/src/runtime/guardian-action-message-composer.ts +30 -0
- package/src/runtime/guardian-decision-types.ts +91 -0
- package/src/runtime/http-server.ts +23 -1
- package/src/runtime/ingress-service.ts +22 -0
- package/src/runtime/invite-redemption-service.ts +181 -0
- package/src/runtime/invite-redemption-templates.ts +39 -0
- package/src/runtime/routes/call-routes.ts +2 -1
- package/src/runtime/routes/guardian-action-routes.ts +206 -0
- package/src/runtime/routes/guardian-approval-interception.ts +66 -190
- package/src/runtime/routes/inbound-message-handler.ts +486 -394
- package/src/runtime/routes/pairing-routes.ts +4 -0
- package/src/security/encrypted-store.ts +31 -17
- package/src/security/keychain.ts +176 -2
- package/src/security/secure-keys.ts +97 -0
- package/src/security/tool-approval-digest.ts +1 -1
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/browser-manager.ts +46 -32
- package/src/tools/browser/browser-screencast.ts +2 -2
- package/src/tools/calls/call-start.ts +1 -1
- package/src/tools/executor.ts +22 -17
- package/src/tools/network/script-proxy/session-manager.ts +1 -5
- package/src/tools/skills/load.ts +22 -8
- package/src/tools/system/avatar-generator.ts +119 -0
- package/src/tools/system/navigate-settings.ts +65 -0
- package/src/tools/system/open-system-settings.ts +75 -0
- package/src/tools/system/voice-config.ts +121 -32
- package/src/tools/terminal/backends/native.ts +40 -19
- package/src/tools/terminal/backends/types.ts +3 -3
- package/src/tools/terminal/parser.ts +1 -1
- package/src/tools/terminal/sandbox-diagnostics.ts +6 -87
- package/src/tools/terminal/sandbox.ts +1 -12
- package/src/tools/terminal/shell.ts +3 -31
- package/src/tools/tool-approval-handler.ts +141 -3
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +6 -0
- package/src/util/diff.ts +36 -13
- package/Dockerfile.sandbox +0 -5
- package/src/__tests__/doordash-client.test.ts +0 -187
- package/src/__tests__/doordash-session.test.ts +0 -154
- package/src/__tests__/signup-e2e.test.ts +0 -354
- package/src/__tests__/terminal-sandbox-docker.test.ts +0 -1065
- package/src/__tests__/terminal-sandbox.integration.test.ts +0 -180
- package/src/cli/doordash.ts +0 -1057
- package/src/config/bundled-skills/doordash/SKILL.md +0 -163
- package/src/config/templates/LOOKS.md +0 -25
- package/src/doordash/cart-queries.ts +0 -787
- package/src/doordash/client.ts +0 -1016
- package/src/doordash/order-queries.ts +0 -85
- package/src/doordash/queries.ts +0 -13
- package/src/doordash/query-extractor.ts +0 -94
- package/src/doordash/search-queries.ts +0 -203
- package/src/doordash/session.ts +0 -84
- package/src/doordash/store-queries.ts +0 -246
- package/src/doordash/types.ts +0 -367
- package/src/tools/terminal/backends/docker.ts +0 -379
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Installs standalone CLI launcher scripts in ~/.vellum/bin/ so that
|
|
3
|
-
* integration commands (e.g. `
|
|
4
|
-
*
|
|
3
|
+
* integration commands (e.g. `map`) can be invoked directly without
|
|
4
|
+
* requiring `vellum` on PATH.
|
|
5
5
|
*
|
|
6
6
|
* Each launcher is a shell script that hardcodes absolute paths to `bun`
|
|
7
7
|
* and the CLI entrypoint, forwarding all arguments to the appropriate
|
|
8
8
|
* subcommand.
|
|
9
|
+
*
|
|
10
|
+
* Commands are split into two categories:
|
|
11
|
+
* - CORE_COMMANDS: always installed, dispatched via the main CLI entrypoint
|
|
12
|
+
* - Skill CLI launchers: dynamically discovered from installed skills that
|
|
13
|
+
* declare a `cli` entry in their SKILL.md frontmatter metadata
|
|
9
14
|
*/
|
|
10
15
|
|
|
11
16
|
import { execSync } from 'node:child_process';
|
|
12
|
-
import { chmodSync,existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
17
|
+
import { chmodSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
13
18
|
import { homedir } from 'node:os';
|
|
14
19
|
import { join } from 'node:path';
|
|
15
20
|
|
|
21
|
+
import { loadSkillCatalog } from '../config/skills.js';
|
|
16
22
|
import { getLogger } from '../util/logger.js';
|
|
17
23
|
|
|
18
24
|
const log = getLogger('install-cli-launchers');
|
|
19
25
|
|
|
20
|
-
/**
|
|
21
|
-
const
|
|
26
|
+
/** Core subcommands dispatched via the main CLI entrypoint (index.ts). */
|
|
27
|
+
const CORE_COMMANDS = ['map'];
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* Resolve the absolute path to the bun binary.
|
|
@@ -68,9 +74,13 @@ function hasSystemConflict(name: string, binDir: string): boolean {
|
|
|
68
74
|
* Install standalone CLI launcher scripts in ~/.vellum/bin/.
|
|
69
75
|
*
|
|
70
76
|
* For each integration command, generates a shell script that execs
|
|
71
|
-
* bun with the
|
|
77
|
+
* bun with the appropriate entrypoint.
|
|
72
78
|
* Uses the short name by default (e.g. `doordash`), falling back to
|
|
73
79
|
* `vellum-<name>` if the short name conflicts with an existing system binary.
|
|
80
|
+
*
|
|
81
|
+
* Skill CLI launchers are discovered dynamically: any installed skill whose
|
|
82
|
+
* SKILL.md frontmatter declares `metadata.vellum.cli` will get a launcher
|
|
83
|
+
* pointing to the declared entry file within the skill directory.
|
|
74
84
|
*/
|
|
75
85
|
export function installCliLaunchers(): void {
|
|
76
86
|
const binDir = join(homedir(), '.vellum', 'bin');
|
|
@@ -83,13 +93,13 @@ export function installCliLaunchers(): void {
|
|
|
83
93
|
return;
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
const
|
|
87
|
-
if (!existsSync(
|
|
96
|
+
const mainEntrypoint = resolveCliEntrypoint();
|
|
97
|
+
if (!existsSync(mainEntrypoint)) {
|
|
88
98
|
// In compiled builds (e.g. macOS app via `bun build --compile`), the
|
|
89
99
|
// source tree isn't available. Launcher scripts are a dev-mode
|
|
90
100
|
// convenience; compiled builds use their own command dispatch, so we
|
|
91
101
|
// silently skip installation.
|
|
92
|
-
log.debug({ entrypoint }, 'CLI entrypoint not found (compiled build?) — skipping launcher installation');
|
|
102
|
+
log.debug({ entrypoint: mainEntrypoint }, 'CLI entrypoint not found (compiled build?) — skipping launcher installation');
|
|
93
103
|
return;
|
|
94
104
|
}
|
|
95
105
|
|
|
@@ -97,18 +107,53 @@ export function installCliLaunchers(): void {
|
|
|
97
107
|
mkdirSync(binDir, { recursive: true });
|
|
98
108
|
}
|
|
99
109
|
|
|
100
|
-
|
|
110
|
+
const installed: string[] = [];
|
|
111
|
+
|
|
112
|
+
// Install core command launchers (dispatched via main CLI)
|
|
113
|
+
for (const name of CORE_COMMANDS) {
|
|
101
114
|
const launcherName = hasSystemConflict(name, binDir) ? `vellum-${name}` : name;
|
|
102
115
|
const launcherPath = join(binDir, launcherName);
|
|
103
116
|
|
|
104
117
|
const script = `#!/bin/bash
|
|
105
|
-
exec "${bunPath}" "${
|
|
118
|
+
exec "${bunPath}" "${mainEntrypoint}" ${name} "$@"
|
|
106
119
|
`;
|
|
107
120
|
|
|
108
121
|
writeFileSync(launcherPath, script);
|
|
109
122
|
chmodSync(launcherPath, 0o755);
|
|
110
|
-
|
|
123
|
+
installed.push(launcherName);
|
|
124
|
+
log.debug({ launcherName, launcherPath }, 'Installed core CLI launcher');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Discover and install skill CLI launchers from the skill catalog
|
|
128
|
+
try {
|
|
129
|
+
const catalog = loadSkillCatalog();
|
|
130
|
+
for (const skill of catalog) {
|
|
131
|
+
const cli = skill.metadata?.cli;
|
|
132
|
+
if (!cli?.command || !cli?.entry) continue;
|
|
133
|
+
|
|
134
|
+
const entrypoint = join(skill.directoryPath, cli.entry);
|
|
135
|
+
if (!existsSync(entrypoint)) {
|
|
136
|
+
log.debug({ skillId: skill.id, entrypoint }, 'Skill CLI entry point not found — skipping');
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const launcherName = hasSystemConflict(cli.command, binDir)
|
|
141
|
+
? `vellum-${cli.command}`
|
|
142
|
+
: cli.command;
|
|
143
|
+
const launcherPath = join(binDir, launcherName);
|
|
144
|
+
|
|
145
|
+
const script = `#!/bin/bash
|
|
146
|
+
exec "${bunPath}" "${entrypoint}" "$@"
|
|
147
|
+
`;
|
|
148
|
+
|
|
149
|
+
writeFileSync(launcherPath, script);
|
|
150
|
+
chmodSync(launcherPath, 0o755);
|
|
151
|
+
installed.push(launcherName);
|
|
152
|
+
log.debug({ launcherName, launcherPath, skillId: skill.id }, 'Installed skill CLI launcher');
|
|
153
|
+
}
|
|
154
|
+
} catch (err) {
|
|
155
|
+
log.warn({ err }, 'Failed to discover skill CLI launchers');
|
|
111
156
|
}
|
|
112
157
|
|
|
113
|
-
log.info({ binDir, commands:
|
|
158
|
+
log.info({ binDir, commands: installed }, 'CLI launchers installed');
|
|
114
159
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Guardian action decision IPC types.
|
|
2
|
+
// Enables desktop clients to fetch pending guardian prompts and submit
|
|
3
|
+
// button decisions deterministically (without text parsing).
|
|
4
|
+
|
|
5
|
+
// === Client -> Server ===
|
|
6
|
+
|
|
7
|
+
export interface GuardianActionsPendingRequest {
|
|
8
|
+
type: 'guardian_actions_pending_request';
|
|
9
|
+
conversationId: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface GuardianActionDecision {
|
|
13
|
+
type: 'guardian_action_decision';
|
|
14
|
+
requestId: string;
|
|
15
|
+
action: string;
|
|
16
|
+
conversationId?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// === Server -> Client ===
|
|
20
|
+
|
|
21
|
+
export interface GuardianActionsPendingResponse {
|
|
22
|
+
type: 'guardian_actions_pending_response';
|
|
23
|
+
conversationId: string;
|
|
24
|
+
prompts: Array<{
|
|
25
|
+
requestId: string;
|
|
26
|
+
requestCode: string;
|
|
27
|
+
state: string;
|
|
28
|
+
questionText: string;
|
|
29
|
+
toolName: string | null;
|
|
30
|
+
actions: Array<{ action: string; label: string }>;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
conversationId: string;
|
|
33
|
+
callSessionId: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface GuardianActionDecisionResponse {
|
|
38
|
+
type: 'guardian_action_decision_response';
|
|
39
|
+
applied: boolean;
|
|
40
|
+
reason?: string;
|
|
41
|
+
requestId?: string;
|
|
42
|
+
userText?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// --- Domain-level union aliases (consumed by the barrel file) ---
|
|
46
|
+
|
|
47
|
+
export type _GuardianActionsClientMessages =
|
|
48
|
+
| GuardianActionsPendingRequest
|
|
49
|
+
| GuardianActionDecision;
|
|
50
|
+
|
|
51
|
+
export type _GuardianActionsServerMessages =
|
|
52
|
+
| GuardianActionsPendingResponse
|
|
53
|
+
| GuardianActionDecisionResponse;
|
|
@@ -156,6 +156,11 @@ export interface ConversationSearchRequest {
|
|
|
156
156
|
maxMessagesPerConversation?: number;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
export interface ReorderThreadsRequest {
|
|
160
|
+
type: 'reorder_threads';
|
|
161
|
+
updates: Array<{ sessionId: string; displayOrder: number | null; isPinned: boolean }>;
|
|
162
|
+
}
|
|
163
|
+
|
|
159
164
|
// === Server → Client ===
|
|
160
165
|
|
|
161
166
|
export interface ConversationSearchMatchingMessage {
|
|
@@ -213,7 +218,7 @@ export interface AssistantAttention {
|
|
|
213
218
|
|
|
214
219
|
export interface SessionListResponse {
|
|
215
220
|
type: 'session_list_response';
|
|
216
|
-
sessions: Array<{ id: string; title: string; createdAt?: number; updatedAt: number; threadType?: ThreadType; source?: string; channelBinding?: ChannelBinding; conversationOriginChannel?: ChannelId; conversationOriginInterface?: InterfaceId; assistantAttention?: AssistantAttention }>;
|
|
221
|
+
sessions: Array<{ id: string; title: string; createdAt?: number; updatedAt: number; threadType?: ThreadType; source?: string; channelBinding?: ChannelBinding; conversationOriginChannel?: ChannelId; conversationOriginInterface?: InterfaceId; assistantAttention?: AssistantAttention; displayOrder?: number; isPinned?: boolean }>;
|
|
217
222
|
/** Whether more sessions exist beyond the returned page. */
|
|
218
223
|
hasMore?: boolean;
|
|
219
224
|
}
|
|
@@ -392,7 +397,8 @@ export type _SessionsClientMessages =
|
|
|
392
397
|
| SessionRenameRequest
|
|
393
398
|
| SessionsClearRequest
|
|
394
399
|
| ConversationSearchRequest
|
|
395
|
-
| MessageContentRequest
|
|
400
|
+
| MessageContentRequest
|
|
401
|
+
| ReorderThreadsRequest;
|
|
396
402
|
|
|
397
403
|
export type _SessionsServerMessages =
|
|
398
404
|
| AuthResult
|
|
@@ -9,6 +9,13 @@ export interface VoiceConfigUpdateRequest {
|
|
|
9
9
|
activationKey: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** Request from the client to generate a custom avatar via Gemini. */
|
|
13
|
+
export interface GenerateAvatarRequest {
|
|
14
|
+
type: 'generate_avatar';
|
|
15
|
+
/** Text description of the desired avatar appearance. */
|
|
16
|
+
description: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
// === Server → Client ===
|
|
13
20
|
|
|
14
21
|
/** Sent by the daemon to update a client-side setting (e.g. activation key). */
|
|
@@ -20,7 +27,23 @@ export interface ClientSettingsUpdate {
|
|
|
20
27
|
value: string;
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
/** Sent by the daemon after the avatar image has been regenerated and saved to disk. */
|
|
31
|
+
export interface AvatarUpdated {
|
|
32
|
+
type: 'avatar_updated';
|
|
33
|
+
/** Absolute path to the updated avatar image file. */
|
|
34
|
+
avatarPath: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Response to a generate_avatar request indicating success or failure. */
|
|
38
|
+
export interface GenerateAvatarResponse {
|
|
39
|
+
type: 'generate_avatar_response';
|
|
40
|
+
/** Whether the avatar was generated successfully. */
|
|
41
|
+
success: boolean;
|
|
42
|
+
/** Error message when success is false. */
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
23
46
|
// --- Domain-level union aliases (consumed by the barrel file) ---
|
|
24
47
|
|
|
25
|
-
export type _SettingsClientMessages = VoiceConfigUpdateRequest;
|
|
26
|
-
export type _SettingsServerMessages = ClientSettingsUpdate;
|
|
48
|
+
export type _SettingsClientMessages = VoiceConfigUpdateRequest | GenerateAvatarRequest;
|
|
49
|
+
export type _SettingsServerMessages = ClientSettingsUpdate | AvatarUpdated | GenerateAvatarResponse;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"_ComputerUseClientMessages",
|
|
6
6
|
"_DiagnosticsClientMessages",
|
|
7
7
|
"_DocumentsClientMessages",
|
|
8
|
+
"_GuardianActionsClientMessages",
|
|
8
9
|
"_InboxClientMessages",
|
|
9
10
|
"_IntegrationsClientMessages",
|
|
10
11
|
"_MessagesClientMessages",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"_ComputerUseServerMessages",
|
|
29
30
|
"_DiagnosticsServerMessages",
|
|
30
31
|
"_DocumentsServerMessages",
|
|
32
|
+
"_GuardianActionsServerMessages",
|
|
31
33
|
"_InboxServerMessages",
|
|
32
34
|
"_IntegrationsServerMessages",
|
|
33
35
|
"_MemoryServerMessages",
|
|
@@ -86,7 +88,10 @@
|
|
|
86
88
|
"fork_shared_app",
|
|
87
89
|
"gallery_install",
|
|
88
90
|
"gallery_list",
|
|
91
|
+
"generate_avatar",
|
|
89
92
|
"get_signing_identity_response",
|
|
93
|
+
"guardian_action_decision",
|
|
94
|
+
"guardian_actions_pending_request",
|
|
90
95
|
"guardian_verification",
|
|
91
96
|
"heartbeat_checklist_read",
|
|
92
97
|
"heartbeat_checklist_write",
|
|
@@ -124,6 +129,7 @@
|
|
|
124
129
|
"reminder_cancel",
|
|
125
130
|
"reminders_list",
|
|
126
131
|
"remove_trust_rule",
|
|
132
|
+
"reorder_threads",
|
|
127
133
|
"ride_shotgun_start",
|
|
128
134
|
"ride_shotgun_stop",
|
|
129
135
|
"sandbox_set",
|
|
@@ -210,6 +216,7 @@
|
|
|
210
216
|
"assistant_text_delta",
|
|
211
217
|
"assistant_thinking_delta",
|
|
212
218
|
"auth_result",
|
|
219
|
+
"avatar_updated",
|
|
213
220
|
"browser_cdp_request",
|
|
214
221
|
"browser_frame",
|
|
215
222
|
"browser_handoff_request",
|
|
@@ -236,9 +243,12 @@
|
|
|
236
243
|
"fork_shared_app_response",
|
|
237
244
|
"gallery_install_response",
|
|
238
245
|
"gallery_list_response",
|
|
246
|
+
"generate_avatar_response",
|
|
239
247
|
"generation_cancelled",
|
|
240
248
|
"generation_handoff",
|
|
241
249
|
"get_signing_identity",
|
|
250
|
+
"guardian_action_decision_response",
|
|
251
|
+
"guardian_actions_pending_response",
|
|
242
252
|
"guardian_verification_response",
|
|
243
253
|
"heartbeat_alert",
|
|
244
254
|
"heartbeat_checklist_response",
|
|
@@ -18,6 +18,7 @@ export * from './ipc-contract/browser.js';
|
|
|
18
18
|
export * from './ipc-contract/computer-use.js';
|
|
19
19
|
export * from './ipc-contract/diagnostics.js';
|
|
20
20
|
export * from './ipc-contract/documents.js';
|
|
21
|
+
export * from './ipc-contract/guardian-actions.js';
|
|
21
22
|
export * from './ipc-contract/inbox.js';
|
|
22
23
|
export * from './ipc-contract/integrations.js';
|
|
23
24
|
export * from './ipc-contract/memory.js';
|
|
@@ -42,6 +43,7 @@ import type { _BrowserClientMessages, _BrowserServerMessages } from './ipc-contr
|
|
|
42
43
|
import type { _ComputerUseClientMessages, _ComputerUseServerMessages } from './ipc-contract/computer-use.js';
|
|
43
44
|
import type { _DiagnosticsClientMessages, _DiagnosticsServerMessages } from './ipc-contract/diagnostics.js';
|
|
44
45
|
import type { _DocumentsClientMessages, _DocumentsServerMessages } from './ipc-contract/documents.js';
|
|
46
|
+
import type { _GuardianActionsClientMessages, _GuardianActionsServerMessages } from './ipc-contract/guardian-actions.js';
|
|
45
47
|
import type { _InboxClientMessages, _InboxServerMessages } from './ipc-contract/inbox.js';
|
|
46
48
|
import type { _IntegrationsClientMessages, _IntegrationsServerMessages } from './ipc-contract/integrations.js';
|
|
47
49
|
import type { _MemoryServerMessages } from './ipc-contract/memory.js';
|
|
@@ -83,6 +85,7 @@ export type ClientMessage =
|
|
|
83
85
|
| _BrowserClientMessages
|
|
84
86
|
| _SubagentsClientMessages
|
|
85
87
|
| _DocumentsClientMessages
|
|
88
|
+
| _GuardianActionsClientMessages
|
|
86
89
|
| _WorkspaceClientMessages
|
|
87
90
|
| _SchedulesClientMessages
|
|
88
91
|
| _DiagnosticsClientMessages
|
|
@@ -107,6 +110,7 @@ export type ServerMessage =
|
|
|
107
110
|
| _BrowserServerMessages
|
|
108
111
|
| _SubagentsServerMessages
|
|
109
112
|
| _DocumentsServerMessages
|
|
113
|
+
| _GuardianActionsServerMessages
|
|
110
114
|
| _MemoryServerMessages
|
|
111
115
|
| _WorkspaceServerMessages
|
|
112
116
|
| _SchedulesServerMessages
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -57,7 +57,7 @@ import type { ServerMessage } from './ipc-protocol.js';
|
|
|
57
57
|
import { initializeProvidersAndTools, registerMessagingProviders,registerWatcherProviders } from './providers-setup.js';
|
|
58
58
|
import { seedInterfaceFiles } from './seed-files.js';
|
|
59
59
|
import { DaemonServer } from './server.js';
|
|
60
|
-
import { setGuardianActionCopyGenerator, setGuardianFollowUpConversationGenerator } from './session-process.js';
|
|
60
|
+
import { setApprovalConversationGenerator, setGuardianActionCopyGenerator, setGuardianFollowUpConversationGenerator } from './session-process.js';
|
|
61
61
|
import { initSlashPairingContext } from './session-slash.js';
|
|
62
62
|
import { installShutdownHandlers } from './shutdown-handlers.js';
|
|
63
63
|
|
|
@@ -307,7 +307,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
307
307
|
server.persistAndProcessMessage(conversationId, content, attachmentIds, options, sourceChannel, sourceInterface),
|
|
308
308
|
interfacesDir: getInterfacesDir(),
|
|
309
309
|
approvalCopyGenerator: createApprovalCopyGenerator(),
|
|
310
|
-
approvalConversationGenerator:
|
|
310
|
+
approvalConversationGenerator: (() => {
|
|
311
|
+
const gen = createApprovalConversationGenerator();
|
|
312
|
+
setApprovalConversationGenerator(gen);
|
|
313
|
+
return gen;
|
|
314
|
+
})(),
|
|
311
315
|
guardianActionCopyGenerator: (() => {
|
|
312
316
|
const gen = createGuardianActionCopyGenerator();
|
|
313
317
|
setGuardianActionCopyGenerator(gen);
|
package/src/daemon/main.ts
CHANGED
package/src/daemon/server.ts
CHANGED
|
@@ -795,6 +795,7 @@ export class DaemonServer {
|
|
|
795
795
|
const resolvedInterface = resolveTurnInterface(sourceInterface);
|
|
796
796
|
session.setAssistantId(options?.assistantId ?? 'self');
|
|
797
797
|
session.setGuardianContext(options?.guardianContext ?? null);
|
|
798
|
+
await session.ensureActorScopedHistory();
|
|
798
799
|
session.setChannelCapabilities(resolveChannelCapabilities(sourceChannel, sourceInterface));
|
|
799
800
|
session.setCommandIntent(options?.commandIntent ?? null);
|
|
800
801
|
session.setTurnChannelContext({
|
|
@@ -19,10 +19,38 @@ import { repairHistory } from './history-repair.js';
|
|
|
19
19
|
import type { SurfaceData,SurfaceType, UsageStats } from './ipc-protocol.js';
|
|
20
20
|
import { unregisterCallNotifiers,unregisterWatchNotifiers } from './session-notifiers.js';
|
|
21
21
|
import type { MessageQueue } from './session-queue-manager.js';
|
|
22
|
+
import type { GuardianRuntimeContext } from './session-runtime-assembly.js';
|
|
22
23
|
import { resetSkillToolProjection } from './session-skill-tools.js';
|
|
23
24
|
|
|
24
25
|
const log = getLogger('session-lifecycle');
|
|
25
26
|
|
|
27
|
+
type GuardianActorRole = GuardianRuntimeContext['actorRole'];
|
|
28
|
+
|
|
29
|
+
function parseProvenanceActorRole(metadata: string | null): GuardianActorRole | undefined {
|
|
30
|
+
if (!metadata) return undefined;
|
|
31
|
+
try {
|
|
32
|
+
const parsed = JSON.parse(metadata) as { provenanceActorRole?: unknown };
|
|
33
|
+
const role = parsed?.provenanceActorRole;
|
|
34
|
+
if (role === 'guardian' || role === 'non-guardian' || role === 'unverified_channel') {
|
|
35
|
+
return role;
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// Ignore malformed metadata and treat as unknown provenance.
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isUntrustedActorRole(role: GuardianActorRole | undefined): boolean {
|
|
44
|
+
return role === 'non-guardian' || role === 'unverified_channel';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function filterMessagesForUntrustedActor(messages: conversationStore.MessageRow[]): conversationStore.MessageRow[] {
|
|
48
|
+
return messages.filter((m) => {
|
|
49
|
+
const provenanceRole = parseProvenanceActorRole(m.metadata);
|
|
50
|
+
return provenanceRole === 'non-guardian' || provenanceRole === 'unverified_channel';
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
26
54
|
// ── Context Interfaces ───────────────────────────────────────────────
|
|
27
55
|
|
|
28
56
|
export interface LoadFromDbContext {
|
|
@@ -31,6 +59,8 @@ export interface LoadFromDbContext {
|
|
|
31
59
|
usageStats: UsageStats;
|
|
32
60
|
contextCompactedMessageCount: number;
|
|
33
61
|
contextCompactedAt: number | null;
|
|
62
|
+
guardianContext?: { actorRole: GuardianActorRole };
|
|
63
|
+
loadedHistoryActorRole?: GuardianActorRole;
|
|
34
64
|
}
|
|
35
65
|
|
|
36
66
|
export interface AbortContext {
|
|
@@ -59,15 +89,28 @@ export interface DisposeContext extends AbortContext {
|
|
|
59
89
|
// ── loadFromDb ───────────────────────────────────────────────────────
|
|
60
90
|
|
|
61
91
|
export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
62
|
-
const
|
|
92
|
+
const actorRole = ctx.guardianContext?.actorRole;
|
|
93
|
+
const allDbMessages = conversationStore.getMessages(ctx.conversationId);
|
|
94
|
+
const dbMessages = isUntrustedActorRole(actorRole)
|
|
95
|
+
? filterMessagesForUntrustedActor(allDbMessages)
|
|
96
|
+
: allDbMessages;
|
|
63
97
|
|
|
64
98
|
const conv = conversationStore.getConversation(ctx.conversationId);
|
|
65
|
-
const contextSummary =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
99
|
+
const contextSummary = !isUntrustedActorRole(actorRole)
|
|
100
|
+
? conv?.contextSummary?.trim() || null
|
|
101
|
+
: null;
|
|
102
|
+
if (isUntrustedActorRole(actorRole)) {
|
|
103
|
+
// Compacted summaries may include trusted/guardian-only details, so we
|
|
104
|
+
// disable summary-based context for untrusted actor views.
|
|
105
|
+
ctx.contextCompactedMessageCount = 0;
|
|
106
|
+
ctx.contextCompactedAt = null;
|
|
107
|
+
} else {
|
|
108
|
+
ctx.contextCompactedMessageCount = Math.max(
|
|
109
|
+
0,
|
|
110
|
+
Math.min(conv?.contextCompactedMessageCount ?? 0, dbMessages.length),
|
|
111
|
+
);
|
|
112
|
+
ctx.contextCompactedAt = conv?.contextCompactedAt ?? null;
|
|
113
|
+
}
|
|
71
114
|
|
|
72
115
|
const parsedMessages: Message[] = dbMessages
|
|
73
116
|
.slice(ctx.contextCompactedMessageCount)
|
|
@@ -102,6 +145,8 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
102
145
|
};
|
|
103
146
|
}
|
|
104
147
|
|
|
148
|
+
ctx.loadedHistoryActorRole = actorRole;
|
|
149
|
+
|
|
105
150
|
log.info({ conversationId: ctx.conversationId, count: ctx.messages.length }, 'Loaded messages from DB');
|
|
106
151
|
}
|
|
107
152
|
|
|
@@ -39,6 +39,16 @@ export interface MemoryPrepareContext {
|
|
|
39
39
|
isInteractive?: boolean;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Returns true when the latest user turn is an internal tool-result-only
|
|
44
|
+
* message (no user-authored text/image content).
|
|
45
|
+
*/
|
|
46
|
+
function isToolResultOnlyUserTurn(message: Message | undefined): boolean {
|
|
47
|
+
return message?.role === 'user'
|
|
48
|
+
&& message.content.length > 0
|
|
49
|
+
&& message.content.every((block) => block.type === 'tool_result');
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
/**
|
|
43
53
|
* Build memory recall, dynamic profile, and conflict gate evaluation
|
|
44
54
|
* for a single agent loop turn. Returns the augmented run messages and
|
|
@@ -86,6 +96,41 @@ export async function prepareMemoryContext(
|
|
|
86
96
|
};
|
|
87
97
|
}
|
|
88
98
|
|
|
99
|
+
// Internal tool-result turns (assistant tool loop) should not trigger
|
|
100
|
+
// memory retrieval/profile injection. Injecting memory here repeats the
|
|
101
|
+
// same long recall block on every tool step and dramatically inflates
|
|
102
|
+
// per-step prompt size/latency.
|
|
103
|
+
const latestMessage = ctx.messages[ctx.messages.length - 1];
|
|
104
|
+
if (isToolResultOnlyUserTurn(latestMessage)) {
|
|
105
|
+
return {
|
|
106
|
+
runMessages: ctx.messages,
|
|
107
|
+
recall: {
|
|
108
|
+
enabled: false,
|
|
109
|
+
degraded: false,
|
|
110
|
+
injectedText: '',
|
|
111
|
+
lexicalHits: 0,
|
|
112
|
+
semanticHits: 0,
|
|
113
|
+
recencyHits: 0,
|
|
114
|
+
entityHits: 0,
|
|
115
|
+
relationSeedEntityCount: 0,
|
|
116
|
+
relationTraversedEdgeCount: 0,
|
|
117
|
+
relationNeighborEntityCount: 0,
|
|
118
|
+
relationExpandedItemCount: 0,
|
|
119
|
+
earlyTerminated: false,
|
|
120
|
+
mergedCount: 0,
|
|
121
|
+
selectedCount: 0,
|
|
122
|
+
rerankApplied: false,
|
|
123
|
+
injectedTokens: 0,
|
|
124
|
+
latencyMs: 0,
|
|
125
|
+
topCandidates: [],
|
|
126
|
+
} as Awaited<ReturnType<typeof buildMemoryRecall>>,
|
|
127
|
+
dynamicProfile: { text: '' },
|
|
128
|
+
softConflictInstruction: null,
|
|
129
|
+
recallInjectionStrategy: 'prepend_user_block',
|
|
130
|
+
conflictClarification: null,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
89
134
|
const runtimeConfig = getConfig();
|
|
90
135
|
const memoryEnabled = runtimeConfig.memory?.enabled !== false;
|
|
91
136
|
|