@vellumai/assistant 0.8.5 → 0.8.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/AGENTS.md +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
|
|
3
|
+
import type { FeedItem } from "../../home/feed-types.js";
|
|
3
4
|
import {
|
|
4
5
|
cliIpcCall,
|
|
5
6
|
exitCodeFromIpcResult,
|
|
@@ -10,6 +11,66 @@ import { log } from "../logger.js";
|
|
|
10
11
|
import { shouldOutputJson, writeOutput } from "../output.js";
|
|
11
12
|
import { tryResolveConversationId } from "../utils/conversation-id.js";
|
|
12
13
|
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Local types & helpers
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
interface ListHomeFeedPayload {
|
|
19
|
+
items: FeedItem[];
|
|
20
|
+
total: number;
|
|
21
|
+
returned: number;
|
|
22
|
+
hasMore: boolean;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseBoundedInt(
|
|
27
|
+
raw: string | undefined,
|
|
28
|
+
label: string,
|
|
29
|
+
bounds: { min: number; max?: number },
|
|
30
|
+
): { value?: number; error?: string } {
|
|
31
|
+
if (raw === undefined) return {};
|
|
32
|
+
const n = Number(raw);
|
|
33
|
+
const upper = bounds.max ?? Infinity;
|
|
34
|
+
if (
|
|
35
|
+
!Number.isFinite(n) ||
|
|
36
|
+
!Number.isInteger(n) ||
|
|
37
|
+
n < bounds.min ||
|
|
38
|
+
n > upper
|
|
39
|
+
) {
|
|
40
|
+
const range =
|
|
41
|
+
bounds.max !== undefined
|
|
42
|
+
? `[${bounds.min}, ${bounds.max}]`
|
|
43
|
+
: `>= ${bounds.min}`;
|
|
44
|
+
return {
|
|
45
|
+
error: `Invalid ${label} "${raw}". Must be an integer ${range}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { value: n };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function renderFeedItemsHuman(payload: ListHomeFeedPayload): void {
|
|
52
|
+
if (payload.items.length === 0) {
|
|
53
|
+
log.info("No notifications match the filters.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
log.info(`${payload.returned} of ${payload.total} notifications:\n`);
|
|
57
|
+
for (const item of payload.items) {
|
|
58
|
+
const idShort = item.id.slice(0, 8);
|
|
59
|
+
const status = item.status.toUpperCase().padEnd(10);
|
|
60
|
+
const urgency = (item.urgency ?? "").padEnd(8);
|
|
61
|
+
const headline = item.title ?? item.summary;
|
|
62
|
+
const convoTag = item.conversationId
|
|
63
|
+
? ` (conv: ${item.conversationId.slice(0, 8)})`
|
|
64
|
+
: "";
|
|
65
|
+
log.info(
|
|
66
|
+
` ${idShort} ${item.createdAt} ${status} ${urgency} ${headline}${convoTag}`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (payload.hasMore) {
|
|
70
|
+
log.info("\n(more results available; bump --offset to paginate)");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
13
74
|
// ---------------------------------------------------------------------------
|
|
14
75
|
// Command registration
|
|
15
76
|
// ---------------------------------------------------------------------------
|
|
@@ -52,7 +113,7 @@ Examples:
|
|
|
52
113
|
)
|
|
53
114
|
.requiredOption(
|
|
54
115
|
"--message <message>",
|
|
55
|
-
"Notification
|
|
116
|
+
"Notification body. Markdown (GFM) renders in the detail panel; the OS banner shows plain text.",
|
|
56
117
|
)
|
|
57
118
|
.option(
|
|
58
119
|
"--urgent",
|
|
@@ -67,7 +128,10 @@ Examples:
|
|
|
67
128
|
"--source-event-name <name>",
|
|
68
129
|
"Event name for audit, routing, and dedupe grouping (default: assistant.share)",
|
|
69
130
|
)
|
|
70
|
-
.option(
|
|
131
|
+
.option(
|
|
132
|
+
"--title <title>",
|
|
133
|
+
"Short headline (≤ 8 words). Always provide one — the auto-derived fallback just truncates --message.",
|
|
134
|
+
)
|
|
71
135
|
.option(
|
|
72
136
|
"--urgency <urgency>",
|
|
73
137
|
"Urgency hint: low, medium, high, critical (default: low; use --urgent for critical)",
|
|
@@ -353,84 +417,189 @@ Examples:
|
|
|
353
417
|
// list
|
|
354
418
|
// -------------------------------------------------------------------------
|
|
355
419
|
|
|
420
|
+
// Commander's `.exitOverride()` (used in tests) swallows thrown errors
|
|
421
|
+
// from collector functions, so we append values here and validate the
|
|
422
|
+
// accumulated array inside the action handler instead.
|
|
423
|
+
const collectFlag = (
|
|
424
|
+
value: string,
|
|
425
|
+
prev: string[] | undefined,
|
|
426
|
+
): string[] => [...(prev ?? []), value];
|
|
427
|
+
|
|
428
|
+
function validateEnumFlag(
|
|
429
|
+
values: string[] | undefined,
|
|
430
|
+
label: string,
|
|
431
|
+
allowed: readonly string[],
|
|
432
|
+
): { error?: string } {
|
|
433
|
+
if (!values) return {};
|
|
434
|
+
for (const v of values) {
|
|
435
|
+
if (!allowed.includes(v)) {
|
|
436
|
+
return {
|
|
437
|
+
error: `Invalid ${label} "${v}". Must be one of: ${allowed.join(", ")}`,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return {};
|
|
442
|
+
}
|
|
443
|
+
|
|
356
444
|
notifications
|
|
357
445
|
.command("list")
|
|
358
446
|
.description(
|
|
359
|
-
"List
|
|
447
|
+
"List notifications surfaced to the user via the home feed. Excludes dismissed items by default.",
|
|
448
|
+
)
|
|
449
|
+
.option(
|
|
450
|
+
"--all",
|
|
451
|
+
"Include dismissed items (default: only new/seen/acted_on)",
|
|
452
|
+
false,
|
|
453
|
+
)
|
|
454
|
+
.option(
|
|
455
|
+
"--status <status>",
|
|
456
|
+
"Filter by status (new|seen|acted_on|dismissed); repeatable. Overrides --all default behavior.",
|
|
457
|
+
collectFlag,
|
|
360
458
|
)
|
|
459
|
+
.option(
|
|
460
|
+
"--before <iso>",
|
|
461
|
+
"Only items with createdAt strictly before this ISO-8601 timestamp",
|
|
462
|
+
)
|
|
463
|
+
.option(
|
|
464
|
+
"--after <iso>",
|
|
465
|
+
"Only items with createdAt strictly after this ISO-8601 timestamp",
|
|
466
|
+
)
|
|
467
|
+
.option(
|
|
468
|
+
"--urgency <urgency>",
|
|
469
|
+
"Filter by urgency (low|medium|high|critical); repeatable",
|
|
470
|
+
collectFlag,
|
|
471
|
+
)
|
|
472
|
+
.option(
|
|
473
|
+
"--category <category>",
|
|
474
|
+
"Filter by category (security|scheduling|background|email|system); repeatable",
|
|
475
|
+
collectFlag,
|
|
476
|
+
)
|
|
477
|
+
.option(
|
|
478
|
+
"--conversation-id <id>",
|
|
479
|
+
"Only items tied to this conversation id",
|
|
480
|
+
)
|
|
481
|
+
.option(
|
|
482
|
+
"--from-assistant",
|
|
483
|
+
"Only items emitted by the assistant",
|
|
484
|
+
false,
|
|
485
|
+
)
|
|
486
|
+
.option("--noteworthy", "Only items flagged as noteworthy", false)
|
|
361
487
|
.option(
|
|
362
488
|
"--limit <n>",
|
|
363
|
-
"Maximum number of
|
|
489
|
+
"Maximum number of items to return (default: 20, max: 200)",
|
|
364
490
|
)
|
|
365
|
-
.option("--
|
|
491
|
+
.option("--offset <n>", "Pagination offset (default: 0)")
|
|
366
492
|
.addHelpText(
|
|
367
493
|
"after",
|
|
368
494
|
`
|
|
369
|
-
Reads
|
|
370
|
-
|
|
371
|
-
|
|
495
|
+
Reads the home feed at ~/.vellum/workspace/data/home-feed.json — the
|
|
496
|
+
user's notification inbox. Items are ordered by priority then recency,
|
|
497
|
+
matching what the user sees in the macOS Home page. The home feed covers
|
|
498
|
+
background/async notifications mirrored from the unified pipeline;
|
|
499
|
+
real-time chat pushes that did not mirror to the feed will not appear.
|
|
372
500
|
|
|
373
501
|
Examples:
|
|
374
502
|
$ assistant notifications list
|
|
375
|
-
$ assistant notifications list --
|
|
376
|
-
$ assistant notifications list --
|
|
377
|
-
$ assistant notifications list --
|
|
503
|
+
$ assistant notifications list --all
|
|
504
|
+
$ assistant notifications list --status new --status seen
|
|
505
|
+
$ assistant notifications list --after 2026-05-28T00:00:00Z --urgency high
|
|
506
|
+
$ assistant notifications list --conversation-id 7fab234c --json
|
|
507
|
+
$ assistant notifications list --limit 5 --offset 5`,
|
|
378
508
|
)
|
|
379
509
|
.action(
|
|
380
510
|
async (
|
|
381
511
|
opts: {
|
|
512
|
+
all?: boolean;
|
|
513
|
+
status?: string[];
|
|
514
|
+
before?: string;
|
|
515
|
+
after?: string;
|
|
516
|
+
urgency?: string[];
|
|
517
|
+
category?: string[];
|
|
518
|
+
conversationId?: string;
|
|
519
|
+
fromAssistant?: boolean;
|
|
520
|
+
noteworthy?: boolean;
|
|
382
521
|
limit?: string;
|
|
383
|
-
|
|
522
|
+
offset?: string;
|
|
384
523
|
},
|
|
385
524
|
cmd: Command,
|
|
386
525
|
) => {
|
|
387
526
|
try {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
527
|
+
const enumChecks: Array<{ error?: string }> = [
|
|
528
|
+
validateEnumFlag(opts.status, "status", [
|
|
529
|
+
"new",
|
|
530
|
+
"seen",
|
|
531
|
+
"acted_on",
|
|
532
|
+
"dismissed",
|
|
533
|
+
]),
|
|
534
|
+
validateEnumFlag(opts.urgency, "urgency", [
|
|
535
|
+
"low",
|
|
536
|
+
"medium",
|
|
537
|
+
"high",
|
|
538
|
+
"critical",
|
|
539
|
+
]),
|
|
540
|
+
validateEnumFlag(opts.category, "category", [
|
|
541
|
+
"security",
|
|
542
|
+
"scheduling",
|
|
543
|
+
"background",
|
|
544
|
+
"email",
|
|
545
|
+
"system",
|
|
546
|
+
]),
|
|
547
|
+
];
|
|
548
|
+
const enumError = enumChecks.find((c) => c.error);
|
|
549
|
+
if (enumError) {
|
|
550
|
+
writeOutput(cmd, { ok: false, error: enumError.error });
|
|
398
551
|
process.exitCode = 1;
|
|
399
552
|
return;
|
|
400
553
|
}
|
|
401
554
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
555
|
+
const limit = parseBoundedInt(opts.limit, "limit", {
|
|
556
|
+
min: 1,
|
|
557
|
+
max: 200,
|
|
558
|
+
});
|
|
559
|
+
if (limit.error) {
|
|
560
|
+
writeOutput(cmd, { ok: false, error: limit.error });
|
|
561
|
+
process.exitCode = 1;
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const offset = parseBoundedInt(opts.offset, "offset", {
|
|
565
|
+
min: 0,
|
|
566
|
+
});
|
|
567
|
+
if (offset.error) {
|
|
568
|
+
writeOutput(cmd, { ok: false, error: offset.error });
|
|
569
|
+
process.exitCode = 1;
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (opts.conversationId != null) {
|
|
574
|
+
const trimmed = opts.conversationId.trim();
|
|
575
|
+
if (trimmed.length === 0) {
|
|
411
576
|
writeOutput(cmd, {
|
|
412
577
|
ok: false,
|
|
413
|
-
error:
|
|
578
|
+
error: "Conversation ID must be a non-empty string",
|
|
414
579
|
});
|
|
415
580
|
process.exitCode = 1;
|
|
416
581
|
return;
|
|
417
582
|
}
|
|
418
|
-
limit = parsed;
|
|
419
583
|
}
|
|
420
584
|
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
585
|
+
const body: Record<string, unknown> = {};
|
|
586
|
+
if (opts.all) body.includeDismissed = true;
|
|
587
|
+
if (opts.status?.length) body.statuses = opts.status;
|
|
588
|
+
if (opts.before) body.before = opts.before;
|
|
589
|
+
if (opts.after) body.after = opts.after;
|
|
590
|
+
if (opts.urgency?.length) body.urgencies = opts.urgency;
|
|
591
|
+
if (opts.category?.length) body.categories = opts.category;
|
|
592
|
+
if (opts.conversationId)
|
|
593
|
+
body.conversationId = opts.conversationId.trim();
|
|
594
|
+
if (opts.fromAssistant) body.fromAssistant = true;
|
|
595
|
+
if (opts.noteworthy) body.noteworthy = true;
|
|
596
|
+
if (limit.value !== undefined) body.limit = limit.value;
|
|
597
|
+
if (offset.value !== undefined) body.offset = offset.value;
|
|
598
|
+
|
|
599
|
+
const result = await cliIpcCall<ListHomeFeedPayload>(
|
|
600
|
+
"list_home_feed",
|
|
601
|
+
{ body },
|
|
602
|
+
);
|
|
434
603
|
|
|
435
604
|
if (!result.ok) {
|
|
436
605
|
writeOutput(cmd, { ok: false, error: result.error });
|
|
@@ -438,19 +607,160 @@ Examples:
|
|
|
438
607
|
return;
|
|
439
608
|
}
|
|
440
609
|
|
|
441
|
-
const
|
|
610
|
+
const payload = result.result!;
|
|
611
|
+
writeOutput(cmd, { ok: true, ...payload });
|
|
612
|
+
|
|
613
|
+
if (!shouldOutputJson(cmd)) {
|
|
614
|
+
renderFeedItemsHuman(payload);
|
|
615
|
+
}
|
|
616
|
+
} catch (err) {
|
|
617
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
618
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
619
|
+
process.exitCode = 1;
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
// -------------------------------------------------------------------------
|
|
625
|
+
// edit
|
|
626
|
+
// -------------------------------------------------------------------------
|
|
627
|
+
|
|
628
|
+
notifications
|
|
629
|
+
.command("edit")
|
|
630
|
+
.description(
|
|
631
|
+
"Edit an already-sent notification. Patches the home-feed entry and updates the delivered channel message in place where supported (Slack today).",
|
|
632
|
+
)
|
|
633
|
+
.requiredOption(
|
|
634
|
+
"--id <id>",
|
|
635
|
+
"Feed item id (notif:<uuid>) from `notifications list --json`. Bare uuids without the `notif:` prefix are also accepted.",
|
|
636
|
+
)
|
|
637
|
+
.option(
|
|
638
|
+
"--message <message>",
|
|
639
|
+
"New notification body. Updates the home-feed summary and the delivered channel message text where supported.",
|
|
640
|
+
)
|
|
641
|
+
.option("--title <title>", "New short headline (≤ 8 words).")
|
|
642
|
+
.option(
|
|
643
|
+
"--urgency <urgency>",
|
|
644
|
+
"Set urgency (low|medium|high|critical). Feed-only — does not re-push channel messages.",
|
|
645
|
+
)
|
|
646
|
+
.option(
|
|
647
|
+
"--status <status>",
|
|
648
|
+
"Set lifecycle status (new|seen|acted_on|dismissed). Feed-only.",
|
|
649
|
+
)
|
|
650
|
+
.addHelpText(
|
|
651
|
+
"after",
|
|
652
|
+
`
|
|
653
|
+
At least one of --message, --title, --urgency, or --status must be
|
|
654
|
+
supplied. --urgency and --status only update the home-feed entry —
|
|
655
|
+
they never re-push channel messages.
|
|
656
|
+
|
|
657
|
+
Channel updates are best-effort: Slack messages get updated via
|
|
658
|
+
chat.update; other channels (push, email, SMS) cannot be edited and
|
|
659
|
+
are reported as "unsupported".
|
|
660
|
+
|
|
661
|
+
Examples:
|
|
662
|
+
$ assistant notifications edit --id notif:abc12345-... --message "Fixed body"
|
|
663
|
+
$ assistant notifications edit --id abc12345-... --title "Backup complete"
|
|
664
|
+
$ assistant notifications edit --id notif:abc12345-... --urgency low
|
|
665
|
+
$ assistant notifications edit --id notif:abc12345-... --status dismissed`,
|
|
666
|
+
)
|
|
667
|
+
.action(
|
|
668
|
+
async (
|
|
669
|
+
opts: {
|
|
670
|
+
id: string;
|
|
671
|
+
message?: string;
|
|
672
|
+
title?: string;
|
|
673
|
+
urgency?: string;
|
|
674
|
+
status?: string;
|
|
675
|
+
},
|
|
676
|
+
cmd: Command,
|
|
677
|
+
) => {
|
|
678
|
+
try {
|
|
679
|
+
const id = opts.id.trim();
|
|
680
|
+
if (!id) {
|
|
681
|
+
writeOutput(cmd, {
|
|
682
|
+
ok: false,
|
|
683
|
+
error: "--id must be a non-empty string",
|
|
684
|
+
});
|
|
685
|
+
process.exitCode = 1;
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (
|
|
690
|
+
opts.message === undefined &&
|
|
691
|
+
opts.title === undefined &&
|
|
692
|
+
opts.urgency === undefined &&
|
|
693
|
+
opts.status === undefined
|
|
694
|
+
) {
|
|
695
|
+
writeOutput(cmd, {
|
|
696
|
+
ok: false,
|
|
697
|
+
error:
|
|
698
|
+
"At least one of --message, --title, --urgency, or --status must be supplied",
|
|
699
|
+
});
|
|
700
|
+
process.exitCode = 1;
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (
|
|
705
|
+
opts.urgency != null &&
|
|
706
|
+
!["low", "medium", "high", "critical"].includes(opts.urgency)
|
|
707
|
+
) {
|
|
708
|
+
writeOutput(cmd, {
|
|
709
|
+
ok: false,
|
|
710
|
+
error: `Invalid urgency "${opts.urgency}". Must be one of: low, medium, high, critical`,
|
|
711
|
+
});
|
|
712
|
+
process.exitCode = 1;
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (
|
|
716
|
+
opts.status != null &&
|
|
717
|
+
!["new", "seen", "acted_on", "dismissed"].includes(opts.status)
|
|
718
|
+
) {
|
|
719
|
+
writeOutput(cmd, {
|
|
720
|
+
ok: false,
|
|
721
|
+
error: `Invalid status "${opts.status}". Must be one of: new, seen, acted_on, dismissed`,
|
|
722
|
+
});
|
|
723
|
+
process.exitCode = 1;
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const body: Record<string, unknown> = { id };
|
|
728
|
+
if (opts.message !== undefined) body.body = opts.message;
|
|
729
|
+
if (opts.title !== undefined) body.title = opts.title;
|
|
730
|
+
if (opts.urgency !== undefined) body.urgency = opts.urgency;
|
|
731
|
+
if (opts.status !== undefined) body.status = opts.status;
|
|
732
|
+
|
|
733
|
+
const result = await cliIpcCall<{
|
|
734
|
+
feedItem: FeedItem;
|
|
735
|
+
channels: Array<{
|
|
736
|
+
channel: string;
|
|
737
|
+
deliveryId: string;
|
|
738
|
+
outcome: "updated" | "unsupported" | "skipped" | "failed";
|
|
739
|
+
reason?: string;
|
|
740
|
+
}>;
|
|
741
|
+
}>("edit_notification", { body });
|
|
742
|
+
|
|
743
|
+
if (!result.ok) {
|
|
744
|
+
writeOutput(cmd, { ok: false, error: result.error });
|
|
745
|
+
process.exitCode = exitCodeFromIpcResult(result);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
442
748
|
|
|
443
|
-
|
|
749
|
+
const payload = result.result!;
|
|
750
|
+
writeOutput(cmd, { ok: true, ...payload });
|
|
444
751
|
|
|
445
752
|
if (!shouldOutputJson(cmd)) {
|
|
446
|
-
|
|
447
|
-
|
|
753
|
+
const item = payload.feedItem;
|
|
754
|
+
log.info(`Updated ${item.id}`);
|
|
755
|
+
const headline = item.title ?? item.summary;
|
|
756
|
+
log.info(` ${headline}`);
|
|
757
|
+
if (payload.channels.length === 0) {
|
|
758
|
+
log.info(" No channel deliveries to update.");
|
|
448
759
|
} else {
|
|
449
|
-
log.info(
|
|
450
|
-
for (const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
);
|
|
760
|
+
log.info(" Channels:");
|
|
761
|
+
for (const ch of payload.channels) {
|
|
762
|
+
const reason = ch.reason ? ` — ${ch.reason}` : "";
|
|
763
|
+
log.info(` ${ch.channel}: ${ch.outcome}${reason}`);
|
|
454
764
|
}
|
|
455
765
|
}
|
|
456
766
|
}
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* CLI-side helper that opens a URL on the user's host machine.
|
|
3
3
|
*
|
|
4
4
|
* Writes an `open_url` event to the `signals/emit-event` file so that the
|
|
5
|
-
*
|
|
6
|
-
* (e.g. the Swift macOS app) via the assistant event hub.
|
|
5
|
+
* assistant's ConfigWatcher picks it up and publishes it to connected
|
|
6
|
+
* clients (e.g. the Swift macOS app) via the assistant event hub.
|
|
7
|
+
*
|
|
8
|
+
* CLI-initiated emit — no conversation context available, so the inner
|
|
9
|
+
* message has no `conversationId`. That's fine: `OpenUrlEventSchema`
|
|
10
|
+
* declares `conversationId` as optional, so this payload parses
|
|
11
|
+
* cleanly on the web side as well as in the Swift macOS app.
|
|
7
12
|
*
|
|
8
13
|
* Uses only `node:` imports so it's safe for `ipc`-tagged CLI commands.
|
|
9
14
|
*/
|
package/src/cli/program.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { registerBrowserCommand } from "./commands/browser.js";
|
|
|
18
18
|
import { registerCacheCommand } from "./commands/cache.js";
|
|
19
19
|
import { registerChangelogCommand } from "./commands/changelog.js";
|
|
20
20
|
import { registerChannelVerificationSessionsCommand } from "./commands/channel-verification-sessions.js";
|
|
21
|
+
import { registerChannelsCommand } from "./commands/channels/index.js";
|
|
21
22
|
import { registerClientsCommand } from "./commands/clients.js";
|
|
22
23
|
import { registerCompletionsCommand } from "./commands/completions.js";
|
|
23
24
|
import { registerConfigCommand } from "./commands/config.js";
|
|
@@ -113,6 +114,7 @@ Examples:
|
|
|
113
114
|
registerCacheCommand(program);
|
|
114
115
|
registerChangelogCommand(program);
|
|
115
116
|
registerChannelVerificationSessionsCommand(program);
|
|
117
|
+
registerChannelsCommand(program);
|
|
116
118
|
registerClientsCommand(program);
|
|
117
119
|
registerCompletionsCommand(program);
|
|
118
120
|
registerConfigCommand(program);
|
|
@@ -18,6 +18,12 @@ import { dirname, join } from "node:path";
|
|
|
18
18
|
|
|
19
19
|
import { ipcGetFeatureFlags } from "../ipc/gateway-client.js";
|
|
20
20
|
import { getLogger } from "../util/logger.js";
|
|
21
|
+
import {
|
|
22
|
+
clearCachedOverrides,
|
|
23
|
+
getCachedOverrides,
|
|
24
|
+
isCachedFromGateway,
|
|
25
|
+
setCachedOverrides,
|
|
26
|
+
} from "./feature-flag-cache.js";
|
|
21
27
|
import type { AssistantConfig } from "./schema.js";
|
|
22
28
|
|
|
23
29
|
const log = getLogger("assistant-feature-flags");
|
|
@@ -112,22 +118,10 @@ function parseRegistryToDefaults(parsed: unknown): FeatureFlagDefaultsRegistry {
|
|
|
112
118
|
// ---------------------------------------------------------------------------
|
|
113
119
|
// Override loading — reads from gateway IPC socket
|
|
114
120
|
// ---------------------------------------------------------------------------
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
* `clearFeatureFlagOverridesCache()`.
|
|
120
|
-
*/
|
|
121
|
-
let cachedOverrides: Record<string, boolean> | null = null;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* True when `cachedOverrides` was populated by the gateway IPC fetch or
|
|
125
|
-
* preseeded by a test via `_setOverridesForTesting()`. Guards
|
|
126
|
-
* `initFeatureFlagOverrides()` from clobbering an existing populated cache
|
|
127
|
-
* when called a second time (e.g. by a CLI entry point after the daemon
|
|
128
|
-
* has already initialized).
|
|
129
|
-
*/
|
|
130
|
-
let cachedOverridesFromGateway = false;
|
|
121
|
+
//
|
|
122
|
+
// The override cache lives in `feature-flag-cache.ts` (stdlib-only) so test
|
|
123
|
+
// helpers can seed it without dragging the pino logger + gateway IPC client
|
|
124
|
+
// transitively through their import chain. See that file's block comment.
|
|
131
125
|
|
|
132
126
|
/**
|
|
133
127
|
* Fetch override values from the gateway via IPC (Unix domain socket).
|
|
@@ -181,8 +175,9 @@ const DEFAULT_INIT_RETRY_BACKOFFS_MS: readonly number[] = [
|
|
|
181
175
|
*
|
|
182
176
|
* No-ops when the cache is already populated — callers that want to
|
|
183
177
|
* refresh must call `clearFeatureFlagOverridesCache()` first. This lets
|
|
184
|
-
* tests preseed flag state via `
|
|
185
|
-
* gateway IPC call
|
|
178
|
+
* tests preseed flag state via `setOverridesForTesting()` (in
|
|
179
|
+
* `__tests__/feature-flag-test-helpers.ts`) without the gateway IPC call
|
|
180
|
+
* clobbering their setup.
|
|
186
181
|
*/
|
|
187
182
|
export async function initFeatureFlagOverrides(options?: {
|
|
188
183
|
retryBackoffsMs?: readonly number[];
|
|
@@ -194,7 +189,7 @@ export async function initFeatureFlagOverrides(options?: {
|
|
|
194
189
|
*/
|
|
195
190
|
callTimeoutMs?: number;
|
|
196
191
|
}): Promise<void> {
|
|
197
|
-
if (
|
|
192
|
+
if (isCachedFromGateway()) return;
|
|
198
193
|
|
|
199
194
|
const backoffs = options?.retryBackoffsMs ?? DEFAULT_INIT_RETRY_BACKOFFS_MS;
|
|
200
195
|
const callTimeoutMs = options?.callTimeoutMs;
|
|
@@ -208,15 +203,14 @@ export async function initFeatureFlagOverrides(options?: {
|
|
|
208
203
|
const delay = backoffs[attempt - 1]!;
|
|
209
204
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
210
205
|
// Re-check after the wait: a concurrent caller (e.g. a test using
|
|
211
|
-
// `
|
|
206
|
+
// `setOverridesForTesting`) may have populated the cache while we
|
|
212
207
|
// were sleeping. Bail out so we don't clobber their setup.
|
|
213
|
-
if (
|
|
208
|
+
if (isCachedFromGateway()) return;
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
const gatewayOverrides = await fetchOverridesFromGateway(callTimeoutMs);
|
|
217
212
|
if (Object.keys(gatewayOverrides).length > 0) {
|
|
218
|
-
|
|
219
|
-
cachedOverridesFromGateway = true;
|
|
213
|
+
setCachedOverrides(gatewayOverrides, { fromGateway: true });
|
|
220
214
|
if (attempt > 0) {
|
|
221
215
|
log.info(
|
|
222
216
|
{ attempt: attempt + 1 },
|
|
@@ -245,18 +239,20 @@ export async function initFeatureFlagOverrides(options?: {
|
|
|
245
239
|
* called at startup, or an empty record otherwise.
|
|
246
240
|
*/
|
|
247
241
|
function loadOverrides(): Record<string, boolean> {
|
|
248
|
-
return
|
|
242
|
+
return getCachedOverrides() ?? {};
|
|
249
243
|
}
|
|
250
244
|
|
|
251
245
|
/**
|
|
252
246
|
* Invalidate the cached overrides so the next call to
|
|
253
247
|
* `isAssistantFeatureFlagEnabled` re-reads from the gateway.
|
|
254
248
|
*
|
|
255
|
-
*
|
|
249
|
+
* Called by `refreshOverridesFromGateway()` when the gateway pushes a
|
|
250
|
+
* `feature_flags_changed` event, and by tests between cases to reset
|
|
251
|
+
* module state. (Tests typically call `setOverridesForTesting()` from
|
|
252
|
+
* `__tests__/feature-flag-test-helpers.ts`, which combines clear + seed.)
|
|
256
253
|
*/
|
|
257
254
|
export function clearFeatureFlagOverridesCache(): void {
|
|
258
|
-
|
|
259
|
-
cachedOverridesFromGateway = false;
|
|
255
|
+
clearCachedOverrides();
|
|
260
256
|
}
|
|
261
257
|
|
|
262
258
|
/**
|
|
@@ -272,21 +268,6 @@ export async function refreshOverridesFromGateway(): Promise<void> {
|
|
|
272
268
|
await initFeatureFlagOverrides({ retryBackoffsMs: [] });
|
|
273
269
|
}
|
|
274
270
|
|
|
275
|
-
/**
|
|
276
|
-
* Directly inject override values into the module-level cache.
|
|
277
|
-
*
|
|
278
|
-
* **Test-only** — bypasses the gateway IPC fetch so unit tests can control
|
|
279
|
-
* flag state without standing up a real gateway. Production code should
|
|
280
|
-
* never call this; use `clearFeatureFlagOverridesCache()` instead and let
|
|
281
|
-
* the resolver re-read from the gateway.
|
|
282
|
-
*/
|
|
283
|
-
export function _setOverridesForTesting(
|
|
284
|
-
overrides: Record<string, boolean>,
|
|
285
|
-
): void {
|
|
286
|
-
cachedOverrides = { ...overrides };
|
|
287
|
-
cachedOverridesFromGateway = true;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
271
|
// ---------------------------------------------------------------------------
|
|
291
272
|
// Public API
|
|
292
273
|
// ---------------------------------------------------------------------------
|
|
@@ -39,10 +39,14 @@ When the user asks to see, open, or pull up a document:
|
|
|
39
39
|
|
|
40
40
|
## Creating a new document
|
|
41
41
|
|
|
42
|
-
1. **Create the document**: Call `document_create` with a title (inferred from the request). Call the tool immediately, not after conversational preamble.
|
|
42
|
+
1. **Create the document**: Call `document_create` with a title (inferred from the request). Call the tool immediately, not after conversational preamble. Capture the `surface_id` from the response — every subsequent `document_update` call must reference it.
|
|
43
43
|
2. **Write content in Markdown**: Use proper structure (`#` for titles, `##` for sections), **bold**, _italic_, code blocks, tables, lists, blockquotes as appropriate.
|
|
44
44
|
3. **CRITICAL - Stream content in chunks**: Call `document_update` MULTIPLE times, not just once. Break content into logical chunks (paragraphs, sections, or every 200-300 words). Call `document_update` with `mode: "append"` for EACH chunk separately. The user experiences real-time content appearing as you write.
|
|
45
45
|
|
|
46
|
+
### Recovering from a failed update
|
|
47
|
+
|
|
48
|
+
If a `document_update` call fails with an `Invalid input` error (for example because `surface_id` was missing), do NOT call `document_create` again. The `surface_id` you need is in the tool result of the most recent `document_create` call in this turn. Retry `document_update` with that `surface_id` and the same content. Creating a second document with the same title produces a duplicate for the user.
|
|
49
|
+
|
|
46
50
|
## Editing an existing document
|
|
47
51
|
|
|
48
52
|
When the user requests changes to a document:
|