@vellumai/assistant 0.7.2 → 0.7.3
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 +16 -1
- package/docs/architecture/memory.md +5 -2
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
- package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- package/openapi.yaml +449 -22
- package/package.json +1 -1
- package/src/__tests__/app-control-flow.test.ts +21 -11
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/assistant-event.test.ts +0 -10
- package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
- package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/call-conversation-messages.test.ts +8 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +4 -2
- package/src/__tests__/config-loader-backfill.test.ts +379 -0
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
- package/src/__tests__/config-watcher.test.ts +140 -69
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credentials-cli.test.ts +7 -0
- package/src/__tests__/cu-unified-flow.test.ts +176 -10
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +260 -11
- package/src/__tests__/host-app-control-proxy.test.ts +195 -25
- package/src/__tests__/host-bash-proxy.test.ts +227 -34
- package/src/__tests__/host-bash-routes.test.ts +178 -13
- package/src/__tests__/host-cu-proxy.test.ts +210 -3
- package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
- package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
- package/src/__tests__/host-file-proxy.test.ts +268 -6
- package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
- package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
- package/src/__tests__/http-user-message-parity.test.ts +107 -1
- package/src/__tests__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/managed-profile-guard.test.ts +18 -0
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
- package/src/__tests__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- package/src/__tests__/runtime-events-sse.test.ts +4 -8
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -1
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/twilio-validation.test.ts +2 -2
- package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/contacts.ts +64 -25
- package/src/cli/commands/credentials.ts +56 -0
- package/src/cli/commands/memory-v2.ts +7 -6
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
- package/src/cli/commands/platform/index.ts +16 -7
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/program.ts +4 -2
- package/src/config/assistant-feature-flags.ts +13 -3
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- package/src/config/env.ts +0 -8
- package/src/config/feature-flag-registry.json +27 -3
- package/src/config/loader.ts +127 -8
- package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +13 -0
- package/src/config/schemas/memory-v2.ts +75 -11
- package/src/config/schemas/platform.ts +43 -3
- package/src/config/schemas/services.ts +28 -0
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -25
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/config-watcher.ts +85 -57
- package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
- package/src/daemon/conversation-agent-loop.ts +170 -33
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +1 -3
- package/src/daemon/conversation-process.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +26 -0
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +195 -15
- package/src/daemon/conversation-tool-setup.ts +57 -14
- package/src/daemon/conversation.ts +17 -22
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/handlers/shared.ts +0 -1
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +137 -41
- package/src/daemon/host-bash-proxy.ts +46 -21
- package/src/daemon/host-cu-proxy.ts +49 -3
- package/src/daemon/host-file-proxy.ts +43 -7
- package/src/daemon/host-transfer-proxy.ts +95 -4
- package/src/daemon/lifecycle.ts +79 -28
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +4 -0
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/tool-setup-types.ts +2 -2
- package/src/documents/document-store.ts +85 -0
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
- package/src/heartbeat/heartbeat-run-store.ts +13 -0
- package/src/heartbeat/heartbeat-service.ts +205 -31
- package/src/home/feed-scheduler.ts +18 -0
- package/src/inbound/platform-callback-registration.ts +8 -15
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/assistant-server.ts +56 -2
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/protocol.ts +5 -7
- package/src/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
- package/src/memory/admin.ts +5 -9
- package/src/memory/context-search/agent-runner.ts +19 -2
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +5 -4
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +4 -12
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +32 -21
- package/src/memory/graph/conversation-graph-memory.ts +42 -54
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +1 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +6 -10
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- package/src/memory/jobs-store.ts +48 -0
- package/src/memory/jobs-worker.ts +81 -43
- package/src/memory/memory-v2-activation-log-store.ts +32 -14
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/qdrant-client.ts +0 -13
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/search/semantic.ts +6 -67
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +311 -250
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +157 -167
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +5 -199
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/static-context.test.ts +76 -1
- package/src/memory/v2/activation.ts +149 -156
- package/src/memory/v2/consolidation-job.ts +62 -12
- package/src/memory/v2/injection.ts +47 -60
- package/src/memory/v2/prompts/consolidation.ts +36 -1
- package/src/memory/v2/qdrant.ts +99 -0
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +10 -84
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +82 -59
- package/src/memory/v2/static-context.ts +22 -0
- package/src/memory/v2/types.ts +10 -10
- package/src/notifications/copy-composer.ts +13 -0
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- package/src/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +21 -7
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +36 -6
- package/src/runtime/assistant-event.ts +0 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/pending-interactions.ts +8 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/client-routes.ts +20 -2
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-routes.ts +35 -26
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +6 -2
- package/src/runtime/routes/documents-routes.ts +2 -75
- package/src/runtime/routes/events-routes.ts +41 -9
- package/src/runtime/routes/host-bash-routes.ts +23 -3
- package/src/runtime/routes/host-cu-routes.ts +33 -6
- package/src/runtime/routes/host-file-routes.ts +32 -6
- package/src/runtime/routes/host-transfer-routes.ts +79 -16
- package/src/runtime/routes/identity-routes.ts +7 -138
- package/src/runtime/routes/inbound-message-handler.ts +77 -12
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-v2-routes.ts +33 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- package/src/schedule/run-script.ts +37 -5
- package/src/schedule/scheduler.ts +20 -1
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/secure-keys.ts +55 -0
- package/src/skills/remote-skill-policy.ts +4 -10
- package/src/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- package/src/tools/background-tool-registry.ts +17 -3
- package/src/tools/host-filesystem/edit.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +43 -1
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +43 -1
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +56 -11
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +43 -1
- package/src/tools/host-terminal/host-shell.ts +13 -6
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +31 -6
- package/src/tools/types.ts +24 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/heartbeat-service.ts +19 -0
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -404
- package/src/signals/bash.ts +0 -198
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
assistantEventHub,
|
|
10
10
|
broadcastMessage,
|
|
11
11
|
} from "../runtime/assistant-event-hub.js";
|
|
12
|
+
import {
|
|
13
|
+
ambiguousSameUserError,
|
|
14
|
+
enforceSameActorOrErrorResult,
|
|
15
|
+
pickSameUserAutoResolve,
|
|
16
|
+
} from "../runtime/auth/same-actor.js";
|
|
12
17
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
13
18
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
14
19
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
@@ -31,6 +36,13 @@ interface TransferEntry {
|
|
|
31
36
|
sha256?: string;
|
|
32
37
|
fileBuffer?: Buffer;
|
|
33
38
|
targetClientId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Snapshot of `targetClientId`'s `actorPrincipalId` taken at registration
|
|
41
|
+
* time. Persisted so the GET/PUT content routes compare against a stable
|
|
42
|
+
* value rather than the live hub — the target client's SSE subscription
|
|
43
|
+
* may briefly disconnect between dispatch and content fetch/upload.
|
|
44
|
+
*/
|
|
45
|
+
targetActorPrincipalId?: string;
|
|
34
46
|
}
|
|
35
47
|
|
|
36
48
|
/**
|
|
@@ -124,6 +136,8 @@ export class HostTransferProxy {
|
|
|
124
136
|
targetClientId?: string;
|
|
125
137
|
},
|
|
126
138
|
signal?: AbortSignal,
|
|
139
|
+
// Principal ID of the actor on whose behalf this request is initiated.
|
|
140
|
+
sourceActorPrincipalId?: string,
|
|
127
141
|
): Promise<ToolExecutionResult> {
|
|
128
142
|
if (signal?.aborted) {
|
|
129
143
|
return Promise.resolve({ content: "Aborted", isError: true });
|
|
@@ -145,8 +159,29 @@ export class HostTransferProxy {
|
|
|
145
159
|
});
|
|
146
160
|
}
|
|
147
161
|
} else {
|
|
148
|
-
|
|
149
|
-
|
|
162
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
163
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
164
|
+
// fan out across the user's machines.
|
|
165
|
+
const resolved = pickSameUserAutoResolve({
|
|
166
|
+
hub: assistantEventHub,
|
|
167
|
+
capability: "host_file",
|
|
168
|
+
sourceActorPrincipalId,
|
|
169
|
+
});
|
|
170
|
+
if (resolved.kind === "ambiguous") {
|
|
171
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
172
|
+
}
|
|
173
|
+
resolvedTargetClientId =
|
|
174
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (resolvedTargetClientId != null) {
|
|
178
|
+
const rejection = enforceSameActorOrErrorResult({
|
|
179
|
+
hub: assistantEventHub,
|
|
180
|
+
sourceActorPrincipalId,
|
|
181
|
+
targetClientId: resolvedTargetClientId,
|
|
182
|
+
op: "host_transfer",
|
|
183
|
+
});
|
|
184
|
+
if (rejection != null) return Promise.resolve(rejection);
|
|
150
185
|
}
|
|
151
186
|
|
|
152
187
|
const requestId = uuid();
|
|
@@ -220,12 +255,24 @@ export class HostTransferProxy {
|
|
|
220
255
|
sha256,
|
|
221
256
|
fileBuffer,
|
|
222
257
|
targetClientId: resolvedTargetClientId,
|
|
258
|
+
targetActorPrincipalId:
|
|
259
|
+
resolvedTargetClientId != null
|
|
260
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
261
|
+
resolvedTargetClientId,
|
|
262
|
+
)
|
|
263
|
+
: undefined,
|
|
223
264
|
});
|
|
224
265
|
|
|
225
266
|
pendingInteractions.register(requestId, {
|
|
226
267
|
conversationId: input.conversationId,
|
|
227
268
|
kind: "host_transfer",
|
|
228
269
|
targetClientId: resolvedTargetClientId,
|
|
270
|
+
targetActorPrincipalId:
|
|
271
|
+
resolvedTargetClientId != null
|
|
272
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
273
|
+
resolvedTargetClientId,
|
|
274
|
+
)
|
|
275
|
+
: undefined,
|
|
229
276
|
rpcResolve: resolve,
|
|
230
277
|
rpcReject: reject,
|
|
231
278
|
timer,
|
|
@@ -291,6 +338,8 @@ export class HostTransferProxy {
|
|
|
291
338
|
targetClientId?: string;
|
|
292
339
|
},
|
|
293
340
|
signal?: AbortSignal,
|
|
341
|
+
// Principal ID of the actor on whose behalf this request is initiated.
|
|
342
|
+
sourceActorPrincipalId?: string,
|
|
294
343
|
): Promise<ToolExecutionResult> {
|
|
295
344
|
if (signal?.aborted) {
|
|
296
345
|
return Promise.resolve({ content: "Aborted", isError: true });
|
|
@@ -312,8 +361,29 @@ export class HostTransferProxy {
|
|
|
312
361
|
});
|
|
313
362
|
}
|
|
314
363
|
} else {
|
|
315
|
-
|
|
316
|
-
|
|
364
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
365
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
366
|
+
// fan out across the user's machines.
|
|
367
|
+
const resolved = pickSameUserAutoResolve({
|
|
368
|
+
hub: assistantEventHub,
|
|
369
|
+
capability: "host_file",
|
|
370
|
+
sourceActorPrincipalId,
|
|
371
|
+
});
|
|
372
|
+
if (resolved.kind === "ambiguous") {
|
|
373
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
374
|
+
}
|
|
375
|
+
resolvedTargetClientId =
|
|
376
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (resolvedTargetClientId != null) {
|
|
380
|
+
const rejection = enforceSameActorOrErrorResult({
|
|
381
|
+
hub: assistantEventHub,
|
|
382
|
+
sourceActorPrincipalId,
|
|
383
|
+
targetClientId: resolvedTargetClientId,
|
|
384
|
+
op: "host_transfer",
|
|
385
|
+
});
|
|
386
|
+
if (rejection != null) return Promise.resolve(rejection);
|
|
317
387
|
}
|
|
318
388
|
|
|
319
389
|
const requestId = uuid();
|
|
@@ -374,12 +444,24 @@ export class HostTransferProxy {
|
|
|
374
444
|
filePath: input.destPath,
|
|
375
445
|
overwrite: input.overwrite,
|
|
376
446
|
targetClientId: resolvedTargetClientId,
|
|
447
|
+
targetActorPrincipalId:
|
|
448
|
+
resolvedTargetClientId != null
|
|
449
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
450
|
+
resolvedTargetClientId,
|
|
451
|
+
)
|
|
452
|
+
: undefined,
|
|
377
453
|
});
|
|
378
454
|
|
|
379
455
|
pendingInteractions.register(requestId, {
|
|
380
456
|
conversationId: input.conversationId,
|
|
381
457
|
kind: "host_transfer",
|
|
382
458
|
targetClientId: resolvedTargetClientId,
|
|
459
|
+
targetActorPrincipalId:
|
|
460
|
+
resolvedTargetClientId != null
|
|
461
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
462
|
+
resolvedTargetClientId,
|
|
463
|
+
)
|
|
464
|
+
: undefined,
|
|
383
465
|
rpcResolve: resolve,
|
|
384
466
|
rpcReject: reject,
|
|
385
467
|
timer,
|
|
@@ -623,6 +705,15 @@ export class HostTransferProxy {
|
|
|
623
705
|
return this.transfers.get(transferId)?.targetClientId ?? null;
|
|
624
706
|
}
|
|
625
707
|
|
|
708
|
+
/**
|
|
709
|
+
* Look up the persisted `targetActorPrincipalId` for a given transferId
|
|
710
|
+
* without consuming the entry. Routes call this for the same-actor
|
|
711
|
+
* binding check so it's stable across brief SSE reconnects.
|
|
712
|
+
*/
|
|
713
|
+
getTargetActorPrincipalIdForTransfer(transferId: string): string | undefined {
|
|
714
|
+
return this.transfers.get(transferId)?.targetActorPrincipalId;
|
|
715
|
+
}
|
|
716
|
+
|
|
626
717
|
dispose(): void {
|
|
627
718
|
for (const entry of pendingInteractions.getByKind("host_transfer")) {
|
|
628
719
|
const transferId = entry.metadata?.transferId as string | undefined;
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -54,7 +54,6 @@ import { startMemoryJobsWorker } from "../memory/jobs-worker.js";
|
|
|
54
54
|
import { initQdrantClient, resolveQdrantUrl } from "../memory/qdrant-client.js";
|
|
55
55
|
import { QdrantManager } from "../memory/qdrant-manager.js";
|
|
56
56
|
import { rotateToolInvocations } from "../memory/tool-usage-store.js";
|
|
57
|
-
import { deleteOldTraceEvents } from "../memory/trace-event-store.js";
|
|
58
57
|
import {
|
|
59
58
|
emitNotificationSignal,
|
|
60
59
|
registerBroadcastFn,
|
|
@@ -62,6 +61,7 @@ import {
|
|
|
62
61
|
import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
|
|
63
62
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
64
63
|
import { loadUserPlugins } from "../plugins/user-loader.js";
|
|
64
|
+
import { backfillGuardIfNeeded } from "../proactive-artifact/index.js";
|
|
65
65
|
import { ensurePromptFiles } from "../prompts/system-prompt.js";
|
|
66
66
|
import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
|
|
67
67
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
@@ -105,6 +105,11 @@ import {
|
|
|
105
105
|
cleanupPidFileIfOwner,
|
|
106
106
|
writePid,
|
|
107
107
|
} from "./daemon-control.js";
|
|
108
|
+
import {
|
|
109
|
+
evaluateDiskPressureNow,
|
|
110
|
+
startDiskPressureGuard,
|
|
111
|
+
stopDiskPressureGuard,
|
|
112
|
+
} from "./disk-pressure-guard.js";
|
|
108
113
|
import { bootstrapPlugins } from "./external-plugins-bootstrap.js";
|
|
109
114
|
import {
|
|
110
115
|
createGuardianActionCopyGenerator,
|
|
@@ -125,11 +130,57 @@ import { DaemonServer } from "./server.js";
|
|
|
125
130
|
import { installShutdownHandlers } from "./shutdown-handlers.js";
|
|
126
131
|
|
|
127
132
|
const log = getLogger("lifecycle");
|
|
133
|
+
let diskPressureStartupSampleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
128
134
|
|
|
129
135
|
function loadDotEnv(): void {
|
|
130
136
|
dotenvConfig({ path: getDotEnvPath(), quiet: true });
|
|
131
137
|
}
|
|
132
138
|
|
|
139
|
+
function runDeferredDiskPressureStartupSample(): void {
|
|
140
|
+
diskPressureStartupSampleTimer = null;
|
|
141
|
+
try {
|
|
142
|
+
const status = evaluateDiskPressureNow();
|
|
143
|
+
if (status.error) {
|
|
144
|
+
log.warn(
|
|
145
|
+
{ error: status.error },
|
|
146
|
+
"Disk pressure guard sample failed during startup — continuing unlocked",
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
} catch (err) {
|
|
150
|
+
log.warn(
|
|
151
|
+
{ err },
|
|
152
|
+
"Disk pressure guard failed during startup — continuing unlocked",
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function startDiskPressureGuardForLifecycle(): void {
|
|
158
|
+
try {
|
|
159
|
+
const startedStatus = startDiskPressureGuard();
|
|
160
|
+
if (!startedStatus.enabled) return;
|
|
161
|
+
if (!diskPressureStartupSampleTimer) {
|
|
162
|
+
diskPressureStartupSampleTimer = setTimeout(
|
|
163
|
+
runDeferredDiskPressureStartupSample,
|
|
164
|
+
0,
|
|
165
|
+
);
|
|
166
|
+
(diskPressureStartupSampleTimer as { unref?: () => void }).unref?.();
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
log.warn(
|
|
170
|
+
{ err },
|
|
171
|
+
"Disk pressure guard failed during startup — continuing unlocked",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function stopDiskPressureGuardForLifecycle(): void {
|
|
177
|
+
if (diskPressureStartupSampleTimer) {
|
|
178
|
+
clearTimeout(diskPressureStartupSampleTimer);
|
|
179
|
+
diskPressureStartupSampleTimer = null;
|
|
180
|
+
}
|
|
181
|
+
stopDiskPressureGuard();
|
|
182
|
+
}
|
|
183
|
+
|
|
133
184
|
export interface CesStartupResult {
|
|
134
185
|
client: CesClient | undefined;
|
|
135
186
|
processManager: CesProcessManager | undefined;
|
|
@@ -448,12 +499,22 @@ export async function runDaemon(): Promise<void> {
|
|
|
448
499
|
}
|
|
449
500
|
} // end if (dbReady)
|
|
450
501
|
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
//
|
|
502
|
+
// Merge CLI-provided default config (from VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH)
|
|
503
|
+
// into the workspace config file before profile seeding and the first
|
|
504
|
+
// loadConfig() call so onboarding/platform preferences are visible to the
|
|
505
|
+
// seeder and persisted alongside schema defaults.
|
|
506
|
+
const defaultConfigMerge = mergeDefaultWorkspaceConfig();
|
|
507
|
+
|
|
508
|
+
// Seed managed inference profiles into the workspace config. Runs after
|
|
509
|
+
// workspace migrations and default-config merge, but before loadConfig() so
|
|
510
|
+
// fresh hatches have profiles on disk before the first config load. Any
|
|
511
|
+
// profile fields explicitly supplied by the default overlay stay
|
|
512
|
+
// authoritative for this startup.
|
|
455
513
|
try {
|
|
456
|
-
seedInferenceProfiles(
|
|
514
|
+
seedInferenceProfiles({
|
|
515
|
+
preserveProfileNames: defaultConfigMerge.providedLlmProfileNames,
|
|
516
|
+
preserveActiveProfile: defaultConfigMerge.providedLlmActiveProfile,
|
|
517
|
+
});
|
|
457
518
|
log.info("Inference profile seeding complete");
|
|
458
519
|
} catch (err) {
|
|
459
520
|
log.warn(
|
|
@@ -462,11 +523,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
462
523
|
);
|
|
463
524
|
}
|
|
464
525
|
|
|
465
|
-
// Merge CLI-provided default config (from VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH)
|
|
466
|
-
// into the workspace config file before the first loadConfig() call so
|
|
467
|
-
// onboarding preferences are persisted alongside schema defaults.
|
|
468
|
-
mergeDefaultWorkspaceConfig();
|
|
469
|
-
|
|
470
526
|
log.info("Daemon startup: loading config");
|
|
471
527
|
const config = loadConfig();
|
|
472
528
|
|
|
@@ -625,6 +681,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
625
681
|
|
|
626
682
|
await server.start();
|
|
627
683
|
log.info("Daemon startup: DaemonServer started");
|
|
684
|
+
startDiskPressureGuardForLifecycle();
|
|
628
685
|
|
|
629
686
|
// Kick off the update bulletin background job AFTER `server.start()`
|
|
630
687
|
// resolves. The conversation store must be initialized before wake
|
|
@@ -1198,22 +1255,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
1198
1255
|
}
|
|
1199
1256
|
}
|
|
1200
1257
|
|
|
1201
|
-
// Prune trace events older than 7 days to keep the database lean.
|
|
1202
|
-
// Deferred so synchronous cleanup doesn't block the startup path.
|
|
1203
|
-
setTimeout(() => {
|
|
1204
|
-
try {
|
|
1205
|
-
const deletedTraceEvents = deleteOldTraceEvents(7);
|
|
1206
|
-
if (deletedTraceEvents > 0) {
|
|
1207
|
-
log.debug(
|
|
1208
|
-
{ deletedTraceEvents },
|
|
1209
|
-
`Pruned ${deletedTraceEvents} trace event(s) older than 7 days`,
|
|
1210
|
-
);
|
|
1211
|
-
}
|
|
1212
|
-
} catch (err) {
|
|
1213
|
-
log.warn({ err }, "Trace event cleanup failed");
|
|
1214
|
-
}
|
|
1215
|
-
}, 0);
|
|
1216
|
-
|
|
1217
1258
|
const workspaceHeartbeat = new WorkspaceHeartbeatService();
|
|
1218
1259
|
workspaceHeartbeat.start();
|
|
1219
1260
|
|
|
@@ -1236,6 +1277,12 @@ export async function runDaemon(): Promise<void> {
|
|
|
1236
1277
|
"Heartbeat service configured",
|
|
1237
1278
|
);
|
|
1238
1279
|
|
|
1280
|
+
try {
|
|
1281
|
+
backfillGuardIfNeeded();
|
|
1282
|
+
} catch (err) {
|
|
1283
|
+
log.warn({ err }, "Proactive artifact backfill failed");
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1239
1286
|
// Filing yields to the memory v2 consolidation job when the flag is on —
|
|
1240
1287
|
// both serve the same role (periodic background memory processing) and
|
|
1241
1288
|
// running both is redundant. The consolidation job runs through the
|
|
@@ -1281,10 +1328,14 @@ export async function runDaemon(): Promise<void> {
|
|
|
1281
1328
|
getQdrantManager: () => bgRefs.qdrantManager,
|
|
1282
1329
|
mcpManager,
|
|
1283
1330
|
telemetryReporter,
|
|
1284
|
-
cleanupPidFile
|
|
1331
|
+
cleanupPidFile: () => {
|
|
1332
|
+
stopDiskPressureGuardForLifecycle();
|
|
1333
|
+
cleanupPidFile();
|
|
1334
|
+
},
|
|
1285
1335
|
});
|
|
1286
1336
|
} catch (err) {
|
|
1287
1337
|
log.error({ err }, "Daemon startup failed — cleaning up");
|
|
1338
|
+
stopDiskPressureGuardForLifecycle();
|
|
1288
1339
|
cleanupPidFileIfOwner(process.pid);
|
|
1289
1340
|
throw err;
|
|
1290
1341
|
}
|
|
@@ -72,7 +72,7 @@ import { getLogger } from "../util/logger.js";
|
|
|
72
72
|
* keeps the supervisor free of path assumptions and simplifies
|
|
73
73
|
* tests.
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
interface MeetHostManifest {
|
|
76
76
|
/** SHA-256 of the shipped skill source tree. */
|
|
77
77
|
sourceHash: string;
|
|
78
78
|
}
|
|
@@ -84,7 +84,7 @@ export interface MeetHostManifest {
|
|
|
84
84
|
* protocol version) can be threaded through later without a
|
|
85
85
|
* signature break.
|
|
86
86
|
*/
|
|
87
|
-
|
|
87
|
+
interface MeetHostHandshakePayload {
|
|
88
88
|
sourceHash: string;
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -97,7 +97,7 @@ export interface MeetHostHandshakePayload {
|
|
|
97
97
|
* supervisor unaware of the rest of the IPC server's surface and avoids a
|
|
98
98
|
* circular import in tests that already stub `skill-server.js`.
|
|
99
99
|
*/
|
|
100
|
-
|
|
100
|
+
interface SkillRequestSender {
|
|
101
101
|
sendRequest(
|
|
102
102
|
connection: SkillIpcConnection,
|
|
103
103
|
method: string,
|
|
@@ -111,7 +111,7 @@ export interface SkillRequestSender {
|
|
|
111
111
|
* child. All are optional on construction — production callers
|
|
112
112
|
* rely on the defaults and tests override one or two at a time.
|
|
113
113
|
*/
|
|
114
|
-
|
|
114
|
+
interface MeetHostSupervisorDeps {
|
|
115
115
|
/** Absolute path to the shipped `meet-join` skill dir, containing `register.ts`. */
|
|
116
116
|
skillRuntimePath: string;
|
|
117
117
|
/** Absolute path to a standalone bun binary, or `"bun"` for PATH lookup. */
|
|
@@ -13,10 +13,12 @@ import { getLogger } from "../util/logger.js";
|
|
|
13
13
|
const log = getLogger("memory-v2-startup");
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Fire-and-forget seed of the v2
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Fire-and-forget seed of the v2 skill entries (now indexed alongside concept
|
|
17
|
+
* pages in `memory_v2_concept_pages` under the `skills/<id>` slug prefix), and
|
|
18
|
+
* a one-shot best-effort cleanup of the legacy `memory_v2_skills` Qdrant
|
|
19
|
+
* collection. Gated on both the `memory-v2-enabled` feature flag and the
|
|
20
|
+
* workspace-level `config.memory.v2.enabled` switch so v2 modules stay out of
|
|
21
|
+
* the v1 startup path when v2 is off.
|
|
20
22
|
*
|
|
21
23
|
* Uses a dynamic import so v2 code does not load unless the gate passes.
|
|
22
24
|
* Never awaits — startup must not block on this (see `assistant/CLAUDE.md`
|
|
@@ -32,4 +34,12 @@ export function maybeSeedMemoryV2Skills(config: AssistantConfig): void {
|
|
|
32
34
|
void import("../memory/v2/skill-store.js")
|
|
33
35
|
.then(({ seedV2SkillEntries }) => seedV2SkillEntries())
|
|
34
36
|
.catch((err) => log.warn({ err }, "Failed to seed v2 skill entries"));
|
|
37
|
+
void import("../memory/v2/qdrant.js")
|
|
38
|
+
.then(({ dropLegacySkillsCollection }) => dropLegacySkillsCollection())
|
|
39
|
+
.catch((err) =>
|
|
40
|
+
log.warn(
|
|
41
|
+
{ err },
|
|
42
|
+
"Failed to drop legacy memory_v2_skills collection — non-fatal",
|
|
43
|
+
),
|
|
44
|
+
);
|
|
35
45
|
}
|
|
@@ -20,6 +20,7 @@ export * from "./message-types/computer-use.js";
|
|
|
20
20
|
export * from "./message-types/contacts.js";
|
|
21
21
|
export * from "./message-types/conversations.js";
|
|
22
22
|
export * from "./message-types/diagnostics.js";
|
|
23
|
+
export * from "./message-types/disk-pressure.js";
|
|
23
24
|
export * from "./message-types/documents.js";
|
|
24
25
|
export * from "./message-types/guardian-actions.js";
|
|
25
26
|
export * from "./message-types/home.js";
|
|
@@ -71,6 +72,7 @@ import type {
|
|
|
71
72
|
_DiagnosticsClientMessages,
|
|
72
73
|
_DiagnosticsServerMessages,
|
|
73
74
|
} from "./message-types/diagnostics.js";
|
|
75
|
+
import type { _DiskPressureServerMessages } from "./message-types/disk-pressure.js";
|
|
74
76
|
import type {
|
|
75
77
|
_DocumentsClientMessages,
|
|
76
78
|
_DocumentsServerMessages,
|
|
@@ -203,6 +205,7 @@ export type ServerMessage =
|
|
|
203
205
|
| _NotificationsServerMessages
|
|
204
206
|
| _UpgradesServerMessages
|
|
205
207
|
| _AcpServerMessages
|
|
208
|
+
| _DiskPressureServerMessages
|
|
206
209
|
| SubagentEvent;
|
|
207
210
|
|
|
208
211
|
// === Contract schema ===
|
|
@@ -29,6 +29,8 @@ interface BaseTransportMetadata {
|
|
|
29
29
|
uxBrief?: string;
|
|
30
30
|
/** Chat type from the gateway (e.g. "private", "group", "supergroup", "channel"). */
|
|
31
31
|
chatType?: string;
|
|
32
|
+
/** IANA timezone reported by the active client for the current turn. */
|
|
33
|
+
clientTimezone?: string;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/**
|
|
@@ -522,6 +524,7 @@ export interface CompactionCircuitClosed {
|
|
|
522
524
|
export type ConversationErrorCode =
|
|
523
525
|
| "PROVIDER_NETWORK"
|
|
524
526
|
| "PROVIDER_RATE_LIMIT"
|
|
527
|
+
| "MANAGED_USAGE_LIMIT"
|
|
525
528
|
| "PROVIDER_OVERLOADED"
|
|
526
529
|
| "PROVIDER_API"
|
|
527
530
|
| "PROVIDER_BILLING"
|
|
@@ -532,6 +535,7 @@ export type ConversationErrorCode =
|
|
|
532
535
|
| "CONTEXT_TOO_LARGE"
|
|
533
536
|
| "CONVERSATION_ABORTED"
|
|
534
537
|
| "CONVERSATION_PROCESSING_FAILED"
|
|
538
|
+
| "DISK_SPACE_CRITICAL"
|
|
535
539
|
| "REGENERATE_FAILED"
|
|
536
540
|
| "UNKNOWN";
|
|
537
541
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DiskPressureStatus } from "../disk-pressure-guard.js";
|
|
2
|
+
|
|
3
|
+
/** Server push when the disk pressure status snapshot changes. */
|
|
4
|
+
export interface DiskPressureStatusChanged {
|
|
5
|
+
type: "disk_pressure_status_changed";
|
|
6
|
+
status: DiskPressureStatus;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type _DiskPressureServerMessages = DiskPressureStatusChanged;
|
|
@@ -236,10 +236,13 @@ export interface MessageComplete {
|
|
|
236
236
|
export interface ErrorMessage {
|
|
237
237
|
type: "error";
|
|
238
238
|
conversationId?: string;
|
|
239
|
+
requestId?: string;
|
|
239
240
|
code?: string;
|
|
240
241
|
message: string;
|
|
241
242
|
/** Categorizes the error so the client can offer contextual actions (e.g. "Send Anyway" for secret_blocked). */
|
|
242
243
|
category?: string;
|
|
244
|
+
/** Machine-readable conversation error category for clients that need source-aware recovery UI. */
|
|
245
|
+
errorCategory?: string;
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
export interface MessageQueued {
|
|
@@ -73,7 +73,7 @@ const DEFAULT_MIN_FREE_MB = 200;
|
|
|
73
73
|
|
|
74
74
|
// ── Result type ─────────────────────────────────────────────────────────
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
interface ProfilerSweepResult {
|
|
77
77
|
/** Number of completed runs pruned during this sweep. */
|
|
78
78
|
prunedCount: number;
|
|
79
79
|
/** Total bytes freed by pruning. */
|
|
@@ -159,7 +159,7 @@ function getFreeDiskBytes(path: string): number {
|
|
|
159
159
|
// ── Core operations ─────────────────────────────────────────────────────
|
|
160
160
|
|
|
161
161
|
/** Options for {@link rescanRuns}. */
|
|
162
|
-
|
|
162
|
+
interface RescanRunsOptions {
|
|
163
163
|
/**
|
|
164
164
|
* When true, skip all `writeManifest()` calls — just read existing
|
|
165
165
|
* manifests and recompute sizes without mutating the filesystem.
|
|
@@ -384,7 +384,7 @@ export function runProfilerSweep(): ProfilerSweepResult {
|
|
|
384
384
|
// health-endpoint reporting and control-plane polling.
|
|
385
385
|
|
|
386
386
|
/** Budget state for the active profiler run. */
|
|
387
|
-
|
|
387
|
+
interface ProfilerBudgetStatus {
|
|
388
388
|
/** Configured maximum bytes across all runs. */
|
|
389
389
|
maxBytes: number;
|
|
390
390
|
/** Bytes remaining before the byte-count budget is exceeded. */
|
|
@@ -398,7 +398,7 @@ export interface ProfilerBudgetStatus {
|
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
/** Summary of the most recently completed profiler run. */
|
|
401
|
-
|
|
401
|
+
interface ProfilerLastCompletedRun {
|
|
402
402
|
runId: string;
|
|
403
403
|
totalBytes: number;
|
|
404
404
|
artifactCount: number;
|
|
@@ -407,7 +407,7 @@ export interface ProfilerLastCompletedRun {
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
/** Full runtime status snapshot for health-endpoint embedding. */
|
|
410
|
-
|
|
410
|
+
interface ProfilerRuntimeStatus {
|
|
411
411
|
/** Whether profiling is enabled (env vars present). */
|
|
412
412
|
enabled: boolean;
|
|
413
413
|
/** The profiling mode ("cpu", "heap", "cpu+heap"), or null when disabled. */
|
|
@@ -21,8 +21,8 @@ export interface ToolSetupContext extends SurfaceConversationContext {
|
|
|
21
21
|
abortController: AbortController | null;
|
|
22
22
|
/** When set, only tools in this set may execute during the current turn. */
|
|
23
23
|
allowedToolNames?: Set<string>;
|
|
24
|
-
/**
|
|
25
|
-
|
|
24
|
+
/** Turn-scoped disk-pressure cleanup mode flag. */
|
|
25
|
+
diskPressureCleanupModeActive?: boolean;
|
|
26
26
|
/** True when the conversation has no connected client (HTTP-only path). */
|
|
27
27
|
hasNoClient?: boolean;
|
|
28
28
|
/** When true, the conversation is executing a task run and must not become interactive. */
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared document persistence service.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from documents-routes.ts so that both HTTP route handlers and
|
|
5
|
+
* background jobs (e.g. proactive artifact generation) can persist documents
|
|
6
|
+
* without going through the HTTP layer.
|
|
7
|
+
*/
|
|
8
|
+
import { rawRun } from "../memory/raw-query.js";
|
|
9
|
+
import { getLogger } from "../util/logger.js";
|
|
10
|
+
|
|
11
|
+
const log = getLogger("document-store");
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Junction table helper
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
/** Insert a document–conversation association (idempotent via INSERT OR IGNORE). */
|
|
18
|
+
export function addDocumentConversation(
|
|
19
|
+
surfaceId: string,
|
|
20
|
+
conversationId: string,
|
|
21
|
+
): void {
|
|
22
|
+
rawRun(
|
|
23
|
+
/*sql*/ `INSERT OR IGNORE INTO document_conversations (surface_id, conversation_id, created_at) VALUES (?, ?, ?)`,
|
|
24
|
+
surfaceId,
|
|
25
|
+
conversationId,
|
|
26
|
+
Date.now(),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Document persistence
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
export function saveDocument(params: {
|
|
35
|
+
surfaceId: string;
|
|
36
|
+
conversationId: string;
|
|
37
|
+
title: string;
|
|
38
|
+
content: string;
|
|
39
|
+
wordCount: number;
|
|
40
|
+
}): { success: true; surfaceId: string } | { success: false; error: string } {
|
|
41
|
+
try {
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
rawRun(
|
|
44
|
+
`INSERT INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
|
|
45
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
46
|
+
ON CONFLICT(surface_id) DO UPDATE SET
|
|
47
|
+
title = excluded.title,
|
|
48
|
+
content = excluded.content,
|
|
49
|
+
word_count = excluded.word_count,
|
|
50
|
+
updated_at = excluded.updated_at`,
|
|
51
|
+
params.surfaceId,
|
|
52
|
+
params.conversationId,
|
|
53
|
+
params.title,
|
|
54
|
+
params.content,
|
|
55
|
+
params.wordCount,
|
|
56
|
+
now,
|
|
57
|
+
now,
|
|
58
|
+
);
|
|
59
|
+
log.info(
|
|
60
|
+
{ surfaceId: params.surfaceId, title: params.title },
|
|
61
|
+
"Saved document",
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Best-effort: associate the document with the conversation.
|
|
65
|
+
// Failures (e.g. migration not yet applied, table missing) must not
|
|
66
|
+
// cause the save response to report failure — the document itself is
|
|
67
|
+
// already persisted at this point.
|
|
68
|
+
try {
|
|
69
|
+
addDocumentConversation(params.surfaceId, params.conversationId);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
log.warn(
|
|
72
|
+
{ err, surfaceId: params.surfaceId },
|
|
73
|
+
"Failed to record document–conversation association",
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return { success: true, surfaceId: params.surfaceId };
|
|
78
|
+
} catch (error) {
|
|
79
|
+
log.error({ err: error, surfaceId: params.surfaceId }, "Save error");
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|