@vellumai/assistant 0.6.4 → 0.6.6
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/.prettierignore +5 -0
- package/AGENTS.md +9 -1
- package/ARCHITECTURE.md +43 -49
- package/Dockerfile +17 -3
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +33 -59
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +19 -18
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/error-handling.md +111 -0
- package/docs/plugins.md +761 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +334 -78
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +36 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +96 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +870 -655
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +440 -114
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +883 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -15
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +86 -46
- package/src/__tests__/conversation-agent-loop.test.ts +435 -216
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +36 -10
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +34 -12
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -15
- package/src/__tests__/conversation-process-callsite.test.ts +309 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +44 -21
- package/src/__tests__/conversation-queue.test.ts +68 -38
- package/src/__tests__/conversation-routes-disk-view.test.ts +36 -7
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2877 -152
- package/src/__tests__/conversation-runtime-workspace.test.ts +35 -50
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +39 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +53 -16
- package/src/__tests__/conversation-speed-override.test.ts +36 -12
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +118 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +4 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +33 -9
- package/src/__tests__/conversation-workspace-injection.test.ts +46 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -15
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +5 -2
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +29 -10
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +1 -66
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +621 -0
- package/src/__tests__/model-intents.test.ts +11 -83
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +46 -78
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -25
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +93 -14
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +69 -9
- package/src/__tests__/reaction-persistence.test.ts +561 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-identity.test.ts +0 -134
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +259 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -8
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +201 -94
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/user-plugin-loader.test.ts +191 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +22 -16
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +545 -115
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +886 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +463 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +606 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -12
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +69 -8
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +299 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/skills.ts +3 -4
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +39 -24
- package/src/cli.ts +0 -37
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +20 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +69 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -190
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +42 -10
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +49 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +317 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +64 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +96 -7
- package/src/context/__tests__/compact-prompt.test.ts +63 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +26 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +417 -39
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -3
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +162 -34
- package/src/daemon/conversation-agent-loop.ts +1282 -599
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +59 -17
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +1063 -211
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +51 -9
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +197 -64
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +65 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +7 -3
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +109 -82
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +63 -0
- package/src/daemon/message-types/messages.ts +21 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +122 -12
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -65
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +99 -28
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +11 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +97 -4
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +34 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +6 -3
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +63 -0
- package/src/ipc/routes/browser.ts +97 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +31 -1
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/upsert-contact.ts +25 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +76 -0
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +133 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +32 -4
- package/src/memory/db-init.ts +10 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +183 -53
- package/src/memory/graph/graph-search.test.ts +93 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +237 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/pkb/pkb-index.test.ts +369 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +252 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +499 -0
- package/src/memory/pkb/pkb-search.ts +159 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +147 -1
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1421 -0
- package/src/messaging/providers/slack/render-transcript.ts +501 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +31 -14
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -106
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +1223 -0
- package/src/permissions/approval-policy.ts +309 -0
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +1620 -0
- package/src/permissions/bash-risk-classifier.ts +950 -0
- package/src/permissions/checker.ts +348 -711
- package/src/permissions/command-registry.test.ts +774 -0
- package/src/permissions/command-registry.ts +1005 -0
- package/src/permissions/defaults.ts +28 -79
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +262 -0
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +25 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +9 -19
- package/src/platform/client.ts +19 -1
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +524 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +80 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +646 -0
- package/src/providers/speech-to-text/xai-realtime.ts +821 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +27 -18
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/client-registry.ts +261 -0
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +129 -9
- package/src/runtime/http-types.ts +23 -3
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +78 -0
- package/src/runtime/routes/approval-routes.ts +29 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +351 -138
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +987 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +720 -127
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +97 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +56 -8
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +35 -9
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +234 -2
- package/src/tools/browser/browser-execution.ts +150 -54
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +129 -73
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +116 -46
- package/src/tools/policy-context.ts +29 -8
- package/src/tools/registry.ts +195 -6
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/system/avatar-generator.ts +6 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +40 -5
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +9 -4
- package/src/util/pricing.ts +41 -8
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +56 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/send-notification-tool.test.ts +0 -83
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/cli/commands/shotgun.ts +0 -266
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -66
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -70,28 +70,36 @@ describe("startFeedScheduler", () => {
|
|
|
70
70
|
expect(summary2.gmailDigestRan).toBe(true);
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
test("rollup only re-runs every
|
|
73
|
+
test("rollup only re-runs every 2 hours as the safety-net cadence", async () => {
|
|
74
|
+
// The scheduler is the safety net; the primary trigger is the
|
|
75
|
+
// on-visit refresh in home-feed-routes.ts. Long cadence is
|
|
76
|
+
// intentional so the scheduler doesn't fight the route.
|
|
74
77
|
handle = startFeedScheduler(defaultOptions());
|
|
75
78
|
|
|
76
79
|
const t0 = new Date("2026-04-14T12:00:00.000Z");
|
|
77
80
|
await handle.runOnce(t0);
|
|
78
81
|
|
|
79
|
-
//
|
|
80
|
-
const t1 = new Date("2026-04-14T12:
|
|
82
|
+
// 30 min later — below the 2-hour gate.
|
|
83
|
+
const t1 = new Date("2026-04-14T12:30:00.000Z");
|
|
81
84
|
const summary1 = await handle.runOnce(t1);
|
|
82
85
|
expect(summary1.rollupRan).toBe(false);
|
|
83
86
|
|
|
84
|
-
//
|
|
85
|
-
const t2 = new Date("2026-04-
|
|
87
|
+
// 1h later — still below the 2-hour gate.
|
|
88
|
+
const t2 = new Date("2026-04-14T13:00:00.000Z");
|
|
86
89
|
const summary2 = await handle.runOnce(t2);
|
|
87
|
-
expect(summary2.rollupRan).toBe(
|
|
90
|
+
expect(summary2.rollupRan).toBe(false);
|
|
91
|
+
|
|
92
|
+
// 2h 1m later — past the gate, should re-run.
|
|
93
|
+
const t3 = new Date("2026-04-14T14:01:00.000Z");
|
|
94
|
+
const summary3 = await handle.runOnce(t3);
|
|
95
|
+
expect(summary3.rollupRan).toBe(true);
|
|
88
96
|
});
|
|
89
97
|
|
|
90
98
|
test("rollup cooldown is NOT advanced on no_provider so the next tick retries", async () => {
|
|
91
99
|
// Mimic the daemon startup ordering: the scheduler boots before
|
|
92
100
|
// the provider registry is ready. The first tick gets no_provider;
|
|
93
101
|
// the next tick (even one second later) must still run the rollup
|
|
94
|
-
// instead of waiting
|
|
102
|
+
// instead of waiting 2 hours.
|
|
95
103
|
rollupRunner.mockImplementationOnce(async () => ({
|
|
96
104
|
wroteCount: 0,
|
|
97
105
|
skippedReason: "no_provider",
|
|
@@ -110,10 +118,30 @@ describe("startFeedScheduler", () => {
|
|
|
110
118
|
expect(rollupRunner).toHaveBeenCalledTimes(2);
|
|
111
119
|
});
|
|
112
120
|
|
|
121
|
+
test("rollup cooldown is NOT advanced on in_flight so the next tick retries", async () => {
|
|
122
|
+
// in_flight means another caller (on-visit refresh, usually) is
|
|
123
|
+
// already running the producer. Advancing the gate here would
|
|
124
|
+
// force the NEXT tick to wait out the full cadence window even
|
|
125
|
+
// though nothing broken happened — the other caller's result is
|
|
126
|
+
// effectively this tick's run.
|
|
127
|
+
rollupRunner.mockImplementationOnce(async () => ({
|
|
128
|
+
wroteCount: 0,
|
|
129
|
+
skippedReason: "in_flight",
|
|
130
|
+
}));
|
|
131
|
+
|
|
132
|
+
handle = startFeedScheduler(defaultOptions());
|
|
133
|
+
await handle.runOnce(new Date("2026-04-14T12:00:00.000Z"));
|
|
134
|
+
expect(rollupRunner).toHaveBeenCalledTimes(1);
|
|
135
|
+
|
|
136
|
+
const summary = await handle.runOnce(new Date("2026-04-14T12:00:01.000Z"));
|
|
137
|
+
expect(summary.rollupRan).toBe(true);
|
|
138
|
+
expect(rollupRunner).toHaveBeenCalledTimes(2);
|
|
139
|
+
});
|
|
140
|
+
|
|
113
141
|
test("rollup cooldown is NOT advanced on no_actions so the next tick retries", async () => {
|
|
114
142
|
// no_actions means the activity log was empty — no LLM call was
|
|
115
143
|
// made. A subsequent tick should retry as soon as new actions
|
|
116
|
-
// land, not wait the full
|
|
144
|
+
// land, not wait the full 2-hour window.
|
|
117
145
|
rollupRunner.mockImplementationOnce(async () => ({
|
|
118
146
|
wroteCount: 0,
|
|
119
147
|
skippedReason: "no_actions",
|
|
@@ -131,7 +159,7 @@ describe("startFeedScheduler", () => {
|
|
|
131
159
|
|
|
132
160
|
test("rollup cooldown IS advanced on other skip reasons to preserve backoff", async () => {
|
|
133
161
|
// empty_items / malformed_output / provider_error are real LLM
|
|
134
|
-
// attempts — the next tick should be gated by the full
|
|
162
|
+
// attempts — the next tick should be gated by the full 2-hour
|
|
135
163
|
// window so a broken producer doesn't get hammered every tick.
|
|
136
164
|
rollupRunner.mockImplementationOnce(async () => ({
|
|
137
165
|
wroteCount: 0,
|
|
@@ -142,8 +170,8 @@ describe("startFeedScheduler", () => {
|
|
|
142
170
|
await handle.runOnce(new Date("2026-04-14T12:00:00.000Z"));
|
|
143
171
|
expect(rollupRunner).toHaveBeenCalledTimes(1);
|
|
144
172
|
|
|
145
|
-
//
|
|
146
|
-
const summary = await handle.runOnce(new Date("2026-04-14T12:
|
|
173
|
+
// Thirty minutes later — below the 2-hour gate, should NOT re-run.
|
|
174
|
+
const summary = await handle.runOnce(new Date("2026-04-14T12:30:00.000Z"));
|
|
147
175
|
expect(summary.rollupRan).toBe(false);
|
|
148
176
|
expect(rollupRunner).toHaveBeenCalledTimes(1);
|
|
149
177
|
});
|
|
@@ -364,6 +364,50 @@ describe("runRollupProducer", () => {
|
|
|
364
364
|
expect(result.wroteCount).toBe(0);
|
|
365
365
|
});
|
|
366
366
|
|
|
367
|
+
test("concurrent calls short-circuit the second with in_flight", async () => {
|
|
368
|
+
// Gate the provider behind a manually-controlled deferred so we
|
|
369
|
+
// can observe state while the first call is still inside the
|
|
370
|
+
// producer body. Without this we'd race the runtime's microtask
|
|
371
|
+
// scheduler to check in-flightness.
|
|
372
|
+
let release: ((value: ContentBlock[]) => void) | null = null;
|
|
373
|
+
const gated = new Promise<ContentBlock[]>((resolve) => {
|
|
374
|
+
release = resolve;
|
|
375
|
+
});
|
|
376
|
+
const provider = makeProvider(async () => {
|
|
377
|
+
const content = await gated;
|
|
378
|
+
return {
|
|
379
|
+
content,
|
|
380
|
+
model: "mock-model",
|
|
381
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
382
|
+
stopReason: "tool_use",
|
|
383
|
+
};
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
const first = runRollupProducer(new Date(), {
|
|
387
|
+
writeItem,
|
|
388
|
+
loadRelationshipState: stubRelationshipState,
|
|
389
|
+
loadRecentActions: stubLoadRecentActions(oneAction),
|
|
390
|
+
resolveProvider: () => provider,
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Second call lands while `first` is blocked awaiting the gated
|
|
394
|
+
// provider response — the in-flight guard must short-circuit it.
|
|
395
|
+
const second = await runRollupProducer(new Date(), {
|
|
396
|
+
writeItem,
|
|
397
|
+
loadRelationshipState: stubRelationshipState,
|
|
398
|
+
loadRecentActions: stubLoadRecentActions(oneAction),
|
|
399
|
+
resolveProvider: () => provider,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
expect(second.skippedReason).toBe("in_flight");
|
|
403
|
+
expect(second.wroteCount).toBe(0);
|
|
404
|
+
|
|
405
|
+
// Release the first call and let it finish.
|
|
406
|
+
release!([toolUseContent({ items: [] })]);
|
|
407
|
+
const firstResult = await first;
|
|
408
|
+
expect(firstResult.skippedReason).toBe("empty_items");
|
|
409
|
+
});
|
|
410
|
+
|
|
367
411
|
test("clamps priority to the valid [0, 100] window", async () => {
|
|
368
412
|
const provider = scriptedProvider([
|
|
369
413
|
toolUseContent({
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
feedItemSchema,
|
|
42
42
|
type FeedItemSource,
|
|
43
43
|
type FeedItemType,
|
|
44
|
+
type FeedItemUrgency,
|
|
44
45
|
} from "./feed-types.js";
|
|
45
46
|
import { appendFeedItem } from "./feed-writer.js";
|
|
46
47
|
|
|
@@ -80,6 +81,8 @@ export interface WriteAssistantFeedItemParams {
|
|
|
80
81
|
minTimeAway?: number;
|
|
81
82
|
/** Absolute ISO-8601 expiry timestamp. */
|
|
82
83
|
expiresAt?: string;
|
|
84
|
+
/** Visual urgency treatment — controls badge color independently of sort priority. */
|
|
85
|
+
urgency?: FeedItemUrgency;
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
/**
|
|
@@ -110,6 +113,7 @@ export async function writeAssistantFeedItem(
|
|
|
110
113
|
timestamp: now,
|
|
111
114
|
createdAt: now,
|
|
112
115
|
actions: params.actions,
|
|
116
|
+
urgency: params.urgency,
|
|
113
117
|
minTimeAway: params.minTimeAway,
|
|
114
118
|
expiresAt: params.expiresAt,
|
|
115
119
|
};
|
|
@@ -41,8 +41,10 @@ import { randomUUID } from "node:crypto";
|
|
|
41
41
|
import {
|
|
42
42
|
type FeedAction,
|
|
43
43
|
type FeedItem,
|
|
44
|
+
type FeedItemDetailPanel,
|
|
44
45
|
feedItemSchema,
|
|
45
46
|
type FeedItemSource,
|
|
47
|
+
type FeedItemUrgency,
|
|
46
48
|
} from "./feed-types.js";
|
|
47
49
|
import { appendFeedItem } from "./feed-writer.js";
|
|
48
50
|
|
|
@@ -93,6 +95,12 @@ export interface EmitFeedEventParams {
|
|
|
93
95
|
* until the user dismisses it (default for activity-log actions).
|
|
94
96
|
*/
|
|
95
97
|
expiresAt?: string;
|
|
98
|
+
/** Visual urgency treatment — controls badge color independently of sort priority. */
|
|
99
|
+
urgency?: FeedItemUrgency;
|
|
100
|
+
/** Optional conversation this feed item is associated with. */
|
|
101
|
+
conversationId?: string;
|
|
102
|
+
/** Server-driven detail panel descriptor; when present, the client opens this panel kind. */
|
|
103
|
+
detailPanel?: FeedItemDetailPanel;
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
/**
|
|
@@ -144,6 +152,9 @@ export async function emitFeedEvent(
|
|
|
144
152
|
timestamp: now,
|
|
145
153
|
createdAt: now,
|
|
146
154
|
actions: params.actions,
|
|
155
|
+
urgency: params.urgency,
|
|
156
|
+
conversationId: params.conversationId,
|
|
157
|
+
detailPanel: params.detailPanel,
|
|
147
158
|
minTimeAway: params.minTimeAway,
|
|
148
159
|
expiresAt: params.expiresAt,
|
|
149
160
|
};
|
|
@@ -43,7 +43,15 @@ const TICK_INTERVAL_MS = 5 * 60 * 1000;
|
|
|
43
43
|
|
|
44
44
|
/** Per-producer minimum gap between runs. */
|
|
45
45
|
const GMAIL_DIGEST_INTERVAL_MS = 5 * 60 * 1000;
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Roll-up cadence is deliberately long — 120 minutes — because the
|
|
48
|
+
* scheduler is the *safety net*, not the primary trigger. Opening the
|
|
49
|
+
* Home page fires a debounced on-visit refresh in the HTTP route (see
|
|
50
|
+
* `runtime/routes/home-feed-routes.ts`), which is the path most users
|
|
51
|
+
* actually hit. The scheduler exists so the feed still stays fresh
|
|
52
|
+
* for long idle stretches where nobody opens the Home page.
|
|
53
|
+
*/
|
|
54
|
+
const ROLLUP_INTERVAL_MS = 2 * 60 * 60 * 1000;
|
|
47
55
|
|
|
48
56
|
export interface FeedSchedulerHandle {
|
|
49
57
|
/** Stops the interval. Safe to call multiple times. */
|
|
@@ -146,8 +154,9 @@ export function startFeedScheduler(
|
|
|
146
154
|
"Rollup producer ran",
|
|
147
155
|
);
|
|
148
156
|
// Only advance the cooldown gate when the producer actually
|
|
149
|
-
// had a chance to run the LLM.
|
|
150
|
-
// before any provider call and should NOT burn the
|
|
157
|
+
// had a chance to run the LLM. Three skip reasons short-
|
|
158
|
+
// circuit before any provider call and should NOT burn the
|
|
159
|
+
// window:
|
|
151
160
|
// - `no_provider`: the provider registry wasn't ready yet
|
|
152
161
|
// (happens on the startup tick because the feed scheduler
|
|
153
162
|
// boots before the provider init pass in
|
|
@@ -155,12 +164,19 @@ export function startFeedScheduler(
|
|
|
155
164
|
// - `no_actions`: there was nothing to roll up. A subsequent
|
|
156
165
|
// tick should retry as soon as new actions land, not wait
|
|
157
166
|
// the full window.
|
|
167
|
+
// - `in_flight`: another caller (usually the on-visit
|
|
168
|
+
// refresh trigger in `home-feed-routes.ts`) is already
|
|
169
|
+
// running the rollup. That caller's result effectively
|
|
170
|
+
// counts as this scheduler tick's real run; bumping the
|
|
171
|
+
// gate here would force the NEXT tick to also wait out
|
|
172
|
+
// the full window even though nothing broken happened.
|
|
158
173
|
// Every other outcome — success, empty items, malformed
|
|
159
174
|
// output, provider error — is a real LLM attempt and does
|
|
160
175
|
// advance the gate so a broken producer doesn't hammer us.
|
|
161
176
|
if (
|
|
162
177
|
result.skippedReason !== "no_provider" &&
|
|
163
|
-
result.skippedReason !== "no_actions"
|
|
178
|
+
result.skippedReason !== "no_actions" &&
|
|
179
|
+
result.skippedReason !== "in_flight"
|
|
164
180
|
) {
|
|
165
181
|
lastRollupAt = nowMs;
|
|
166
182
|
}
|
package/src/home/feed-types.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { z } from "zod";
|
|
|
25
25
|
export type FeedItemType = "nudge" | "digest" | "action" | "thread";
|
|
26
26
|
|
|
27
27
|
/** User-facing lifecycle of a feed item. */
|
|
28
|
-
export type FeedItemStatus = "new" | "seen" | "acted_on";
|
|
28
|
+
export type FeedItemStatus = "new" | "seen" | "acted_on" | "dismissed";
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Origin of the underlying event.
|
|
@@ -34,7 +34,12 @@ export type FeedItemStatus = "new" | "seen" | "acted_on";
|
|
|
34
34
|
* stays exhaustive. Future sources will be added explicitly rather
|
|
35
35
|
* than letting arbitrary strings slip through.
|
|
36
36
|
*/
|
|
37
|
-
export type FeedItemSource =
|
|
37
|
+
export type FeedItemSource =
|
|
38
|
+
| "gmail"
|
|
39
|
+
| "slack"
|
|
40
|
+
| "calendar"
|
|
41
|
+
| "assistant"
|
|
42
|
+
| "telegram";
|
|
38
43
|
|
|
39
44
|
/**
|
|
40
45
|
* Internal field used by the hybrid authoring resolver (PR 5 writer).
|
|
@@ -46,6 +51,9 @@ export type FeedItemSource = "gmail" | "slack" | "calendar" | "assistant";
|
|
|
46
51
|
*/
|
|
47
52
|
export type FeedItemAuthor = "assistant" | "platform";
|
|
48
53
|
|
|
54
|
+
/** Visual urgency treatment — controls badge color independently of sort priority. */
|
|
55
|
+
export type FeedItemUrgency = "low" | "medium" | "high" | "critical";
|
|
56
|
+
|
|
49
57
|
/**
|
|
50
58
|
* A single action button attached to a feed item.
|
|
51
59
|
*
|
|
@@ -59,6 +67,20 @@ export interface FeedAction {
|
|
|
59
67
|
prompt: string;
|
|
60
68
|
}
|
|
61
69
|
|
|
70
|
+
/** Which detail panel the macOS client should open for this feed item. */
|
|
71
|
+
export type FeedItemDetailPanelKind =
|
|
72
|
+
| "emailDraft"
|
|
73
|
+
| "documentPreview"
|
|
74
|
+
| "permissionChat"
|
|
75
|
+
| "paymentAuth"
|
|
76
|
+
| "toolPermission"
|
|
77
|
+
| "updatesList";
|
|
78
|
+
|
|
79
|
+
/** Server-driven detail panel descriptor attached to a feed item. */
|
|
80
|
+
export interface FeedItemDetailPanel {
|
|
81
|
+
kind: FeedItemDetailPanelKind;
|
|
82
|
+
}
|
|
83
|
+
|
|
62
84
|
/**
|
|
63
85
|
* A single item rendered in the Home feed.
|
|
64
86
|
*
|
|
@@ -78,7 +100,7 @@ export interface FeedItem {
|
|
|
78
100
|
priority: number;
|
|
79
101
|
title: string;
|
|
80
102
|
summary: string;
|
|
81
|
-
/** Optional; when present must be one of the
|
|
103
|
+
/** Optional; when present must be one of the v1 sources. */
|
|
82
104
|
source?: FeedItemSource;
|
|
83
105
|
/** Event time (ISO-8601). */
|
|
84
106
|
timestamp: string;
|
|
@@ -89,12 +111,28 @@ export interface FeedItem {
|
|
|
89
111
|
/** Minimum seconds the user must be away before the item is shown. */
|
|
90
112
|
minTimeAway?: number;
|
|
91
113
|
actions?: FeedAction[];
|
|
114
|
+
/** Visual urgency treatment — controls badge color independently of sort priority. */
|
|
115
|
+
urgency?: FeedItemUrgency;
|
|
116
|
+
/** Optional conversation this feed item is associated with. */
|
|
117
|
+
conversationId?: string;
|
|
118
|
+
/** Server-driven detail panel descriptor; when present, the client opens this panel kind. */
|
|
119
|
+
detailPanel?: FeedItemDetailPanel;
|
|
92
120
|
/** Internal: who authored this item. */
|
|
93
121
|
author: FeedItemAuthor;
|
|
94
122
|
/** Internal: ISO-8601 writer-record time, used for ordering + TTL. */
|
|
95
123
|
createdAt: string;
|
|
96
124
|
}
|
|
97
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Summary of low-priority items that were collapsed out of the main
|
|
128
|
+
* feed list. The client renders this as a single "N low priority
|
|
129
|
+
* updates" line instead of showing each item individually.
|
|
130
|
+
*/
|
|
131
|
+
export interface LowPriorityCollapsed {
|
|
132
|
+
count: number;
|
|
133
|
+
itemIds: string[];
|
|
134
|
+
}
|
|
135
|
+
|
|
98
136
|
/**
|
|
99
137
|
* On-disk file format for `~/.vellum/workspace/data/home-feed.json`.
|
|
100
138
|
*
|
|
@@ -108,29 +146,66 @@ export interface HomeFeedFile {
|
|
|
108
146
|
updatedAt: string;
|
|
109
147
|
}
|
|
110
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Origin of a suggested prompt — whether it was deterministically derived
|
|
151
|
+
* (e.g. from a missing OAuth connection) or generated by the assistant.
|
|
152
|
+
*/
|
|
153
|
+
export type SuggestedPromptSource = "deterministic" | "assistant";
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* A prompt suggestion shown at the top of the Home page.
|
|
157
|
+
*
|
|
158
|
+
* Deterministic prompts are derived from workspace state (e.g. missing
|
|
159
|
+
* OAuth connections). Assistant-generated prompts are contextual
|
|
160
|
+
* conversation starters produced by the LLM.
|
|
161
|
+
*/
|
|
162
|
+
export interface SuggestedPrompt {
|
|
163
|
+
id: string;
|
|
164
|
+
label: string;
|
|
165
|
+
icon?: string;
|
|
166
|
+
prompt: string;
|
|
167
|
+
source: SuggestedPromptSource;
|
|
168
|
+
}
|
|
169
|
+
|
|
111
170
|
// ---------------------------------------------------------------------------
|
|
112
171
|
// Zod schemas
|
|
113
172
|
// ---------------------------------------------------------------------------
|
|
114
173
|
|
|
115
174
|
const feedItemTypeSchema = z.enum(["nudge", "digest", "action", "thread"]);
|
|
116
175
|
|
|
117
|
-
const feedItemStatusSchema = z.enum(["new", "seen", "acted_on"]);
|
|
176
|
+
const feedItemStatusSchema = z.enum(["new", "seen", "acted_on", "dismissed"]);
|
|
118
177
|
|
|
119
178
|
const feedItemSourceSchema = z.enum([
|
|
120
179
|
"gmail",
|
|
121
180
|
"slack",
|
|
122
181
|
"calendar",
|
|
123
182
|
"assistant",
|
|
183
|
+
"telegram",
|
|
124
184
|
]);
|
|
125
185
|
|
|
126
186
|
const feedItemAuthorSchema = z.enum(["assistant", "platform"]);
|
|
127
187
|
|
|
188
|
+
const feedItemUrgencySchema = z.enum(["low", "medium", "high", "critical"]);
|
|
189
|
+
|
|
128
190
|
const feedActionSchema = z.object({
|
|
129
191
|
id: z.string(),
|
|
130
192
|
label: z.string(),
|
|
131
193
|
prompt: z.string(),
|
|
132
194
|
});
|
|
133
195
|
|
|
196
|
+
const feedItemDetailPanelKindSchema = z.enum([
|
|
197
|
+
"emailDraft",
|
|
198
|
+
"documentPreview",
|
|
199
|
+
"permissionChat",
|
|
200
|
+
"paymentAuth",
|
|
201
|
+
"toolPermission",
|
|
202
|
+
"updatesList",
|
|
203
|
+
]);
|
|
204
|
+
|
|
205
|
+
const feedItemDetailPanelSchema = z.object({
|
|
206
|
+
kind: feedItemDetailPanelKindSchema,
|
|
207
|
+
});
|
|
208
|
+
|
|
134
209
|
/**
|
|
135
210
|
* Schema for a single `FeedItem`.
|
|
136
211
|
*
|
|
@@ -157,10 +232,28 @@ export const feedItemSchema = z.object({
|
|
|
157
232
|
expiresAt: z.string().optional(),
|
|
158
233
|
minTimeAway: z.number().int().min(0).optional(),
|
|
159
234
|
actions: z.array(feedActionSchema).optional(),
|
|
235
|
+
urgency: feedItemUrgencySchema.optional(),
|
|
236
|
+
conversationId: z.string().optional(),
|
|
237
|
+
detailPanel: feedItemDetailPanelSchema.optional(),
|
|
160
238
|
author: feedItemAuthorSchema,
|
|
161
239
|
createdAt: z.string(),
|
|
162
240
|
});
|
|
163
241
|
|
|
242
|
+
const suggestedPromptSourceSchema = z.enum(["deterministic", "assistant"]);
|
|
243
|
+
|
|
244
|
+
export const suggestedPromptSchema = z.object({
|
|
245
|
+
id: z.string(),
|
|
246
|
+
label: z.string(),
|
|
247
|
+
icon: z.string().optional(),
|
|
248
|
+
prompt: z.string(),
|
|
249
|
+
source: suggestedPromptSourceSchema,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
export const lowPriorityCollapsedSchema = z.object({
|
|
253
|
+
count: z.number().int().min(0),
|
|
254
|
+
itemIds: z.array(z.string()),
|
|
255
|
+
});
|
|
256
|
+
|
|
164
257
|
/** Schema for the on-disk `home-feed.json` file. */
|
|
165
258
|
export const homeFeedFileSchema = z.object({
|
|
166
259
|
version: z.literal(1),
|
|
@@ -161,7 +161,7 @@ export async function computeRelationshipState(): Promise<RelationshipState> {
|
|
|
161
161
|
// 1. The guardian contact's per-user file (`users/<slug>.md`), resolved
|
|
162
162
|
// via `resolveGuardianPersonaPath()` — this is the canonical location
|
|
163
163
|
// after workspace migration 031 and handles slugged userFiles like
|
|
164
|
-
// `users/
|
|
164
|
+
// `users/alice.md` that were invisible to a hardcoded `default.md`
|
|
165
165
|
// lookup.
|
|
166
166
|
// 2. Legacy workspace-root `USER.md` as a last-ditch fallback for very
|
|
167
167
|
// old workspaces that never ran migration 031.
|
|
@@ -361,7 +361,7 @@ export async function backfillRelationshipStateIfMissing(): Promise<void> {
|
|
|
361
361
|
* user content:
|
|
362
362
|
*
|
|
363
363
|
* 1. `resolveGuardianPersonaPath()` via contact-store — the canonical
|
|
364
|
-
* per-guardian slugged file (e.g. `users/
|
|
364
|
+
* per-guardian slugged file (e.g. `users/alice.md`).
|
|
365
365
|
* 2. `users/default.md` — the default-guardian persona file that the
|
|
366
366
|
* workspace migration leaves in place. Catches the window where
|
|
367
367
|
* the resolver throws or returns null but the file-backed content
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getConfiguredProvider } from "../providers/provider-send-message.js";
|
|
2
|
+
import { getLogger } from "../util/logger.js";
|
|
3
|
+
|
|
4
|
+
const log = getLogger("command-preview-rewriter");
|
|
5
|
+
const REWRITE_TIMEOUT_MS = 3000;
|
|
6
|
+
const REWRITE_MAX_TOKENS = 100;
|
|
7
|
+
|
|
8
|
+
const SYSTEM_PROMPT = `You rewrite technical computer commands into simple, human-readable descriptions.
|
|
9
|
+
Output ONLY the rewritten description — no quotes, no explanation, no preamble.
|
|
10
|
+
Keep it under 15 words. Use plain language a non-technical person would understand.
|
|
11
|
+
Examples:
|
|
12
|
+
- "ls -la ~/Desktop" → "View files on the desktop"
|
|
13
|
+
- "cat ~/.bashrc" → "Read shell configuration file"
|
|
14
|
+
- "rm -rf /tmp/cache" → "Delete temporary cache files"
|
|
15
|
+
- "grep -r 'password' ." → "Search files for the word 'password'"
|
|
16
|
+
- "curl https://api.example.com/users" → "Fetch user data from an API"`;
|
|
17
|
+
|
|
18
|
+
export async function rewriteCommandPreview(
|
|
19
|
+
toolName: string,
|
|
20
|
+
commandPreview: string,
|
|
21
|
+
): Promise<string | null> {
|
|
22
|
+
try {
|
|
23
|
+
const provider = await getConfiguredProvider("feedEventCopy");
|
|
24
|
+
if (!provider) return null;
|
|
25
|
+
|
|
26
|
+
const response = await provider.sendMessage(
|
|
27
|
+
[
|
|
28
|
+
{
|
|
29
|
+
role: "user",
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `Tool: ${toolName}\nCommand: ${commandPreview}`,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
[],
|
|
39
|
+
SYSTEM_PROMPT,
|
|
40
|
+
{
|
|
41
|
+
config: {
|
|
42
|
+
max_tokens: REWRITE_MAX_TOKENS,
|
|
43
|
+
callSite: "feedEventCopy",
|
|
44
|
+
},
|
|
45
|
+
signal: AbortSignal.timeout(REWRITE_TIMEOUT_MS),
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const block = response.content.find((entry) => entry.type === "text");
|
|
50
|
+
const text =
|
|
51
|
+
block && "text" in block ? (block as { text: string }).text.trim() : "";
|
|
52
|
+
if (!text) return null;
|
|
53
|
+
return (
|
|
54
|
+
text
|
|
55
|
+
.replace(/^["'`]+/, "")
|
|
56
|
+
.replace(/["'`]+$/, "")
|
|
57
|
+
.trim() || null
|
|
58
|
+
);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
log.warn(
|
|
61
|
+
{ err, toolName, commandPreview },
|
|
62
|
+
"Command preview rewrite failed",
|
|
63
|
+
);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -144,10 +144,16 @@ export interface RollupResult {
|
|
|
144
144
|
* `no_actions` means there was nothing to roll up — a quiet but
|
|
145
145
|
* normal outcome that does not advance the cooldown gate (no point
|
|
146
146
|
* re-running until new actions land).
|
|
147
|
+
*
|
|
148
|
+
* `in_flight` means another caller is already running the producer.
|
|
149
|
+
* The second call short-circuits without entering the body so we
|
|
150
|
+
* never fire two concurrent LLM requests — this guards against the
|
|
151
|
+
* scheduler tick and an on-visit refresh trigger racing each other.
|
|
147
152
|
*/
|
|
148
153
|
skippedReason:
|
|
149
154
|
| "no_provider"
|
|
150
155
|
| "no_actions"
|
|
156
|
+
| "in_flight"
|
|
151
157
|
| "empty_items"
|
|
152
158
|
| "provider_error"
|
|
153
159
|
| "malformed_output"
|
|
@@ -169,6 +175,16 @@ export interface RollupProducerDeps {
|
|
|
169
175
|
resolveProvider?: () => Provider | null;
|
|
170
176
|
}
|
|
171
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Module-level in-flight guard. Prevents two callers (e.g. the
|
|
180
|
+
* scheduler tick and an on-visit refresh trigger) from launching two
|
|
181
|
+
* concurrent LLM requests. A second caller short-circuits with
|
|
182
|
+
* `skippedReason: "in_flight"` without entering the body. The lock
|
|
183
|
+
* is released in the `finally` so a thrown exception can't strand
|
|
184
|
+
* it in the `true` state.
|
|
185
|
+
*/
|
|
186
|
+
let producerInFlight = false;
|
|
187
|
+
|
|
172
188
|
/**
|
|
173
189
|
* Run one roll-up pass. Loads recent action items from the feed plus
|
|
174
190
|
* relationship state, builds a user prompt around them, asks the
|
|
@@ -178,6 +194,21 @@ export interface RollupProducerDeps {
|
|
|
178
194
|
export async function runRollupProducer(
|
|
179
195
|
now: Date = new Date(),
|
|
180
196
|
deps: RollupProducerDeps = {},
|
|
197
|
+
): Promise<RollupResult> {
|
|
198
|
+
if (producerInFlight) {
|
|
199
|
+
return { wroteCount: 0, skippedReason: "in_flight" };
|
|
200
|
+
}
|
|
201
|
+
producerInFlight = true;
|
|
202
|
+
try {
|
|
203
|
+
return await runRollupProducerInner(now, deps);
|
|
204
|
+
} finally {
|
|
205
|
+
producerInFlight = false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function runRollupProducerInner(
|
|
210
|
+
now: Date,
|
|
211
|
+
deps: RollupProducerDeps,
|
|
181
212
|
): Promise<RollupResult> {
|
|
182
213
|
const writeItem = deps.writeItem ?? writeAssistantFeedItem;
|
|
183
214
|
const loadRelationshipState =
|
|
@@ -261,10 +292,10 @@ export async function runRollupProducer(
|
|
|
261
292
|
|
|
262
293
|
function resolveDefaultProvider(): ReturnType<typeof getProvider> | null {
|
|
263
294
|
const config = loadConfig();
|
|
264
|
-
if (!listProviders().includes(config.
|
|
295
|
+
if (!listProviders().includes(config.llm.default.provider)) {
|
|
265
296
|
return null;
|
|
266
297
|
}
|
|
267
|
-
return getProvider(config.
|
|
298
|
+
return getProvider(config.llm.default.provider);
|
|
268
299
|
}
|
|
269
300
|
|
|
270
301
|
/**
|
|
@@ -337,9 +368,7 @@ function buildUserPrompt(
|
|
|
337
368
|
* the `type` narrowing to digest/thread (actions and nudges are
|
|
338
369
|
* rejected here even if the model ignores the tool schema).
|
|
339
370
|
*/
|
|
340
|
-
function coerceRollupItem(
|
|
341
|
-
raw: unknown,
|
|
342
|
-
): WriteAssistantFeedItemParams | null {
|
|
371
|
+
function coerceRollupItem(raw: unknown): WriteAssistantFeedItemParams | null {
|
|
343
372
|
if (!raw || typeof raw !== "object") return null;
|
|
344
373
|
const obj = raw as Record<string, unknown>;
|
|
345
374
|
|