@vellumai/assistant 0.7.2 → 0.8.0
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 +45 -29
- package/Dockerfile +1 -0
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- package/docs/architecture/memory.md +5 -2
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- 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 +470 -25
- package/package.json +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/app-control-flow.test.ts +21 -11
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- 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 +48 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/call-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -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__/cli-memory-v2-reembed-skills.test.ts +58 -28
- package/src/__tests__/config-loader-backfill.test.ts +379 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +284 -1
- 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 +6 -33
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +12 -7
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +457 -8
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-process-callsite.test.ts +38 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +74 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -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-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +476 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +61 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- 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 +2 -20
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -26
- 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 +36 -16
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +154 -67
- 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__/notification-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/oauth-cli.test.ts +121 -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 +60 -5
- 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__/secret-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/server-history-render.test.ts +82 -0
- package/src/__tests__/skill-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-tool.test.ts +44 -16
- package/src/__tests__/skills.test.ts +39 -0
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -0
- package/src/__tests__/twilio-validation.test.ts +2 -2
- package/src/__tests__/voice-session-bridge.test.ts +3 -0
- 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-069-seed-onboarding-threads.test.ts +120 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +78 -0
- package/src/agent/loop.ts +11 -0
- package/src/approvals/guardian-request-resolvers.ts +3 -32
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/calls/relay-server.ts +7 -1
- package/src/calls/voice-session-bridge.ts +1 -1
- 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 +11 -10
- package/src/cli/commands/oauth/__tests__/connect.test.ts +401 -219
- package/src/cli/commands/oauth/connect.ts +124 -40
- 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/app-builder/SKILL.md +1 -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 +13 -5
- package/src/config/loader.ts +199 -27
- 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 +76 -12
- 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-lifecycle-auto-analyze.test.ts +32 -0
- 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 +38 -0
- package/src/daemon/conversation-agent-loop.ts +183 -43
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +22 -10
- 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 +211 -29
- package/src/daemon/conversation-tool-setup.ts +66 -19
- package/src/daemon/conversation.ts +18 -23
- 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 +26 -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 +47 -22
- package/src/daemon/host-browser-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +50 -4
- package/src/daemon/host-file-proxy.ts +44 -8
- package/src/daemon/host-transfer-proxy.ts +97 -6
- package/src/daemon/lifecycle.ts +167 -101
- 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 +66 -15
- 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 +22 -1
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/tool-setup-types.ts +2 -2
- package/src/documents/document-store.ts +119 -0
- package/src/filing/filing-service.ts +29 -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 +149 -38
- package/src/ipc/gateway-client.ts +37 -3
- package/src/ipc/skill-server.ts +99 -42
- 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 +34 -51
- 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 +1 -16
- package/src/memory/context-search/sources/memory.ts +2 -3
- package/src/memory/context-search/sources/pkb.ts +2 -3
- 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 +136 -82
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/conversation-graph-memory.ts +72 -61
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +11 -67
- package/src/memory/graph/graph-search.ts +4 -24
- package/src/memory/graph/retriever.test.ts +12 -1
- package/src/memory/graph/retriever.ts +10 -15
- package/src/memory/graph/tool-handlers.ts +3 -4
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/indexer.ts +53 -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/__tests__/embed-concept-page.test.ts +116 -0
- package/src/memory/jobs/embed-concept-page.ts +223 -87
- package/src/memory/jobs-store.ts +48 -0
- package/src/memory/jobs-worker.ts +85 -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 +7 -0
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/qdrant-client.ts +3 -13
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/search/semantic.ts +10 -72
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +346 -255
- package/src/memory/v2/__tests__/consolidation-job.test.ts +61 -40
- package/src/memory/v2/__tests__/injection.test.ts +297 -190
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +326 -9
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +113 -196
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/static-context.test.ts +77 -14
- package/src/memory/v2/__tests__/sweep-job.test.ts +19 -33
- package/src/memory/v2/activation.ts +149 -156
- package/src/memory/v2/consolidation-job.ts +69 -20
- package/src/memory/v2/injection.ts +75 -68
- package/src/memory/v2/page-store.ts +39 -0
- package/src/memory/v2/prompts/consolidation.ts +41 -1
- package/src/memory/v2/qdrant.ts +306 -46
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +77 -110
- 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 +26 -8
- package/src/memory/v2/sweep-job.ts +5 -6
- package/src/memory/v2/types.ts +17 -10
- package/src/notifications/copy-composer.ts +47 -0
- package/src/notifications/decision-engine.ts +46 -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/permissions/gateway-threshold-reader.ts +116 -8
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- package/src/plugins/defaults/injectors.ts +36 -4
- 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 +914 -0
- package/src/proactive-artifact/job.ts +366 -0
- package/src/proactive-artifact/message-copy.ts +58 -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/prompts/templates/SOUL.md +13 -28
- 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 +15 -1
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/channel-approvals.ts +3 -2
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/pending-interactions.ts +27 -15
- 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/__tests__/memory-v2-routes.test.ts +147 -0
- package/src/runtime/routes/approval-routes.ts +7 -3
- package/src/runtime/routes/client-routes.ts +20 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -9
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +44 -1
- package/src/runtime/routes/conversation-routes.ts +35 -26
- package/src/runtime/routes/debug-bash-routes.ts +165 -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/filing-routes.ts +2 -3
- 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/index.ts +6 -0
- package/src/runtime/routes/memory-item-routes.test.ts +37 -17
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +136 -17
- 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/include-graph.ts +35 -13
- 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/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- 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 +14 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/permission-checker.ts +15 -0
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +31 -6
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +43 -3
- 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 +14 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +28 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- package/src/workspace/migrations/registry.ts +14 -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
|
@@ -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,119 @@
|
|
|
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 { rawGet, 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
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Update persisted document content (append or replace). */
|
|
88
|
+
export function updateDocumentContent(
|
|
89
|
+
surfaceId: string,
|
|
90
|
+
markdown: string,
|
|
91
|
+
mode: string,
|
|
92
|
+
): void {
|
|
93
|
+
try {
|
|
94
|
+
const existing = rawGet<{ content: string }>(
|
|
95
|
+
/*sql*/ `SELECT content FROM documents WHERE surface_id = ?`,
|
|
96
|
+
surfaceId,
|
|
97
|
+
);
|
|
98
|
+
if (!existing) {
|
|
99
|
+
log.info({ surfaceId }, "No persisted document to update");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const sep = mode === "append" && existing.content.length > 0 ? "\n\n" : "";
|
|
103
|
+
const newContent =
|
|
104
|
+
mode === "append" ? existing.content + sep + markdown : markdown;
|
|
105
|
+
const wordCount = newContent
|
|
106
|
+
.split(/\s+/)
|
|
107
|
+
.filter((w) => w.length > 0).length;
|
|
108
|
+
rawRun(
|
|
109
|
+
/*sql*/ `UPDATE documents SET content = ?, word_count = ?, updated_at = ? WHERE surface_id = ?`,
|
|
110
|
+
newContent,
|
|
111
|
+
wordCount,
|
|
112
|
+
Date.now(),
|
|
113
|
+
surfaceId,
|
|
114
|
+
);
|
|
115
|
+
log.info({ surfaceId, mode }, "Updated document content");
|
|
116
|
+
} catch (error) {
|
|
117
|
+
log.error({ err: error, surfaceId }, "Document content update error");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
5
4
|
import { getConfig } from "../config/loader.js";
|
|
6
5
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
6
|
+
import {
|
|
7
|
+
checkDiskPressureBackgroundGate,
|
|
8
|
+
diskPressureBackgroundSkipLogFields,
|
|
9
|
+
shouldLogDiskPressureBackgroundSkip,
|
|
10
|
+
} from "../daemon/disk-pressure-background-gate.js";
|
|
7
11
|
import { processMessage } from "../daemon/process-message.js";
|
|
8
12
|
import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
|
|
9
13
|
import { getLogger } from "../util/logger.js";
|
|
@@ -110,10 +114,7 @@ export class FilingService {
|
|
|
110
114
|
|
|
111
115
|
start(): void {
|
|
112
116
|
const fullConfig = getConfig();
|
|
113
|
-
if (
|
|
114
|
-
isAssistantFeatureFlagEnabled("memory-v2-enabled", fullConfig) &&
|
|
115
|
-
fullConfig.memory.v2.enabled
|
|
116
|
-
) {
|
|
117
|
+
if (fullConfig.memory.v2.enabled) {
|
|
117
118
|
log.info("Filing service disabled — memory v2 is active");
|
|
118
119
|
this._nextRunAt = null;
|
|
119
120
|
this._nextCompactionAt = null;
|
|
@@ -195,6 +196,10 @@ export class FilingService {
|
|
|
195
196
|
const config = getConfig().filing;
|
|
196
197
|
if (!force && !config.enabled) return false;
|
|
197
198
|
|
|
199
|
+
if (!force && this.shouldSkipForDiskPressure("filing")) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
198
203
|
if (
|
|
199
204
|
!force &&
|
|
200
205
|
!this.isWithinActiveHoursNow(
|
|
@@ -245,6 +250,10 @@ export class FilingService {
|
|
|
245
250
|
const config = getConfig().filing;
|
|
246
251
|
if (!force && !config.compactionEnabled) return false;
|
|
247
252
|
|
|
253
|
+
if (!force && this.shouldSkipForDiskPressure("compaction")) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
|
|
248
257
|
if (
|
|
249
258
|
!force &&
|
|
250
259
|
!this.isWithinActiveHoursNow(
|
|
@@ -299,6 +308,21 @@ export class FilingService {
|
|
|
299
308
|
this._nextCompactionAt = Date.now() + intervalMs;
|
|
300
309
|
}
|
|
301
310
|
|
|
311
|
+
private shouldSkipForDiskPressure(source: "filing" | "compaction"): boolean {
|
|
312
|
+
const diskPressureGate = checkDiskPressureBackgroundGate("background-work");
|
|
313
|
+
if (diskPressureGate.action === "allow") return false;
|
|
314
|
+
if (shouldLogDiskPressureBackgroundSkip(`filing-service:${source}`)) {
|
|
315
|
+
log.warn(
|
|
316
|
+
{
|
|
317
|
+
source,
|
|
318
|
+
...diskPressureBackgroundSkipLogFields(diskPressureGate),
|
|
319
|
+
},
|
|
320
|
+
"Filing service skipped during disk pressure cleanup mode",
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
|
|
302
326
|
private hasBufferContent(): boolean {
|
|
303
327
|
const bufferPath = join(getWorkspaceDir(), "pkb", "buffer.md");
|
|
304
328
|
if (!existsSync(bufferPath)) return false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
@@ -15,6 +15,7 @@ mock.module("../heartbeat-run-store.js", () => ({
|
|
|
15
15
|
markStaleRunsAsMissed: () => 0,
|
|
16
16
|
markStaleRunningAsError: () => 0,
|
|
17
17
|
listHeartbeatRuns: () => [],
|
|
18
|
+
countCompletedHeartbeatRuns: () => 10,
|
|
18
19
|
}));
|
|
19
20
|
|
|
20
21
|
// Stub the in-process SSE hub so the writer's publish path is a
|
|
@@ -146,6 +147,7 @@ interface OnDiskItem {
|
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
function readFeedItems(): OnDiskItem[] {
|
|
150
|
+
if (!existsSync(getHomeFeedPath())) return [];
|
|
149
151
|
const raw = JSON.parse(readFileSync(getHomeFeedPath(), "utf-8"));
|
|
150
152
|
return raw.items as OnDiskItem[];
|
|
151
153
|
}
|
|
@@ -174,7 +176,7 @@ afterEach(() => {
|
|
|
174
176
|
});
|
|
175
177
|
|
|
176
178
|
describe("heartbeat feed events", () => {
|
|
177
|
-
test("successful heartbeat
|
|
179
|
+
test("successful heartbeat without an alert does not emit a feed event", async () => {
|
|
178
180
|
_testProcessMessage = async () => ({ messageId: "msg-1" });
|
|
179
181
|
const service = new HeartbeatService({
|
|
180
182
|
alerter: () => {},
|
|
@@ -182,18 +184,12 @@ describe("heartbeat feed events", () => {
|
|
|
182
184
|
|
|
183
185
|
await service.runOnce({ force: true });
|
|
184
186
|
|
|
185
|
-
// Give
|
|
187
|
+
// Give any fire-and-forget surfacing work time to flush.
|
|
186
188
|
await new Promise((r) => setTimeout(r, 100));
|
|
187
189
|
|
|
188
190
|
const items = readFeedItems();
|
|
189
191
|
const heartbeatItem = items.find((i) => i.title === "Heartbeat");
|
|
190
|
-
expect(heartbeatItem).
|
|
191
|
-
expect(heartbeatItem!.summary).toBe(
|
|
192
|
-
"Periodic check completed. Tap to see details.",
|
|
193
|
-
);
|
|
194
|
-
expect(heartbeatItem!.priority).toBe(30);
|
|
195
|
-
expect(heartbeatItem!.urgency).toBeUndefined();
|
|
196
|
-
expect(heartbeatItem!.source).toBe("assistant");
|
|
192
|
+
expect(heartbeatItem).toBeUndefined();
|
|
197
193
|
});
|
|
198
194
|
|
|
199
195
|
test("failed heartbeat emits feed event with priority 55 and urgency medium", async () => {
|
|
@@ -218,13 +214,13 @@ describe("heartbeat feed events", () => {
|
|
|
218
214
|
expect(heartbeatItem!.source).toBe("assistant");
|
|
219
215
|
});
|
|
220
216
|
|
|
221
|
-
test("
|
|
217
|
+
test("repeated successful heartbeats without alerts stay silent", async () => {
|
|
222
218
|
_testProcessMessage = async () => ({ messageId: "msg-1" });
|
|
223
219
|
const service = new HeartbeatService({
|
|
224
220
|
alerter: () => {},
|
|
225
221
|
});
|
|
226
222
|
|
|
227
|
-
// Run twice —
|
|
223
|
+
// Run twice — neither should create a generic success item.
|
|
228
224
|
await service.runOnce({ force: true });
|
|
229
225
|
await new Promise((r) => setTimeout(r, 100));
|
|
230
226
|
await service.runOnce({ force: true });
|
|
@@ -232,9 +228,6 @@ describe("heartbeat feed events", () => {
|
|
|
232
228
|
|
|
233
229
|
const items = readFeedItems();
|
|
234
230
|
const heartbeatItems = items.filter((i) => i.title === "Heartbeat");
|
|
235
|
-
expect(heartbeatItems).toHaveLength(
|
|
236
|
-
|
|
237
|
-
const today = new Date().toISOString().split("T")[0];
|
|
238
|
-
expect(heartbeatItems[0]!.id).toBe(`emit:assistant:heartbeat:ok:${today}`);
|
|
231
|
+
expect(heartbeatItems).toHaveLength(0);
|
|
239
232
|
});
|
|
240
233
|
});
|
|
@@ -15,6 +15,7 @@ import { getDb } from "../../memory/db-connection.js";
|
|
|
15
15
|
import { initializeDb } from "../../memory/db-init.js";
|
|
16
16
|
import {
|
|
17
17
|
completeHeartbeatRun,
|
|
18
|
+
countCompletedHeartbeatRuns,
|
|
18
19
|
insertPendingHeartbeatRun,
|
|
19
20
|
listHeartbeatRuns,
|
|
20
21
|
markStaleRunningAsError,
|
|
@@ -213,4 +214,39 @@ describe("heartbeat-run-store", () => {
|
|
|
213
214
|
const rows = listHeartbeatRuns(3);
|
|
214
215
|
expect(rows).toHaveLength(3);
|
|
215
216
|
});
|
|
217
|
+
|
|
218
|
+
test("countCompletedHeartbeatRuns counts only ok rows", () => {
|
|
219
|
+
const now = Date.now();
|
|
220
|
+
|
|
221
|
+
// Insert runs with various statuses
|
|
222
|
+
const id1 = insertPendingHeartbeatRun(now);
|
|
223
|
+
startHeartbeatRun(id1);
|
|
224
|
+
completeHeartbeatRun(id1, { status: "ok", conversationId: "conv-1" });
|
|
225
|
+
|
|
226
|
+
const id2 = insertPendingHeartbeatRun(now + 1);
|
|
227
|
+
startHeartbeatRun(id2);
|
|
228
|
+
completeHeartbeatRun(id2, { status: "error", error: "something broke" });
|
|
229
|
+
|
|
230
|
+
const id3 = insertPendingHeartbeatRun(now + 2);
|
|
231
|
+
skipHeartbeatRun(id3, "disabled");
|
|
232
|
+
|
|
233
|
+
const id4 = insertPendingHeartbeatRun(now + 3);
|
|
234
|
+
startHeartbeatRun(id4);
|
|
235
|
+
completeHeartbeatRun(id4, { status: "ok", conversationId: "conv-2" });
|
|
236
|
+
|
|
237
|
+
expect(countCompletedHeartbeatRuns()).toBe(2);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("countCompletedHeartbeatRuns returns 0 when no ok rows exist", () => {
|
|
241
|
+
const now = Date.now();
|
|
242
|
+
|
|
243
|
+
const id1 = insertPendingHeartbeatRun(now);
|
|
244
|
+
startHeartbeatRun(id1);
|
|
245
|
+
completeHeartbeatRun(id1, { status: "error", error: "fail" });
|
|
246
|
+
|
|
247
|
+
const id2 = insertPendingHeartbeatRun(now + 1);
|
|
248
|
+
skipHeartbeatRun(id2, "outside_active_hours");
|
|
249
|
+
|
|
250
|
+
expect(countCompletedHeartbeatRuns()).toBe(0);
|
|
251
|
+
});
|
|
216
252
|
});
|
|
@@ -202,6 +202,19 @@ export function markStaleRunningAsError(
|
|
|
202
202
|
return rawChanges();
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Count the number of heartbeat runs that completed with status `ok`.
|
|
207
|
+
*/
|
|
208
|
+
export function countCompletedHeartbeatRuns(): number {
|
|
209
|
+
const db = getDb();
|
|
210
|
+
const row = db
|
|
211
|
+
.select({ count: sql<number>`count(*)` })
|
|
212
|
+
.from(heartbeatRuns)
|
|
213
|
+
.where(eq(heartbeatRuns.status, "ok"))
|
|
214
|
+
.get();
|
|
215
|
+
return row?.count ?? 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
205
218
|
/**
|
|
206
219
|
* List heartbeat runs ordered by `scheduledFor` descending.
|
|
207
220
|
*/
|