@vellumai/assistant 0.6.0 → 0.6.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/AGENTS.md +4 -0
- package/ARCHITECTURE.md +68 -15
- package/Dockerfile +2 -2
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +42 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/openapi.yaml +539 -4
- package/package.json +5 -1
- package/src/__tests__/anthropic-provider.test.ts +160 -95
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/checker.test.ts +138 -172
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-schema.test.ts +5 -0
- package/src/__tests__/context-overflow-approval.test.ts +5 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +4 -6
- package/src/__tests__/conversation-agent-loop.test.ts +4 -51
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-wipe.test.ts +2 -6
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +0 -2
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/injection-block.test.ts +24 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/install-skill-routing.test.ts +7 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +15 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +101 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +162 -0
- package/src/__tests__/log-export-workspace.test.ts +257 -100
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-recall-log-store.test.ts +132 -0
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/onboarding-template-contract.test.ts +63 -14
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/registry.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +0 -2
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sandbox-host-parity.test.ts +5 -4
- package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +4 -3
- package/src/__tests__/send-endpoint-busy.test.ts +42 -3
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +12 -0
- package/src/__tests__/skill-memory.test.ts +2 -783
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-memory-cleanup.test.ts +12 -12
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +16 -29
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +4 -27
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/transport-hints-queue.test.ts +77 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +116 -2
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/agent/loop.ts +6 -29
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/channels/types.ts +5 -0
- package/src/cli/__tests__/run-assistant-command.ts +56 -0
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +1 -34
- package/src/cli/commands/notifications.ts +7 -2
- package/src/cli/commands/oauth/__tests__/connect.test.ts +27 -0
- package/src/cli/commands/oauth/connect.ts +25 -5
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +130 -20
- package/src/cli/program.ts +11 -2
- package/src/cli.ts +1 -120
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +91 -5
- package/src/config/bundled-skills/gmail/SKILL.md +13 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/messaging/SKILL.md +7 -0
- package/src/config/bundled-skills/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/slack/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/env-registry.ts +63 -0
- package/src/config/feature-flag-registry.json +17 -1
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/security.ts +14 -0
- package/src/config/schemas/services.ts +8 -0
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +85 -3
- package/src/daemon/context-overflow-approval.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +20 -0
- package/src/daemon/conversation-agent-loop.ts +179 -65
- package/src/daemon/conversation-attachments.ts +0 -1
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +8 -14
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +30 -8
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +359 -308
- package/src/daemon/conversation-surfaces.ts +65 -0
- package/src/daemon/conversation-tool-setup.ts +44 -17
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +19 -3
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +5 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +70 -5
- package/src/daemon/handlers/skills.ts +11 -18
- package/src/daemon/lifecycle.ts +220 -158
- package/src/daemon/message-types/conversations.ts +29 -6
- package/src/daemon/message-types/messages.ts +9 -2
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +18 -0
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/server.ts +87 -10
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +23 -3
- package/src/daemon/transport-hints.ts +33 -0
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +96 -7
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +33 -32
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +1 -1
- package/src/memory/conversation-crud.ts +151 -117
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +66 -6
- package/src/memory/conversation-queries.ts +58 -12
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +182 -376
- package/src/memory/embedding-local.ts +1 -1
- package/src/memory/graph/bootstrap.ts +75 -66
- package/src/memory/graph/capability-seed.ts +167 -17
- package/src/memory/graph/consolidation.ts +38 -4
- package/src/memory/graph/conversation-graph-memory.ts +133 -104
- package/src/memory/graph/extraction-job.ts +9 -4
- package/src/memory/graph/extraction.ts +66 -23
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +29 -15
- package/src/memory/graph/injection.ts +38 -8
- package/src/memory/graph/inspect.ts +12 -3
- package/src/memory/graph/retriever.ts +365 -262
- package/src/memory/graph/store.test.ts +48 -0
- package/src/memory/graph/store.ts +150 -11
- package/src/memory/graph/tool-handlers.ts +84 -209
- package/src/memory/graph/tools.ts +8 -52
- package/src/memory/graph/types.ts +24 -0
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/job-handlers/cleanup.ts +44 -1
- package/src/memory/jobs-store.ts +70 -60
- package/src/memory/jobs-worker.ts +44 -28
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/migrations/203-drop-memory-items-tables.ts +33 -1
- package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +15 -0
- package/src/memory/task-memory-cleanup.ts +30 -11
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/copy-composer.ts +86 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/platform-connection.test.ts +2 -2
- package/src/oauth/seed-providers.ts +1 -0
- package/src/permissions/checker.ts +15 -4
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/prompter.ts +0 -2
- package/src/permissions/workspace-policy.ts +9 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +59 -7
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +76 -162
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +30 -9
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +107 -219
- package/src/runtime/assistant-event-hub.ts +22 -0
- package/src/runtime/auth/route-policy.ts +23 -0
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/http-server.ts +32 -2
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/btw-routes.ts +14 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +185 -0
- package/src/runtime/routes/conversation-management-routes.ts +1 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +270 -44
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +41 -278
- package/src/runtime/routes/memory-item-routes.test.ts +168 -233
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +27 -12
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +45 -18
- package/src/skills/catalog-install.ts +10 -2
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/skills/managed-store.ts +2 -2
- package/src/skills/skill-memory.ts +1 -293
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +4 -4
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/permission-checker.ts +78 -18
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/secret-detection-handler.ts +0 -1
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +16 -1
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +3 -5
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +2 -3
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +85 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -377
- package/src/__tests__/clipboard.test.ts +0 -88
- package/src/cli/cli-memory.ts +0 -179
- package/src/util/clipboard.ts +0 -34
|
@@ -81,6 +81,8 @@ export interface HistorySurface {
|
|
|
81
81
|
data: Record<string, unknown>;
|
|
82
82
|
actions?: Array<{ id: string; label: string; style?: string }>;
|
|
83
83
|
display?: string;
|
|
84
|
+
completed?: boolean;
|
|
85
|
+
completionSummary?: string;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
export interface RenderedHistoryContent {
|
|
@@ -281,6 +283,11 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
281
283
|
: {},
|
|
282
284
|
actions: Array.isArray(block.actions) ? block.actions : undefined,
|
|
283
285
|
display: typeof block.display === "string" ? block.display : undefined,
|
|
286
|
+
completed: block.completed === true ? true : undefined,
|
|
287
|
+
completionSummary:
|
|
288
|
+
typeof block.completionSummary === "string"
|
|
289
|
+
? block.completionSummary
|
|
290
|
+
: undefined,
|
|
284
291
|
};
|
|
285
292
|
surfaces.push(surface);
|
|
286
293
|
contentOrder.push(`surface:${surfaces.length - 1}`);
|
|
@@ -497,13 +504,71 @@ export function ensureSkillEntry(
|
|
|
497
504
|
return entries[name] as Record<string, unknown>;
|
|
498
505
|
}
|
|
499
506
|
|
|
500
|
-
/**
|
|
507
|
+
/**
|
|
508
|
+
* Parse a version string into its core numeric parts and optional pre-release tag.
|
|
509
|
+
* Handles optional `v`/`V` prefix (e.g. "v0.6.0-staging.5").
|
|
510
|
+
*/
|
|
511
|
+
function parseSemverParts(v: string): {
|
|
512
|
+
nums: [number, number, number];
|
|
513
|
+
pre: string | null;
|
|
514
|
+
} {
|
|
515
|
+
const stripped = v.replace(/^[vV]/, "");
|
|
516
|
+
const [core, ...rest] = stripped.split("-");
|
|
517
|
+
const pre = rest.length > 0 ? rest.join("-") : null;
|
|
518
|
+
const segs = (core ?? "").split(".").map(Number);
|
|
519
|
+
return {
|
|
520
|
+
nums: [segs[0] || 0, segs[1] || 0, segs[2] || 0],
|
|
521
|
+
pre,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Compare two pre-release strings per semver §11:
|
|
527
|
+
* - Dot-separated identifiers compared left to right.
|
|
528
|
+
* - Both numeric → compare as integers.
|
|
529
|
+
* - Both non-numeric → compare lexically.
|
|
530
|
+
* - Numeric vs non-numeric → numeric sorts lower (§11.4.4).
|
|
531
|
+
* - Fewer identifiers sorts earlier when all preceding are equal.
|
|
532
|
+
*/
|
|
533
|
+
function comparePreRelease(a: string, b: string): number {
|
|
534
|
+
const pa = a.split(".");
|
|
535
|
+
const pb = b.split(".");
|
|
536
|
+
const len = Math.max(pa.length, pb.length);
|
|
537
|
+
for (let i = 0; i < len; i++) {
|
|
538
|
+
if (i >= pa.length) return -1; // a has fewer fields → a < b
|
|
539
|
+
if (i >= pb.length) return 1;
|
|
540
|
+
const aIsNum = /^\d+$/.test(pa[i]);
|
|
541
|
+
const bIsNum = /^\d+$/.test(pb[i]);
|
|
542
|
+
if (aIsNum && bIsNum) {
|
|
543
|
+
const diff = Number(pa[i]) - Number(pb[i]);
|
|
544
|
+
if (diff !== 0) return diff;
|
|
545
|
+
} else if (aIsNum !== bIsNum) {
|
|
546
|
+
return aIsNum ? -1 : 1; // numeric < non-numeric per §11.4.4
|
|
547
|
+
} else {
|
|
548
|
+
const cmp = (pa[i] ?? "").localeCompare(pb[i] ?? "");
|
|
549
|
+
if (cmp !== 0) return cmp;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return 0;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Compare two semver strings. Returns negative if a < b, 0 if equal, positive if a > b.
|
|
557
|
+
*
|
|
558
|
+
* Handles pre-release suffixes per semver spec:
|
|
559
|
+
* - `0.6.0-staging.1 < 0.6.0` (pre-release < release)
|
|
560
|
+
* - `0.6.0-staging.1 < 0.6.0-staging.2` (numeric postfix comparison)
|
|
561
|
+
*/
|
|
501
562
|
export function compareSemver(a: string, b: string): number {
|
|
502
|
-
const pa = a
|
|
503
|
-
const pb = b
|
|
563
|
+
const pa = parseSemverParts(a);
|
|
564
|
+
const pb = parseSemverParts(b);
|
|
504
565
|
for (let i = 0; i < 3; i++) {
|
|
505
|
-
const diff =
|
|
566
|
+
const diff = pa.nums[i] - pb.nums[i];
|
|
506
567
|
if (diff !== 0) return diff;
|
|
507
568
|
}
|
|
508
|
-
|
|
569
|
+
// Same major.minor.patch — compare pre-release
|
|
570
|
+
if (pa.pre === null && pb.pre === null) return 0;
|
|
571
|
+
if (pa.pre !== null && pb.pre === null) return -1; // pre-release < release
|
|
572
|
+
if (pa.pre === null && pb.pre !== null) return 1;
|
|
573
|
+
return comparePreRelease(pa.pre!, pb.pre!);
|
|
509
574
|
}
|
|
@@ -20,6 +20,11 @@ import {
|
|
|
20
20
|
} from "../../config/loader.js";
|
|
21
21
|
import { resolveSkillStates, skillFlagKey } from "../../config/skill-state.js";
|
|
22
22
|
import { loadSkillCatalog, type SkillSummary } from "../../config/skills.js";
|
|
23
|
+
import {
|
|
24
|
+
deleteSkillCapabilityNode,
|
|
25
|
+
seedSkillGraphNodes,
|
|
26
|
+
seedUninstalledCatalogSkillMemories,
|
|
27
|
+
} from "../../memory/graph/capability-seed.js";
|
|
23
28
|
import {
|
|
24
29
|
createTimeout,
|
|
25
30
|
extractText,
|
|
@@ -51,11 +56,6 @@ import {
|
|
|
51
56
|
removeSkillsIndexEntry,
|
|
52
57
|
validateManagedSkillId,
|
|
53
58
|
} from "../../skills/managed-store.js";
|
|
54
|
-
import {
|
|
55
|
-
deleteSkillCapabilityMemory,
|
|
56
|
-
seedCatalogSkillMemories,
|
|
57
|
-
seedUninstalledCatalogSkillMemories,
|
|
58
|
-
} from "../../skills/skill-memory.js";
|
|
59
59
|
import {
|
|
60
60
|
installExternalSkill,
|
|
61
61
|
resolveSkillSource,
|
|
@@ -242,7 +242,7 @@ export function postInstallSkill(
|
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
// Seed skill memories
|
|
245
|
-
|
|
245
|
+
seedSkillGraphNodes();
|
|
246
246
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -603,7 +603,7 @@ export function enableSkill(
|
|
|
603
603
|
name: skillId,
|
|
604
604
|
state: "enabled",
|
|
605
605
|
});
|
|
606
|
-
|
|
606
|
+
seedSkillGraphNodes();
|
|
607
607
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
608
608
|
return { success: true };
|
|
609
609
|
} catch (err) {
|
|
@@ -626,7 +626,7 @@ export function disableSkill(
|
|
|
626
626
|
name: skillId,
|
|
627
627
|
state: "disabled",
|
|
628
628
|
});
|
|
629
|
-
|
|
629
|
+
seedSkillGraphNodes();
|
|
630
630
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
631
631
|
return { success: true };
|
|
632
632
|
} catch (err) {
|
|
@@ -719,7 +719,7 @@ export async function installSkill(
|
|
|
719
719
|
"Failed to auto-enable bundled skill",
|
|
720
720
|
);
|
|
721
721
|
}
|
|
722
|
-
|
|
722
|
+
seedSkillGraphNodes();
|
|
723
723
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
724
724
|
return { success: true };
|
|
725
725
|
}
|
|
@@ -847,14 +847,7 @@ export async function uninstallSkill(
|
|
|
847
847
|
}
|
|
848
848
|
// Best-effort cleanup of capability memory for uninstalled skill
|
|
849
849
|
// (managed path handles this internally via deleteManagedSkill)
|
|
850
|
-
|
|
851
|
-
try {
|
|
852
|
-
const { deleteSkillCapabilityNode } =
|
|
853
|
-
await import("../../memory/graph/capability-seed.js");
|
|
854
|
-
deleteSkillCapabilityNode(skillId);
|
|
855
|
-
} catch {
|
|
856
|
-
/* best effort */
|
|
857
|
-
}
|
|
850
|
+
deleteSkillCapabilityNode(skillId);
|
|
858
851
|
}
|
|
859
852
|
|
|
860
853
|
// Clean config entry
|
|
@@ -1255,7 +1248,7 @@ export async function createSkill(
|
|
|
1255
1248
|
);
|
|
1256
1249
|
}
|
|
1257
1250
|
|
|
1258
|
-
|
|
1251
|
+
seedSkillGraphNodes();
|
|
1259
1252
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
1260
1253
|
return { success: true };
|
|
1261
1254
|
} catch (err) {
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { reconcileCallsOnStartup } from "../calls/call-recovery.js";
|
|
|
5
5
|
import { setRelayBroadcast } from "../calls/relay-server.js";
|
|
6
6
|
import { TwilioConversationRelayProvider } from "../calls/twilio-provider.js";
|
|
7
7
|
import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
|
|
8
|
-
import {
|
|
8
|
+
import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
|
|
9
9
|
import {
|
|
10
10
|
getPlatformAssistantId,
|
|
11
11
|
getQdrantHttpPortEnv,
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
awaitCesClientWithTimeout,
|
|
33
33
|
DEFAULT_CES_STARTUP_TIMEOUT_MS,
|
|
34
34
|
} from "../credential-execution/startup-timeout.js";
|
|
35
|
+
import { FilingService } from "../filing/filing-service.js";
|
|
35
36
|
import { HeartbeatService } from "../heartbeat/heartbeat-service.js";
|
|
36
37
|
import { getHookManager } from "../hooks/manager.js";
|
|
37
38
|
import { installTemplates } from "../hooks/templates.js";
|
|
@@ -82,10 +83,6 @@ import {
|
|
|
82
83
|
setCesClient,
|
|
83
84
|
setCesReconnect,
|
|
84
85
|
} from "../security/secure-keys.js";
|
|
85
|
-
import {
|
|
86
|
-
seedCatalogSkillMemories,
|
|
87
|
-
seedUninstalledCatalogSkillMemories,
|
|
88
|
-
} from "../skills/skill-memory.js";
|
|
89
86
|
import { UsageTelemetryReporter } from "../telemetry/usage-telemetry-reporter.js";
|
|
90
87
|
import { getDeviceId } from "../util/device-id.js";
|
|
91
88
|
import { getLogger, initLogger } from "../util/logger.js";
|
|
@@ -127,6 +124,7 @@ import {
|
|
|
127
124
|
} from "./handlers/conversations.js";
|
|
128
125
|
import { installAssistantSymlink } from "./install-symlink.js";
|
|
129
126
|
import type { ServerMessage } from "./message-protocol.js";
|
|
127
|
+
import { runProfilerSweep } from "./profiler-run-store.js";
|
|
130
128
|
import {
|
|
131
129
|
initializeProvidersAndTools,
|
|
132
130
|
registerMessagingProviders,
|
|
@@ -272,6 +270,15 @@ export async function runDaemon(): Promise<void> {
|
|
|
272
270
|
const signingKey = resolveSigningKey();
|
|
273
271
|
initAuthSigningKey(signingKey);
|
|
274
272
|
|
|
273
|
+
// Pre-populate the feature flag cache from the gateway so all
|
|
274
|
+
// subsequent sync isAssistantFeatureFlagEnabled() calls have data.
|
|
275
|
+
// Fired non-blocking so a slow or unreachable gateway doesn't delay
|
|
276
|
+
// daemon startup (the fetch has a 10s timeout that would otherwise
|
|
277
|
+
// stall the critical path).
|
|
278
|
+
void initFeatureFlagOverrides().catch((err) =>
|
|
279
|
+
log.warn({ err }, "Background feature flag init failed"),
|
|
280
|
+
);
|
|
281
|
+
|
|
275
282
|
seedInterfaceFiles();
|
|
276
283
|
|
|
277
284
|
log.info("Daemon startup: installing templates and initializing DB");
|
|
@@ -282,151 +289,191 @@ export async function runDaemon(): Promise<void> {
|
|
|
282
289
|
// workspace migrations (e.g. 009-backfill-conversation-disk-view)
|
|
283
290
|
// depend on DB migrations having run (e.g. the inline-attachment-to-disk
|
|
284
291
|
// backfill that populates attachment filePaths).
|
|
285
|
-
initializeDb();
|
|
286
|
-
// Seed well-known OAuth provider configurations (insert-if-not-exists)
|
|
287
|
-
seedOAuthProviders();
|
|
288
|
-
log.info("Daemon startup: DB initialized");
|
|
289
|
-
|
|
290
|
-
await runWorkspaceMigrations(getWorkspaceDir(), WORKSPACE_MIGRATIONS);
|
|
291
|
-
log.info("Daemon startup: workspace migrations complete");
|
|
292
|
-
|
|
293
|
-
// Backfill oauth_connection rows for manual-token providers (Telegram,
|
|
294
|
-
// Slack channel) that already have stored credentials from before the
|
|
295
|
-
// oauth_connection migration. Safe to call on every startup.
|
|
296
292
|
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
293
|
+
// If DB initialization fails (e.g. a migration error), the daemon
|
|
294
|
+
// continues in a degraded state — DB-dependent features won't work but
|
|
295
|
+
// the HTTP server and config-based subsystems still start so the process
|
|
296
|
+
// remains reachable for health checks and diagnostics.
|
|
297
|
+
let dbReady = false;
|
|
300
298
|
try {
|
|
301
|
-
|
|
299
|
+
initializeDb();
|
|
300
|
+
dbReady = true;
|
|
301
|
+
log.info("Daemon startup: DB initialized");
|
|
302
302
|
} catch (err) {
|
|
303
|
-
log.
|
|
303
|
+
log.error(
|
|
304
304
|
{ err },
|
|
305
|
-
"
|
|
305
|
+
"DB initialization failed — continuing startup in degraded mode",
|
|
306
306
|
);
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
"
|
|
317
|
-
|
|
309
|
+
// Seed well-known OAuth provider configurations (insert-if-not-exists).
|
|
310
|
+
// Runs in its own try/catch so a seeding error doesn't force degraded mode
|
|
311
|
+
// when the DB itself initialized successfully.
|
|
312
|
+
if (dbReady) {
|
|
313
|
+
try {
|
|
314
|
+
seedOAuthProviders();
|
|
315
|
+
} catch (err) {
|
|
316
|
+
log.warn({ err }, "OAuth provider seeding failed — continuing startup");
|
|
317
|
+
}
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
setSentryDeviceId(getDeviceId());
|
|
320
|
+
if (dbReady) {
|
|
321
|
+
await runWorkspaceMigrations(getWorkspaceDir(), WORKSPACE_MIGRATIONS);
|
|
322
|
+
log.info("Daemon startup: workspace migrations complete");
|
|
324
323
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
324
|
+
// Profiler retention sweep — prune completed profiler runs to stay
|
|
325
|
+
// within configured byte-count, run-count, and free-space budgets.
|
|
326
|
+
// Runs on every startup and is safe to call from explicit cleanup routes.
|
|
327
|
+
try {
|
|
328
|
+
const sweepResult = runProfilerSweep();
|
|
329
|
+
if (sweepResult.prunedCount > 0 || sweepResult.activeRunOverBudget) {
|
|
330
|
+
log.info(
|
|
331
|
+
{
|
|
332
|
+
prunedCount: sweepResult.prunedCount,
|
|
333
|
+
freedBytes: sweepResult.freedBytes,
|
|
334
|
+
activeRunOverBudget: sweepResult.activeRunOverBudget,
|
|
335
|
+
remainingRuns: sweepResult.remainingRuns,
|
|
336
|
+
},
|
|
337
|
+
"Profiler retention sweep completed on startup",
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
} catch (err) {
|
|
341
|
+
log.warn(
|
|
342
|
+
{ err },
|
|
343
|
+
"Profiler retention sweep failed — continuing startup",
|
|
344
|
+
);
|
|
340
345
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
+
|
|
347
|
+
// Backfill oauth_connection rows for manual-token providers (Telegram,
|
|
348
|
+
// Slack channel) that already have stored credentials from before the
|
|
349
|
+
// oauth_connection migration. Safe to call on every startup.
|
|
350
|
+
//
|
|
351
|
+
// Must run AFTER workspace migrations.
|
|
352
|
+
// Otherwise syncManualTokenConnection sees no stored credentials and
|
|
353
|
+
// incorrectly removes existing connection rows.
|
|
354
|
+
try {
|
|
355
|
+
await backfillManualTokenConnections();
|
|
356
|
+
} catch (err) {
|
|
357
|
+
log.warn(
|
|
358
|
+
{ err },
|
|
359
|
+
"Manual-token connection backfill failed — continuing startup",
|
|
360
|
+
);
|
|
346
361
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
362
|
+
|
|
363
|
+
// Backfill injection templates on Slack bot token credentials so the
|
|
364
|
+
// credential proxy can inject Authorization headers. Safe on every startup.
|
|
365
|
+
try {
|
|
366
|
+
backfillSlackInjectionTemplates();
|
|
367
|
+
} catch (err) {
|
|
368
|
+
log.warn(
|
|
369
|
+
{ err },
|
|
370
|
+
"Slack injection template backfill failed — continuing startup",
|
|
371
|
+
);
|
|
352
372
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
)
|
|
373
|
+
|
|
374
|
+
// Now that workspace migrations have run (including 003-seed-device-id
|
|
375
|
+
// which may copy the legacy installationId into device.json), it is safe
|
|
376
|
+
// to read the device ID and set the Sentry tag.
|
|
377
|
+
setSentryDeviceId(getDeviceId());
|
|
378
|
+
|
|
379
|
+
// Purge private (temporary) conversations from the previous daemon run.
|
|
380
|
+
// These are ephemeral by design and should not survive daemon restarts.
|
|
381
|
+
const { count: purgedCount, deletedMemory } = purgePrivateConversations();
|
|
382
|
+
if (purgedCount > 0) {
|
|
358
383
|
log.info(
|
|
359
|
-
{
|
|
360
|
-
|
|
361
|
-
orphanedItems: deletedMemory.orphanedItemIds.length,
|
|
362
|
-
deletedSummaries: deletedMemory.deletedSummaryIds.length,
|
|
363
|
-
},
|
|
364
|
-
"Enqueued Qdrant vector cleanup jobs for purged private conversations",
|
|
384
|
+
{ purgedCount },
|
|
385
|
+
`Purged ${purgedCount} private conversation(s) from previous daemon run`,
|
|
365
386
|
);
|
|
387
|
+
// Qdrant may not be ready at startup, so enqueue vector cleanup jobs
|
|
388
|
+
// rather than attempting direct deletion.
|
|
389
|
+
for (const segId of deletedMemory.segmentIds) {
|
|
390
|
+
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
391
|
+
targetType: "segment",
|
|
392
|
+
targetId: segId,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
for (const summaryId of deletedMemory.deletedSummaryIds) {
|
|
396
|
+
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
397
|
+
targetType: "summary",
|
|
398
|
+
targetId: summaryId,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
if (
|
|
402
|
+
deletedMemory.segmentIds.length > 0 ||
|
|
403
|
+
deletedMemory.deletedSummaryIds.length > 0
|
|
404
|
+
) {
|
|
405
|
+
log.info(
|
|
406
|
+
{
|
|
407
|
+
segments: deletedMemory.segmentIds.length,
|
|
408
|
+
deletedSummaries: deletedMemory.deletedSummaryIds.length,
|
|
409
|
+
},
|
|
410
|
+
"Enqueued Qdrant vector cleanup jobs for purged private conversations",
|
|
411
|
+
);
|
|
412
|
+
}
|
|
366
413
|
}
|
|
367
|
-
}
|
|
368
414
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
415
|
+
// Expire stale pending canonical guardian requests left over from before
|
|
416
|
+
// this process started. Two categories are cleaned up:
|
|
417
|
+
//
|
|
418
|
+
// 1. Interaction-bound kinds (tool_approval, pending_question) — their
|
|
419
|
+
// in-memory pending-interaction session references are gone, so they
|
|
420
|
+
// can never be completed.
|
|
421
|
+
// 2. Any pending request whose expiresAt has already passed — persistent
|
|
422
|
+
// kinds (access_request, tool_grant_request) that expired while the
|
|
423
|
+
// daemon was stopped are transitioned so dedup logic doesn't return
|
|
424
|
+
// stale rows.
|
|
425
|
+
const expiredCount = expireAllPendingCanonicalRequests();
|
|
426
|
+
if (expiredCount > 0) {
|
|
427
|
+
log.info(
|
|
428
|
+
{ event: "startup_expired_stale_requests", expiredCount },
|
|
429
|
+
`Expired ${expiredCount} stale canonical request(s) from previous process`,
|
|
430
|
+
);
|
|
431
|
+
}
|
|
386
432
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
433
|
+
// Ensure a vellum guardian binding exists so the identity system works
|
|
434
|
+
// without requiring a manual bootstrap step.
|
|
435
|
+
try {
|
|
436
|
+
ensureVellumGuardianBinding(DAEMON_INTERNAL_ASSISTANT_ID);
|
|
437
|
+
} catch (err) {
|
|
438
|
+
log.warn(
|
|
439
|
+
{ err },
|
|
440
|
+
"Vellum guardian binding backfill failed — continuing startup",
|
|
441
|
+
);
|
|
442
|
+
}
|
|
397
443
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
444
|
+
try {
|
|
445
|
+
syncUpdateBulletinOnStartup();
|
|
446
|
+
} catch (err) {
|
|
447
|
+
log.warn({ err }, "Bulletin sync failed — continuing startup");
|
|
448
|
+
}
|
|
403
449
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
450
|
+
// Recover orphaned work items that were left in 'running' state when the
|
|
451
|
+
// daemon previously crashed or was killed mid-task.
|
|
452
|
+
const orphanedRunning = listWorkItems({ status: "running" });
|
|
453
|
+
if (orphanedRunning.length > 0) {
|
|
454
|
+
for (const item of orphanedRunning) {
|
|
455
|
+
updateWorkItem(item.id, {
|
|
456
|
+
status: "failed",
|
|
457
|
+
lastRunStatus: "interrupted",
|
|
458
|
+
});
|
|
459
|
+
log.info(
|
|
460
|
+
{ workItemId: item.id, title: item.title },
|
|
461
|
+
"Recovered orphaned running work item → failed (interrupted)",
|
|
462
|
+
);
|
|
463
|
+
}
|
|
413
464
|
log.info(
|
|
414
|
-
{
|
|
415
|
-
"Recovered orphaned running work
|
|
465
|
+
{ count: orphanedRunning.length },
|
|
466
|
+
"Recovered orphaned running work items",
|
|
416
467
|
);
|
|
417
468
|
}
|
|
418
|
-
log.info(
|
|
419
|
-
{ count: orphanedRunning.length },
|
|
420
|
-
"Recovered orphaned running work items",
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
469
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
470
|
+
try {
|
|
471
|
+
const twilioProvider = new TwilioConversationRelayProvider();
|
|
472
|
+
await reconcileCallsOnStartup(twilioProvider, log);
|
|
473
|
+
} catch (err) {
|
|
474
|
+
log.warn({ err }, "Call recovery failed — continuing startup");
|
|
475
|
+
}
|
|
476
|
+
} // end if (dbReady)
|
|
430
477
|
|
|
431
478
|
// Merge CLI-provided default config (from VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH)
|
|
432
479
|
// into the workspace config file before the first loadConfig() call so
|
|
@@ -645,35 +692,21 @@ export async function runDaemon(): Promise<void> {
|
|
|
645
692
|
log.info("Daemon startup: starting memory worker");
|
|
646
693
|
bgRefs.memoryWorker = startMemoryJobsWorker();
|
|
647
694
|
|
|
648
|
-
// Seed capability memories for all enabled skills so the memory
|
|
649
|
-
// pipeline can surface relevant skills via semantic search.
|
|
650
|
-
try {
|
|
651
|
-
seedCatalogSkillMemories();
|
|
652
|
-
} catch (err) {
|
|
653
|
-
log.warn({ err }, "Catalog skill memory seeding failed — continuing");
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
// Seed memories for catalog skills not yet installed so they're
|
|
657
|
-
// discoverable via memory injection and can be auto-installed.
|
|
658
|
-
void seedUninstalledCatalogSkillMemories().catch((err) =>
|
|
659
|
-
log.warn(
|
|
660
|
-
{ err },
|
|
661
|
-
"Uninstalled catalog skill memory seeding failed — continuing",
|
|
662
|
-
),
|
|
663
|
-
);
|
|
664
|
-
|
|
665
|
-
try {
|
|
666
|
-
seedCliCommandMemories();
|
|
667
|
-
} catch (err) {
|
|
668
|
-
log.warn({ err }, "CLI command memory seeding failed — continuing");
|
|
669
|
-
}
|
|
670
|
-
|
|
671
695
|
// Seed capability graph nodes (new memory graph system)
|
|
672
696
|
try {
|
|
673
|
-
const {
|
|
674
|
-
|
|
697
|
+
const {
|
|
698
|
+
seedSkillGraphNodes,
|
|
699
|
+
seedCliGraphNodes,
|
|
700
|
+
seedUninstalledCatalogSkillMemories,
|
|
701
|
+
} = await import("../memory/graph/capability-seed.js");
|
|
675
702
|
seedSkillGraphNodes();
|
|
676
|
-
seedCliGraphNodes();
|
|
703
|
+
await seedCliGraphNodes();
|
|
704
|
+
void seedUninstalledCatalogSkillMemories().catch((err) =>
|
|
705
|
+
log.warn(
|
|
706
|
+
{ err },
|
|
707
|
+
"Uninstalled catalog skill memory seeding failed — continuing",
|
|
708
|
+
),
|
|
709
|
+
);
|
|
677
710
|
} catch (err) {
|
|
678
711
|
log.warn({ err }, "Graph capability seeding failed — continuing");
|
|
679
712
|
}
|
|
@@ -682,10 +715,8 @@ export async function runDaemon(): Promise<void> {
|
|
|
682
715
|
// segments exist, enqueue a one-time graph_bootstrap job to populate the
|
|
683
716
|
// graph from conversation history and journal files.
|
|
684
717
|
try {
|
|
685
|
-
const {
|
|
686
|
-
|
|
687
|
-
cleanupStaleItemVectors,
|
|
688
|
-
} = await import("../memory/graph/bootstrap.js");
|
|
718
|
+
const { maybeEnqueueGraphBootstrap, cleanupStaleItemVectors } =
|
|
719
|
+
await import("../memory/graph/bootstrap.js");
|
|
689
720
|
maybeEnqueueGraphBootstrap();
|
|
690
721
|
// Fire-and-forget: clean up orphaned Qdrant vectors from dropped memory_items table
|
|
691
722
|
void cleanupStaleItemVectors().catch((err) =>
|
|
@@ -742,6 +773,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
742
773
|
},
|
|
743
774
|
routingIntent: schedule.routingIntent,
|
|
744
775
|
routingHints: schedule.routingHints,
|
|
776
|
+
conversationMetadata: {
|
|
777
|
+
groupId: "system:scheduled",
|
|
778
|
+
scheduleJobId: schedule.id,
|
|
779
|
+
source: "schedule",
|
|
780
|
+
},
|
|
745
781
|
dedupeKey: `schedule:notify:${schedule.id}:${Date.now()}`,
|
|
746
782
|
throwOnError: true,
|
|
747
783
|
});
|
|
@@ -761,6 +797,11 @@ export async function runDaemon(): Promise<void> {
|
|
|
761
797
|
scheduleId: schedule.id,
|
|
762
798
|
name: schedule.name,
|
|
763
799
|
},
|
|
800
|
+
conversationMetadata: {
|
|
801
|
+
groupId: "system:scheduled",
|
|
802
|
+
scheduleJobId: schedule.id,
|
|
803
|
+
source: "schedule",
|
|
804
|
+
},
|
|
764
805
|
dedupeKey: `schedule:complete:${schedule.id}:${Date.now()}`,
|
|
765
806
|
});
|
|
766
807
|
},
|
|
@@ -849,8 +890,8 @@ export async function runDaemon(): Promise<void> {
|
|
|
849
890
|
guardianFollowUpConversationGenerator:
|
|
850
891
|
createGuardianFollowUpConversationGenerator(),
|
|
851
892
|
sendMessageDeps: {
|
|
852
|
-
getOrCreateConversation: (conversationId) =>
|
|
853
|
-
server.getConversationForMessages(conversationId),
|
|
893
|
+
getOrCreateConversation: (conversationId, options) =>
|
|
894
|
+
server.getConversationForMessages(conversationId, options),
|
|
854
895
|
assistantEventHub,
|
|
855
896
|
resolveAttachments: (attachmentIds) => {
|
|
856
897
|
const resolved = attachmentsStore.getAttachmentsByIds(attachmentIds, {
|
|
@@ -1226,6 +1267,26 @@ export async function runDaemon(): Promise<void> {
|
|
|
1226
1267
|
"Heartbeat service configured",
|
|
1227
1268
|
);
|
|
1228
1269
|
|
|
1270
|
+
const filingConfig = config.filing;
|
|
1271
|
+
const filing = new FilingService({
|
|
1272
|
+
processMessage: (conversationId, content, options) =>
|
|
1273
|
+
server.processMessage(conversationId, content, undefined, {
|
|
1274
|
+
trustContext: {
|
|
1275
|
+
sourceChannel: "vellum",
|
|
1276
|
+
trustClass: "guardian",
|
|
1277
|
+
},
|
|
1278
|
+
...options,
|
|
1279
|
+
}),
|
|
1280
|
+
});
|
|
1281
|
+
filing.start();
|
|
1282
|
+
log.info(
|
|
1283
|
+
{
|
|
1284
|
+
enabled: filingConfig.enabled,
|
|
1285
|
+
intervalMs: filingConfig.intervalMs,
|
|
1286
|
+
},
|
|
1287
|
+
"Filing service configured",
|
|
1288
|
+
);
|
|
1289
|
+
|
|
1229
1290
|
// Retrieve the MCP manager if MCP servers were configured.
|
|
1230
1291
|
// The manager is a singleton created during initializeProvidersAndTools().
|
|
1231
1292
|
const mcpManager =
|
|
@@ -1237,6 +1298,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
1237
1298
|
server,
|
|
1238
1299
|
workspaceHeartbeat,
|
|
1239
1300
|
heartbeat,
|
|
1301
|
+
filing,
|
|
1240
1302
|
hookManager,
|
|
1241
1303
|
runtimeHttp,
|
|
1242
1304
|
scheduler,
|