@vellumai/assistant 0.8.12 → 0.9.0-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +0 -14
- package/ARCHITECTURE.md +45 -45
- package/README.md +1 -1
- package/bun.lock +200 -154
- package/docs/architecture/integrations.md +3 -3
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/security.md +10 -10
- package/docs/runbook-trusted-contacts.md +12 -12
- package/docs/skills.md +6 -6
- package/docs/workflows-testing.md +221 -0
- package/docs/workflows.md +510 -0
- package/examples/plugins/echo/README.md +5 -5
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
- package/openapi.yaml +7197 -5708
- package/package.json +8 -4
- package/scripts/generate-openapi.ts +66 -114
- package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
- package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
- package/src/__tests__/app-compiler.test.ts +7 -1
- package/src/__tests__/app-dir-path-guard.test.ts +27 -3
- package/src/__tests__/app-executors.test.ts +43 -0
- package/src/__tests__/approval-cascade.test.ts +0 -5
- package/src/__tests__/approval-routes-http.test.ts +91 -0
- package/src/__tests__/assistant-stream-state.test.ts +107 -0
- package/src/__tests__/browser-fill-credential.test.ts +3 -3
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +63 -7
- package/src/__tests__/compaction-trail-store.test.ts +74 -1
- package/src/__tests__/compaction.benchmark.test.ts +63 -41
- package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-process-callsite.test.ts +0 -5
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
- package/src/__tests__/conversation-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
- package/src/__tests__/conversation-speed-override.test.ts +0 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
- package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
- package/src/__tests__/credential-broker-server-use.test.ts +2 -2
- package/src/__tests__/credential-broker.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +417 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault.test.ts +37 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
- package/src/__tests__/dynamic-page-surface.test.ts +219 -0
- package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
- package/src/__tests__/gateway-flag-listener.test.ts +24 -7
- package/src/__tests__/guardian-action-sweep.test.ts +56 -219
- package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
- package/src/__tests__/llm-resolver.test.ts +115 -0
- package/src/__tests__/managed-profile-guard.test.ts +6 -5
- package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
- package/src/__tests__/media-generate-image.test.ts +20 -9
- package/src/__tests__/mock-gateway-ipc.ts +23 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/normalize-onboarding.test.ts +26 -0
- package/src/__tests__/notification-decision-strategy.test.ts +4 -2
- package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
- package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
- package/src/__tests__/require-fresh-approval.test.ts +425 -1
- package/src/__tests__/resolve-app-id.test.ts +56 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
- package/src/__tests__/schedule-routes.test.ts +257 -4
- package/src/__tests__/schedule-store.test.ts +60 -0
- package/src/__tests__/schedule-tools.test.ts +247 -2
- package/src/__tests__/skill-execute-input.test.ts +85 -0
- package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
- package/src/__tests__/task-scheduler.test.ts +299 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
- package/src/__tests__/tool-result-spool.test.ts +3 -1
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
- package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
- package/src/agent/compaction-circuit.ts +11 -0
- package/src/agent/loop.ts +181 -12
- package/src/api/constants/call-sites.ts +12 -0
- package/src/api/events/assistant-thinking-delta.ts +10 -0
- package/src/api/events/usage-update.ts +7 -0
- package/src/api/index.ts +4 -1
- package/src/api/responses/memory-v3-selection-log.ts +18 -11
- package/src/approvals/approval-primitive.ts +2 -2
- package/src/background-wake/background-wake-routes.test.ts +5 -2
- package/src/bundler/compiler-tools.ts +1 -1
- package/src/bundler/package-resolver.ts +0 -1
- package/src/calls/call-domain.ts +1 -1
- package/src/calls/guardian-action-sweep.ts +16 -93
- package/src/cli/AGENTS.md +4 -0
- package/src/cli/commands/__tests__/schedules.test.ts +430 -1
- package/src/cli/commands/credentials.ts +28 -24
- package/src/cli/commands/image-generation.ts +23 -9
- package/src/cli/commands/notifications.ts +1 -1
- package/src/cli/commands/plugins.ts +89 -46
- package/src/cli/commands/schedules.ts +384 -11
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
- package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
- package/src/cli/lib/inspect-plugin.ts +62 -1
- package/src/cli/lib/install-from-github.ts +52 -5
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/config/__tests__/workflows-schema.test.ts +60 -0
- package/src/config/bundled-skills/acp/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
- package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
- package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
- package/src/config/bundled-skills/schedule/SKILL.md +7 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
- package/src/config/bundled-skills/workflows/SKILL.md +214 -0
- package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
- package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
- package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
- package/src/config/bundled-tool-registry.ts +14 -2
- package/src/config/call-site-defaults.ts +5 -0
- package/src/config/feature-flag-registry.json +12 -4
- package/src/config/llm-context-resolution.ts +8 -0
- package/src/config/llm-resolver.ts +30 -0
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
- package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
- package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
- package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/heartbeat.ts +4 -1
- package/src/config/schemas/llm.ts +33 -26
- package/src/config/schemas/memory-retrospective.ts +19 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/services.ts +5 -2
- package/src/config/schemas/workflows.ts +42 -0
- package/src/config/skills.ts +3 -3
- package/src/context/compactor.ts +273 -39
- package/src/context/post-turn-tool-result-truncation.ts +23 -6
- package/src/context/tool-result-spool.ts +12 -17
- package/src/credential-execution/executable-discovery.ts +1 -1
- package/src/credential-execution/process-manager.ts +37 -3
- package/src/credential-execution/prompted-credential.ts +205 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
- package/src/daemon/conversation-process.ts +11 -2
- package/src/daemon/conversation-surfaces.ts +167 -3
- package/src/daemon/conversation-tool-setup.ts +103 -26
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +115 -11
- package/src/daemon/handlers/shared.ts +26 -14
- package/src/daemon/host-cu-proxy.ts +15 -12
- package/src/daemon/host-file-proxy.ts +15 -12
- package/src/daemon/host-transfer-proxy.ts +30 -24
- package/src/daemon/lifecycle.ts +40 -3
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/messages.ts +2 -10
- package/src/daemon/message-types/workflows.ts +49 -0
- package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
- package/src/daemon/process-message.ts +6 -0
- package/src/daemon/tool-setup-types.ts +57 -0
- package/src/daemon/wake-conversation-ops.ts +18 -0
- package/src/heartbeat/heartbeat-run-store.ts +8 -2
- package/src/home/feed-types.ts +1 -1
- package/src/ipc/gateway-flag-listener.ts +28 -6
- package/src/mcp/mcp-auth-state.ts +8 -20
- package/src/media/__tests__/image-models.test.ts +57 -0
- package/src/media/image-models.ts +66 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
- package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
- package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
- package/src/memory/auto-analysis-enqueue.ts +14 -1
- package/src/memory/compaction-log-store-clickhouse.ts +6 -4
- package/src/memory/conversation-crud.ts +9 -2
- package/src/memory/conversation-disk-view.ts +1 -1
- package/src/memory/conversation-queries.ts +22 -7
- package/src/memory/db-init.ts +20 -0
- package/src/memory/db-maintenance.ts +16 -0
- package/src/memory/embedding-runtime-manager.ts +1 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
- package/src/memory/llm-request-log-source-local.ts +19 -1
- package/src/memory/llm-request-log-source.ts +35 -6
- package/src/memory/llm-request-log-store.ts +90 -2
- package/src/memory/memory-retrospective-constants.ts +9 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -6
- package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
- package/src/memory/memory-retrospective-job.ts +500 -208
- package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
- package/src/memory/memory-retrospective-state.ts +85 -2
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
- package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
- package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
- package/src/memory/migrations/284-workflow-runs.ts +51 -0
- package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
- package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
- package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
- package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
- package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
- package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
- package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/preloaded-apps.ts +116 -0
- package/src/memory/schema/infrastructure.ts +4 -0
- package/src/memory/schema/memory-core.ts +4 -0
- package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
- package/src/memory/v2/__tests__/page-store.test.ts +13 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -6
- package/src/memory/v2/page-store.ts +4 -3
- package/src/memory/v2/qdrant.ts +42 -3
- package/src/memory/v2/types.ts +16 -10
- package/src/messaging/draft-store.ts +1 -1
- package/src/notifications/access-request-copy.ts +200 -113
- package/src/notifications/adapters/slack.ts +250 -111
- package/src/notifications/adapters/telegram.ts +7 -44
- package/src/notifications/approval-card-builder.ts +93 -0
- package/src/notifications/broadcaster.ts +74 -0
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/copy-composer.ts +32 -26
- package/src/notifications/decision-engine.ts +59 -7
- package/src/notifications/guardian-question-mode.ts +145 -155
- package/src/notifications/home-feed-side-effect.ts +28 -11
- package/src/notifications/notification-utils.ts +66 -0
- package/src/notifications/signal.ts +6 -0
- package/src/notifications/tool-approval-copy.ts +142 -0
- package/src/notifications/types.ts +19 -0
- package/src/permissions/threshold.ts +11 -0
- package/src/plugin-api/types.ts +16 -4
- package/src/plugins/defaults/compaction/window-manager.ts +44 -0
- package/src/plugins/defaults/index.ts +46 -0
- package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
- package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
- package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
- package/src/prompts/__tests__/system-prompt.test.ts +100 -1
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
- package/src/prompts/normalize-onboarding.ts +2 -0
- package/src/prompts/persona-resolver.ts +3 -0
- package/src/prompts/system-prompt.ts +51 -2
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
- package/src/prompts/templates/system-sections.ts +8 -3
- package/src/providers/call-site-routing.ts +6 -3
- package/src/providers/fireworks/client.ts +3 -0
- package/src/providers/inference/auth.ts +52 -46
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
- package/src/providers/openai/chat-completions-provider.ts +47 -9
- package/src/providers/openai/coerce-object-args.ts +104 -0
- package/src/providers/retry.ts +8 -5
- package/src/providers/types.ts +10 -0
- package/src/runtime/__tests__/agent-wake.test.ts +629 -7
- package/src/runtime/access-request-helper.ts +16 -9
- package/src/runtime/agent-wake.ts +302 -51
- package/src/runtime/assistant-stream-state.ts +141 -8
- package/src/runtime/background-job-runner.ts +9 -0
- package/src/runtime/channel-approval-types.ts +1 -0
- package/src/runtime/channel-invite-transports/telegram.ts +6 -5
- package/src/runtime/channel-invite-transports/voice.ts +2 -2
- package/src/runtime/channel-invite-types.ts +4 -2
- package/src/runtime/channel-retry-sweep.ts +19 -41
- package/src/runtime/finalize-event-delivery.ts +72 -0
- package/src/runtime/guardian-action-message-composer.ts +0 -54
- package/src/runtime/http-server.ts +6 -14
- package/src/runtime/http-types.ts +0 -1
- package/src/runtime/message-composer-types.ts +0 -9
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
- package/src/runtime/middleware/auth.ts +27 -3
- package/src/runtime/middleware/rate-limiter.ts +28 -1
- package/src/runtime/migrations/vbundle-builder.ts +6 -5
- package/src/runtime/pending-interactions.ts +20 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
- package/src/runtime/routes/approval-routes.ts +35 -8
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
- package/src/runtime/routes/btw-routes.ts +37 -1
- package/src/runtime/routes/channel-delivery-routes.ts +11 -7
- package/src/runtime/routes/channel-route-definitions.ts +3 -0
- package/src/runtime/routes/channel-route-shared.ts +3 -1
- package/src/runtime/routes/consolidation-routes.ts +17 -13
- package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
- package/src/runtime/routes/conversation-list-routes.ts +41 -4
- package/src/runtime/routes/conversation-query-routes.ts +196 -11
- package/src/runtime/routes/conversation-routes.ts +15 -1
- package/src/runtime/routes/credential-prompt-routes.ts +39 -17
- package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
- package/src/runtime/routes/heartbeat-routes.ts +18 -13
- package/src/runtime/routes/image-generation-routes.ts +20 -2
- package/src/runtime/routes/inbound-message-handler.ts +13 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/log-export/AGENTS.md +1 -1
- package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +5 -9
- package/src/runtime/routes/plugins-routes.ts +26 -0
- package/src/runtime/routes/ps-routes.ts +10 -8
- package/src/runtime/routes/retrospective-routes.ts +235 -0
- package/src/runtime/routes/runs-pagination.ts +75 -0
- package/src/runtime/routes/schedule-routes.ts +367 -59
- package/src/runtime/routes/sounds-config-routes.ts +239 -0
- package/src/runtime/routes/surface-action-routes.ts +84 -4
- package/src/runtime/routes/workflow-routes.test.ts +372 -0
- package/src/runtime/routes/workflow-routes.ts +363 -0
- package/src/runtime/routes/workspace-routes.test.ts +61 -1
- package/src/runtime/routes/workspace-routes.ts +26 -1
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
- package/src/runtime/services/analyze-conversation.ts +26 -13
- package/src/schedule/inference-profile.ts +28 -0
- package/src/schedule/schedule-store.ts +152 -4
- package/src/schedule/scheduler-types.ts +6 -0
- package/src/schedule/scheduler.ts +96 -0
- package/src/security/secret-allowlist.ts +1 -1
- package/src/skills/path-classifier.ts +1 -1
- package/src/tools/apps/executors.ts +23 -0
- package/src/tools/apps/resolve-app-id.ts +42 -0
- package/src/tools/browser/browser-execution.ts +9 -11
- package/src/tools/credentials/broker.ts +4 -4
- package/src/tools/credentials/vault.ts +26 -137
- package/src/tools/executor.ts +69 -0
- package/src/tools/flag-gated-tools.test.ts +76 -0
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/registry.ts +51 -0
- package/src/tools/schedule/create.ts +77 -1
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +73 -1
- package/src/tools/skills/execute.ts +56 -0
- package/src/tools/terminal/shell.ts +1 -1
- package/src/tools/ui-surface/definitions.ts +91 -2
- package/src/tools/workflows/manage-workflows.ts +183 -0
- package/src/tools/workflows/run-workflow.test.ts +442 -0
- package/src/tools/workflows/run-workflow.ts +88 -0
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +24 -0
- package/src/util/canonicalize-identity.ts +12 -3
- package/src/util/platform.ts +17 -17
- package/src/watcher/__tests__/engine.test.ts +24 -0
- package/src/watcher/__tests__/telemetry.test.ts +135 -0
- package/src/watcher/engine.ts +7 -0
- package/src/watcher/telemetry.ts +74 -0
- package/src/workflows/capabilities.test.ts +365 -0
- package/src/workflows/capabilities.ts +359 -0
- package/src/workflows/deterministic-stringify.ts +27 -0
- package/src/workflows/engine-integration.test.ts +656 -0
- package/src/workflows/engine.test.ts +1144 -0
- package/src/workflows/engine.ts +1078 -0
- package/src/workflows/fanout-load.test.ts +168 -0
- package/src/workflows/journal-store.test.ts +369 -0
- package/src/workflows/journal-store.ts +470 -0
- package/src/workflows/leaf-runner.test.ts +704 -0
- package/src/workflows/leaf-runner.ts +589 -0
- package/src/workflows/library.test.ts +134 -0
- package/src/workflows/library.ts +124 -0
- package/src/workflows/run-manager.test.ts +711 -0
- package/src/workflows/run-manager.ts +593 -0
- package/src/workflows/sandbox-escape.test.ts +339 -0
- package/src/workflows/sandbox.test.ts +251 -0
- package/src/workflows/sandbox.ts +447 -0
- package/src/workspace/adaptive-thinking-repair.ts +33 -11
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
- package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
- package/src/workspace/migrations/031-drop-user-md.ts +1 -4
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
- package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
- package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
- package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
- package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/migrations/runner.ts +1 -1
- package/tsconfig.json +1 -1
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
- package/src/__tests__/guardian-action-store.test.ts +0 -106
- package/src/daemon/guardian-action-generators.ts +0 -71
- package/src/memory/guardian-action-store.ts +0 -484
- package/src/runtime/guardian-action-grant-minter.ts +0 -150
|
@@ -37,8 +37,9 @@ import {
|
|
|
37
37
|
} from "../../config/loader.js";
|
|
38
38
|
import { AssistantConfigSchema } from "../../config/schema.js";
|
|
39
39
|
import { getSchemaAtPath } from "../../config/schema-utils.js";
|
|
40
|
-
import { ProfileEntry } from "../../config/schemas/llm.js";
|
|
40
|
+
import { LLMConfigFragment, ProfileEntry } from "../../config/schemas/llm.js";
|
|
41
41
|
import { VALID_MEMORY_EMBEDDING_PROVIDERS } from "../../config/schemas/memory-storage.js";
|
|
42
|
+
import { ServiceModeSchema } from "../../config/schemas/services.js";
|
|
42
43
|
import { getConfigWatcher } from "../../daemon/config-watcher.js";
|
|
43
44
|
import {
|
|
44
45
|
getEmbeddingConfigInfo,
|
|
@@ -74,7 +75,7 @@ import { type LogRow } from "../../memory/llm-request-log-store.js";
|
|
|
74
75
|
import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
|
|
75
76
|
import { getMemoryV2ActivationLogByMessageIds } from "../../memory/memory-v2-activation-log-store.js";
|
|
76
77
|
import { MEMORY_V2_CONSOLIDATION_SOURCE } from "../../memory/v2/constants.js";
|
|
77
|
-
import {
|
|
78
|
+
import { getMemoryV3SelectionForInspectorByMessageIds } from "../../plugins/defaults/memory-v3-shadow/selection-log-store.js";
|
|
78
79
|
import {
|
|
79
80
|
createConnection,
|
|
80
81
|
listConnections,
|
|
@@ -468,6 +469,187 @@ function readPlainObject(value: unknown): Record<string, unknown> | undefined {
|
|
|
468
469
|
return value as Record<string, unknown>;
|
|
469
470
|
}
|
|
470
471
|
|
|
472
|
+
const WireProfileEntry = ProfileEntry.extend({
|
|
473
|
+
supportsVision: z.boolean().optional(),
|
|
474
|
+
})
|
|
475
|
+
.passthrough()
|
|
476
|
+
.meta({ id: "ProfileEntry" });
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Wire shape of the `memory` section in config responses. Passthrough
|
|
480
|
+
* preserves fields beyond `enabled` and `v2` so the client doesn't strip
|
|
481
|
+
* unrecognised memory config that newer daemons may add.
|
|
482
|
+
*/
|
|
483
|
+
const MemoryWireConfigSchema = z
|
|
484
|
+
.object({
|
|
485
|
+
enabled: z.boolean().optional(),
|
|
486
|
+
v2: z.object({ enabled: z.boolean().optional() }).passthrough().optional(),
|
|
487
|
+
})
|
|
488
|
+
.passthrough()
|
|
489
|
+
.meta({ id: "MemoryConfig" });
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Response schema for `GET /v1/config`.
|
|
493
|
+
*
|
|
494
|
+
* Describes the wire shape of the raw `settings.json` response after
|
|
495
|
+
* context-default filling and vision-flag enrichment. All top-level fields
|
|
496
|
+
* are optional because the on-disk config may be sparse. Additional
|
|
497
|
+
* top-level config sections beyond what's typed here are preserved via
|
|
498
|
+
* passthrough — this schema types the fields that web/macOS clients consume
|
|
499
|
+
* without restricting the full config surface.
|
|
500
|
+
*/
|
|
501
|
+
const ConfigGetResponseSchema = z
|
|
502
|
+
.object({
|
|
503
|
+
llm: z
|
|
504
|
+
.object({
|
|
505
|
+
default: LLMConfigFragment.extend({
|
|
506
|
+
provider_connection: z.string().optional(),
|
|
507
|
+
}).optional(),
|
|
508
|
+
profiles: z.record(z.string(), WireProfileEntry).optional(),
|
|
509
|
+
profileOrder: z.array(z.string()).optional(),
|
|
510
|
+
activeProfile: z.string().optional(),
|
|
511
|
+
callSites: z
|
|
512
|
+
.record(
|
|
513
|
+
z.string(),
|
|
514
|
+
LLMConfigFragment.extend({
|
|
515
|
+
profile: z.string().optional(),
|
|
516
|
+
}).nullable(),
|
|
517
|
+
)
|
|
518
|
+
.optional(),
|
|
519
|
+
profileSession: z
|
|
520
|
+
.object({
|
|
521
|
+
defaultTtlSeconds: z.number().optional(),
|
|
522
|
+
maxTtlSeconds: z.number().optional(),
|
|
523
|
+
})
|
|
524
|
+
.optional(),
|
|
525
|
+
pricingOverrides: z.array(z.unknown()).optional(),
|
|
526
|
+
})
|
|
527
|
+
.passthrough()
|
|
528
|
+
.optional(),
|
|
529
|
+
memory: MemoryWireConfigSchema.optional(),
|
|
530
|
+
services: z
|
|
531
|
+
.object({
|
|
532
|
+
"web-search": z
|
|
533
|
+
.object({
|
|
534
|
+
mode: ServiceModeSchema.optional(),
|
|
535
|
+
provider: z.string().optional(),
|
|
536
|
+
})
|
|
537
|
+
.passthrough()
|
|
538
|
+
.optional(),
|
|
539
|
+
"image-generation": z
|
|
540
|
+
.object({ mode: ServiceModeSchema.optional() })
|
|
541
|
+
.passthrough()
|
|
542
|
+
.optional(),
|
|
543
|
+
inference: z
|
|
544
|
+
.object({ mode: ServiceModeSchema.optional() })
|
|
545
|
+
.passthrough()
|
|
546
|
+
.optional(),
|
|
547
|
+
})
|
|
548
|
+
.passthrough()
|
|
549
|
+
.optional(),
|
|
550
|
+
})
|
|
551
|
+
.passthrough()
|
|
552
|
+
.meta({ id: "ConfigGetResponse" });
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Given a `z.object(...)` schema, returns a new schema where every property
|
|
556
|
+
* is `.nullable().optional()`. Used to express PATCH body semantics where any
|
|
557
|
+
* field can be `null` (meaning "delete via deep-merge") or omitted (unchanged).
|
|
558
|
+
*/
|
|
559
|
+
function nullablePartial(schema: z.ZodObject<z.ZodRawShape>) {
|
|
560
|
+
const shape: Record<string, z.ZodType> = {};
|
|
561
|
+
for (const [key, value] of Object.entries(schema.shape)) {
|
|
562
|
+
shape[key] = (value as z.ZodType).nullable().optional();
|
|
563
|
+
}
|
|
564
|
+
return z.object(shape);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* A single profile entry within a PATCH body. All fields are
|
|
569
|
+
* `.nullable().optional()`: `null` = delete via deep-merge, omitted =
|
|
570
|
+
* unchanged. Named so HeyAPI generates `ProfilePatchEntry` as a top-level
|
|
571
|
+
* export in the SDK.
|
|
572
|
+
*/
|
|
573
|
+
const ProfilePatchEntrySchema = nullablePartial(ProfileEntry)
|
|
574
|
+
.passthrough()
|
|
575
|
+
.meta({ id: "ProfilePatchEntry" });
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* A single call-site override within a PATCH body.
|
|
579
|
+
*/
|
|
580
|
+
const CallSiteOverrideDraftSchema = nullablePartial(
|
|
581
|
+
LLMConfigFragment.extend({ profile: z.string().optional() }),
|
|
582
|
+
)
|
|
583
|
+
.passthrough()
|
|
584
|
+
.meta({ id: "CallSiteOverrideDraft" });
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Request body schema for `PATCH /v1/config`.
|
|
588
|
+
*
|
|
589
|
+
* Mirrors the response shape but every field is `.nullable().optional()`:
|
|
590
|
+
* omitted keys are left unchanged by the daemon's deep-merge, `null` values
|
|
591
|
+
* delete the key. Uses the same Zod enums as `ConfigGetResponseSchema` so
|
|
592
|
+
* the generated SDK produces literal-union types — no hand-written patch
|
|
593
|
+
* types needed downstream.
|
|
594
|
+
*/
|
|
595
|
+
const ConfigPatchRequestSchema = z
|
|
596
|
+
.object({
|
|
597
|
+
llm: z
|
|
598
|
+
.object({
|
|
599
|
+
default: nullablePartial(
|
|
600
|
+
LLMConfigFragment.extend({
|
|
601
|
+
provider_connection: z.string().optional(),
|
|
602
|
+
}),
|
|
603
|
+
)
|
|
604
|
+
.passthrough()
|
|
605
|
+
.nullable()
|
|
606
|
+
.optional(),
|
|
607
|
+
profiles: z
|
|
608
|
+
.record(z.string(), ProfilePatchEntrySchema.nullable())
|
|
609
|
+
.optional(),
|
|
610
|
+
profileOrder: z.array(z.string()).optional(),
|
|
611
|
+
activeProfile: z.string().nullable().optional(),
|
|
612
|
+
callSites: z
|
|
613
|
+
.record(z.string(), CallSiteOverrideDraftSchema.nullable())
|
|
614
|
+
.optional(),
|
|
615
|
+
profileSession: z
|
|
616
|
+
.object({
|
|
617
|
+
defaultTtlSeconds: z.number().optional(),
|
|
618
|
+
maxTtlSeconds: z.number().optional(),
|
|
619
|
+
})
|
|
620
|
+
.nullable()
|
|
621
|
+
.optional(),
|
|
622
|
+
})
|
|
623
|
+
.passthrough()
|
|
624
|
+
.optional(),
|
|
625
|
+
memory: MemoryWireConfigSchema.nullable().optional(),
|
|
626
|
+
services: z
|
|
627
|
+
.object({
|
|
628
|
+
"web-search": z
|
|
629
|
+
.object({
|
|
630
|
+
mode: ServiceModeSchema.optional(),
|
|
631
|
+
provider: z.string().optional(),
|
|
632
|
+
})
|
|
633
|
+
.passthrough()
|
|
634
|
+
.nullable()
|
|
635
|
+
.optional(),
|
|
636
|
+
"image-generation": z
|
|
637
|
+
.object({ mode: ServiceModeSchema.optional() })
|
|
638
|
+
.passthrough()
|
|
639
|
+
.nullable()
|
|
640
|
+
.optional(),
|
|
641
|
+
inference: z
|
|
642
|
+
.object({ mode: ServiceModeSchema.optional() })
|
|
643
|
+
.passthrough()
|
|
644
|
+
.nullable()
|
|
645
|
+
.optional(),
|
|
646
|
+
})
|
|
647
|
+
.passthrough()
|
|
648
|
+
.optional(),
|
|
649
|
+
})
|
|
650
|
+
.passthrough()
|
|
651
|
+
.meta({ id: "ConfigPatchRequest" });
|
|
652
|
+
|
|
471
653
|
function handleGetConfig() {
|
|
472
654
|
try {
|
|
473
655
|
const config = applyContextDefaultsToRawConfig(loadRawConfig());
|
|
@@ -623,7 +805,10 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
|
|
|
623
805
|
deepMergeOverwrite(raw, patch);
|
|
624
806
|
|
|
625
807
|
await commitConfigWrite(raw, "patch");
|
|
626
|
-
|
|
808
|
+
|
|
809
|
+
const merged = applyContextDefaultsToRawConfig(loadRawConfig());
|
|
810
|
+
enrichProfilesWithVisionFlag(merged);
|
|
811
|
+
return merged;
|
|
627
812
|
}
|
|
628
813
|
|
|
629
814
|
/**
|
|
@@ -950,12 +1135,11 @@ async function handleGetLlmContext({
|
|
|
950
1135
|
// turn finishes — see `assistant/src/memory/conversation-crud.ts`.
|
|
951
1136
|
const conversationTotalEstimatedCostUsd =
|
|
952
1137
|
conversation?.totalEstimatedCost ?? null;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
: null;
|
|
1138
|
+
// v3 selections are keyed to the turn's message ids (stamped by the turn-end
|
|
1139
|
+
// backfill), independent of v2's tracker turn — so the panel shows whenever
|
|
1140
|
+
// the turn has v3 data, regardless of v2/v3 turn-counter drift.
|
|
1141
|
+
const memoryV3Selection =
|
|
1142
|
+
await getMemoryV3SelectionForInspectorByMessageIds(turnMessageIds);
|
|
959
1143
|
return {
|
|
960
1144
|
messageId,
|
|
961
1145
|
conversationKind,
|
|
@@ -1201,6 +1385,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
1201
1385
|
summary: "Get full config",
|
|
1202
1386
|
description: "Return the raw settings.json configuration object.",
|
|
1203
1387
|
tags: ["config"],
|
|
1388
|
+
responseBody: ConfigGetResponseSchema,
|
|
1204
1389
|
handler: handleGetConfig,
|
|
1205
1390
|
},
|
|
1206
1391
|
{
|
|
@@ -1215,8 +1400,8 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
1215
1400
|
description:
|
|
1216
1401
|
"Deep-merge a partial JSON object into the settings.json configuration.",
|
|
1217
1402
|
tags: ["config"],
|
|
1218
|
-
requestBody:
|
|
1219
|
-
responseBody:
|
|
1403
|
+
requestBody: ConfigPatchRequestSchema,
|
|
1404
|
+
responseBody: ConfigGetResponseSchema,
|
|
1220
1405
|
handler: handlePatchConfig,
|
|
1221
1406
|
},
|
|
1222
1407
|
{
|
|
@@ -97,6 +97,7 @@ import {
|
|
|
97
97
|
getOrCreateConversation,
|
|
98
98
|
} from "../../memory/conversation-key-store.js";
|
|
99
99
|
import { searchConversations } from "../../memory/conversation-queries.js";
|
|
100
|
+
import { MEMORY_RETROSPECTIVE_FORK_SOURCE } from "../../memory/memory-retrospective-constants.js";
|
|
100
101
|
import { recordOnboardingEvent } from "../../memory/onboarding-events-store.js";
|
|
101
102
|
import { buildSlackMessageDeepLinks } from "../../messaging/providers/slack/deep-link.js";
|
|
102
103
|
import {
|
|
@@ -681,12 +682,23 @@ export function handleListMessages({
|
|
|
681
682
|
// is left visible, the result will render as a standalone orphan because
|
|
682
683
|
// `mergeToolResultsIntoAssistantMessages` has nothing to merge it into.
|
|
683
684
|
//
|
|
685
|
+
// Exception: memory-retrospective fork conversations show their hidden rows
|
|
686
|
+
// (the retrospective instruction) so the run is readable as a distinct turn
|
|
687
|
+
// and its LLM call is inspectable. The instruction row also separates the
|
|
688
|
+
// copied source tail from the review turn, so `mergeConsecutiveAssistantMessages`
|
|
689
|
+
// no longer folds the review into the source's last assistant message. This
|
|
690
|
+
// is display-only and scoped to the fork source; the LLM-side `getMessages`
|
|
691
|
+
// loader is unfiltered regardless.
|
|
692
|
+
//
|
|
684
693
|
// Only renderable roles reach this UI-facing transcript. `system` rows (a
|
|
685
694
|
// permitted `MessageRole`, e.g. skill-authored context) are agent-context
|
|
686
695
|
// scaffolding, never a displayed turn, so they are dropped here at the
|
|
687
696
|
// source rather than narrowed away per-client.
|
|
697
|
+
const isRetrospectiveFork =
|
|
698
|
+
getConversation(resolvedConversationId)?.source ===
|
|
699
|
+
MEMORY_RETROSPECTIVE_FORK_SOURCE;
|
|
688
700
|
const visibleFilter = (m: MessageRow) =>
|
|
689
|
-
!isHiddenMessage(m.metadata) &&
|
|
701
|
+
(isRetrospectiveFork || !isHiddenMessage(m.metadata)) &&
|
|
690
702
|
(m.role === "user" || m.role === "assistant");
|
|
691
703
|
|
|
692
704
|
if (isPaginated) {
|
|
@@ -1030,6 +1042,7 @@ export function persistOnboardingArtifacts(onboarding: {
|
|
|
1030
1042
|
tasks: string[];
|
|
1031
1043
|
tone: string;
|
|
1032
1044
|
userName?: string;
|
|
1045
|
+
occupation?: string;
|
|
1033
1046
|
assistantName?: string;
|
|
1034
1047
|
priorAssistants?: string[];
|
|
1035
1048
|
cohort?: string;
|
|
@@ -2693,6 +2706,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
2693
2706
|
tasks: z.array(z.string()),
|
|
2694
2707
|
tone: z.string(),
|
|
2695
2708
|
userName: z.string().optional(),
|
|
2709
|
+
occupation: z.string().optional(),
|
|
2696
2710
|
assistantName: z.string().optional(),
|
|
2697
2711
|
googleConnected: z.boolean().optional(),
|
|
2698
2712
|
googleScopes: z.array(z.string()).optional(),
|
|
@@ -8,14 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
|
|
11
|
-
import { requestSecretStandalone } from "../../daemon/handlers/shared.js";
|
|
12
|
-
import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
|
|
13
|
-
import { credentialKey } from "../../security/credential-key.js";
|
|
14
|
-
import { setSecureKeyAsync } from "../../security/secure-keys.js";
|
|
15
11
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "../../
|
|
12
|
+
formatSlackChannelStatus,
|
|
13
|
+
persistPromptedCredential,
|
|
14
|
+
} from "../../credential-execution/prompted-credential.js";
|
|
15
|
+
import { requestSecretStandalone } from "../../daemon/handlers/shared.js";
|
|
16
|
+
import { assertMetadataWritable } from "../../tools/credentials/metadata-store.js";
|
|
19
17
|
import { LOCAL_PRINCIPALS } from "../auth/route-policy.js";
|
|
20
18
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
21
19
|
|
|
@@ -37,9 +35,11 @@ const CredentialPromptParams = z.object({
|
|
|
37
35
|
label: z.string().min(1),
|
|
38
36
|
description: z.string().optional(),
|
|
39
37
|
placeholder: z.string().optional(),
|
|
38
|
+
usageDescription: z.string().optional(),
|
|
40
39
|
allowedDomains: z.array(z.string()).optional(),
|
|
41
40
|
allowedTools: z.array(z.string()).optional(),
|
|
42
41
|
injectionTemplates: z.array(InjectionTemplateSchema).optional(),
|
|
42
|
+
conversationId: z.string().optional(),
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
// ---------------------------------------------------------------------------
|
|
@@ -51,6 +51,7 @@ export type CredentialPromptResult = {
|
|
|
51
51
|
error?: string;
|
|
52
52
|
service?: string;
|
|
53
53
|
field?: string;
|
|
54
|
+
message?: string;
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
// ---------------------------------------------------------------------------
|
|
@@ -68,8 +69,10 @@ async function handleCredentialPrompt({ body = {} }: RouteHandlerArgs) {
|
|
|
68
69
|
label: validated.label,
|
|
69
70
|
description: validated.description,
|
|
70
71
|
placeholder: validated.placeholder,
|
|
72
|
+
purpose: validated.usageDescription,
|
|
71
73
|
allowedTools: validated.allowedTools,
|
|
72
74
|
allowedDomains: validated.allowedDomains,
|
|
75
|
+
conversationId: validated.conversationId,
|
|
73
76
|
});
|
|
74
77
|
|
|
75
78
|
if (!result.value) {
|
|
@@ -80,23 +83,41 @@ async function handleCredentialPrompt({ body = {} }: RouteHandlerArgs) {
|
|
|
80
83
|
return { ok: false, error: reason };
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
const persisted = await persistPromptedCredential({
|
|
87
|
+
service: validated.service,
|
|
88
|
+
field: validated.field,
|
|
89
|
+
value: result.value,
|
|
90
|
+
delivery: result.delivery,
|
|
91
|
+
policy: {
|
|
92
|
+
allowedTools: validated.allowedTools,
|
|
93
|
+
allowedDomains: validated.allowedDomains,
|
|
94
|
+
usageDescription: validated.usageDescription,
|
|
95
|
+
injectionTemplates: validated.injectionTemplates,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (persisted.outcome === "error") {
|
|
100
|
+
return { ok: false, error: persisted.message };
|
|
87
101
|
}
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
if (persisted.outcome === "transient") {
|
|
104
|
+
return {
|
|
105
|
+
ok: true,
|
|
106
|
+
service: validated.service,
|
|
107
|
+
field: validated.field,
|
|
108
|
+
message: `One-time credential provided for ${validated.service}/${validated.field}. The value was not saved and will be consumed by the next operation.`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const slackStatus = persisted.slackChannel
|
|
113
|
+
? formatSlackChannelStatus(persisted.slackChannel).trim()
|
|
114
|
+
: "";
|
|
95
115
|
|
|
96
116
|
return {
|
|
97
117
|
ok: true,
|
|
98
118
|
service: validated.service,
|
|
99
119
|
field: validated.field,
|
|
120
|
+
message: slackStatus.length > 0 ? slackStatus : undefined,
|
|
100
121
|
};
|
|
101
122
|
}
|
|
102
123
|
|
|
@@ -124,6 +145,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
124
145
|
error: z.string().optional(),
|
|
125
146
|
service: z.string().optional(),
|
|
126
147
|
field: z.string().optional(),
|
|
148
|
+
message: z.string().optional(),
|
|
127
149
|
}),
|
|
128
150
|
},
|
|
129
151
|
];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caching layer for the empty-state (new-chat) greeting generated via the
|
|
3
|
+
* `POST /v1/btw` side-chain with `conversationKey: "greeting"`.
|
|
4
|
+
*
|
|
5
|
+
* Stores a single greeting string with a configurable TTL
|
|
6
|
+
* (`ui.emptyStateGreetingCacheTtlMs`, default 4h). A TTL of `0` (or less)
|
|
7
|
+
* disables caching entirely — reads always miss and writes are skipped — so
|
|
8
|
+
* the greeting regenerates on every request. This is the knob a workspace
|
|
9
|
+
* sets to always receive a fresh greeting.
|
|
10
|
+
*
|
|
11
|
+
* Storage uses the existing `memory_checkpoints` table (simple key-value
|
|
12
|
+
* store), mirroring {@link ./identity-intro-cache.ts}.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { getConfig } from "../../config/loader.js";
|
|
16
|
+
import {
|
|
17
|
+
getMemoryCheckpoint,
|
|
18
|
+
setMemoryCheckpoint,
|
|
19
|
+
} from "../../memory/checkpoints.js";
|
|
20
|
+
|
|
21
|
+
const CHECKPOINT_KEY_TEXT = "empty_state:greeting:text";
|
|
22
|
+
const CHECKPOINT_KEY_TIMESTAMP = "empty_state:greeting:cached_at";
|
|
23
|
+
|
|
24
|
+
function cacheTtlMs(): number {
|
|
25
|
+
return getConfig().ui.emptyStateGreetingCacheTtlMs;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Return the cached greeting if present and within the configured TTL.
|
|
30
|
+
* Returns `null` when caching is disabled (TTL <= 0), the cache is empty,
|
|
31
|
+
* or the entry has expired.
|
|
32
|
+
*/
|
|
33
|
+
export function getCachedEmptyStateGreeting(): string | null {
|
|
34
|
+
const ttl = cacheTtlMs();
|
|
35
|
+
if (ttl <= 0) return null; // caching disabled — always regenerate
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const text = getMemoryCheckpoint(CHECKPOINT_KEY_TEXT);
|
|
39
|
+
const timestampStr = getMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP);
|
|
40
|
+
if (!text || !timestampStr) return null;
|
|
41
|
+
|
|
42
|
+
const cachedAt = Number(timestampStr);
|
|
43
|
+
if (Number.isNaN(cachedAt) || Date.now() - cachedAt > ttl) return null;
|
|
44
|
+
|
|
45
|
+
return text;
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Store a freshly generated greeting along with the current timestamp.
|
|
53
|
+
* No-ops when caching is disabled (TTL <= 0) so a zero-TTL workspace never
|
|
54
|
+
* writes a stale entry.
|
|
55
|
+
*/
|
|
56
|
+
export function setCachedEmptyStateGreeting(text: string): void {
|
|
57
|
+
if (cacheTtlMs() <= 0) return; // caching disabled — skip write
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_TEXT, text);
|
|
61
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP, String(Date.now()));
|
|
62
|
+
} catch {
|
|
63
|
+
// Cache write failure is non-fatal — next request will regenerate.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -25,6 +25,13 @@ import { getLogger } from "../../util/logger.js";
|
|
|
25
25
|
import { getWorkspacePromptPath } from "../../util/platform.js";
|
|
26
26
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
27
27
|
import { BadRequestError, InternalError } from "./errors.js";
|
|
28
|
+
import {
|
|
29
|
+
paginateRuns,
|
|
30
|
+
parseRunsBeforeCursor,
|
|
31
|
+
parseRunsLimit,
|
|
32
|
+
RUNS_NEXT_CURSOR_SCHEMA,
|
|
33
|
+
RUNS_PAGINATION_QUERY_PARAMS,
|
|
34
|
+
} from "./runs-pagination.js";
|
|
28
35
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
29
36
|
|
|
30
37
|
const log = getLogger("heartbeat-routes");
|
|
@@ -34,15 +41,18 @@ const log = getLogger("heartbeat-routes");
|
|
|
34
41
|
// ---------------------------------------------------------------------------
|
|
35
42
|
|
|
36
43
|
function handleListRuns(queryParams: Record<string, string>) {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
? Math.min(Math.max(Math.floor(rawLimit), 1), 100)
|
|
40
|
-
: 20;
|
|
44
|
+
const limit = parseRunsLimit(queryParams, 20);
|
|
45
|
+
const before = parseRunsBeforeCursor(queryParams);
|
|
41
46
|
|
|
42
|
-
const
|
|
47
|
+
const { rows, nextCursor } = paginateRuns(
|
|
48
|
+
listHeartbeatRuns(limit + 1, before),
|
|
49
|
+
limit,
|
|
50
|
+
(r) => r.scheduledFor,
|
|
51
|
+
);
|
|
43
52
|
const now = Date.now();
|
|
44
53
|
return {
|
|
45
|
-
|
|
54
|
+
nextCursor,
|
|
55
|
+
runs: rows.map((r) => {
|
|
46
56
|
const conversation = r.conversationId
|
|
47
57
|
? getConversation(r.conversationId)
|
|
48
58
|
: null;
|
|
@@ -113,13 +123,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
113
123
|
summary: "List heartbeat runs",
|
|
114
124
|
description: "Return recent heartbeat conversation runs.",
|
|
115
125
|
tags: ["heartbeat"],
|
|
116
|
-
queryParams:
|
|
117
|
-
{
|
|
118
|
-
name: "limit",
|
|
119
|
-
schema: { type: "integer" },
|
|
120
|
-
description: "Max runs to return (default 20, max 100)",
|
|
121
|
-
},
|
|
122
|
-
],
|
|
126
|
+
queryParams: RUNS_PAGINATION_QUERY_PARAMS(20),
|
|
123
127
|
responseBody: z.object({
|
|
124
128
|
runs: z
|
|
125
129
|
.array(
|
|
@@ -140,6 +144,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
140
144
|
}),
|
|
141
145
|
)
|
|
142
146
|
.describe("Heartbeat run records"),
|
|
147
|
+
nextCursor: RUNS_NEXT_CURSOR_SCHEMA,
|
|
143
148
|
}),
|
|
144
149
|
handler: ({ queryParams }: RouteHandlerArgs) =>
|
|
145
150
|
handleListRuns(queryParams ?? {}),
|
|
@@ -2,6 +2,10 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
import { getConfig } from "../../config/loader.js";
|
|
4
4
|
import { resolveImageGenCredentials } from "../../media/image-credentials.js";
|
|
5
|
+
import {
|
|
6
|
+
describeImageModels,
|
|
7
|
+
resolveImageModel,
|
|
8
|
+
} from "../../media/image-models.js";
|
|
5
9
|
import {
|
|
6
10
|
generateImage,
|
|
7
11
|
mapImageGenError,
|
|
@@ -77,8 +81,22 @@ async function handleImageGenerationGenerate(
|
|
|
77
81
|
const config = getConfig();
|
|
78
82
|
const svc = config.services["image-generation"];
|
|
79
83
|
|
|
84
|
+
// Resolve tier aliases (fast, quality, openai) to concrete model IDs via
|
|
85
|
+
// the registry; reject unknown values with the current catalog so the
|
|
86
|
+
// error is self-describing rather than a stale enum.
|
|
87
|
+
let resolvedModel = model as string | undefined;
|
|
88
|
+
if (typeof resolvedModel === "string" && resolvedModel) {
|
|
89
|
+
const entry = resolveImageModel(resolvedModel);
|
|
90
|
+
if (!entry) {
|
|
91
|
+
throw new BadRequestError(
|
|
92
|
+
`Unknown model "${resolvedModel}". Available models and aliases:\n${describeImageModels()}`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
resolvedModel = entry.id;
|
|
96
|
+
}
|
|
97
|
+
|
|
80
98
|
// Derive provider from explicit model override when supplied
|
|
81
|
-
const provider = providerForModel(
|
|
99
|
+
const provider = providerForModel(resolvedModel, svc.provider);
|
|
82
100
|
|
|
83
101
|
// Resolve credentials
|
|
84
102
|
const { credentials, errorHint } = await resolveImageGenCredentials({
|
|
@@ -103,7 +121,7 @@ async function handleImageGenerationGenerate(
|
|
|
103
121
|
sourceImages: sourceImages as
|
|
104
122
|
| Array<{ mimeType: string; dataBase64: string }>
|
|
105
123
|
| undefined,
|
|
106
|
-
model:
|
|
124
|
+
model: resolvedModel ?? svc.model,
|
|
107
125
|
variants: clampedVariants,
|
|
108
126
|
});
|
|
109
127
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* verification, guardian action answers, approval interception, and
|
|
5
5
|
* invite token redemption.
|
|
6
6
|
*/
|
|
7
|
+
import type { SourceMetadata } from "@vellumai/gateway-client";
|
|
8
|
+
|
|
7
9
|
import {
|
|
8
10
|
attachmentsToContentBlocks,
|
|
9
11
|
type MessageAttachmentInput,
|
|
@@ -127,16 +129,16 @@ function trimMetadataString(
|
|
|
127
129
|
|
|
128
130
|
function parseSlackActorTimezoneMetadata(
|
|
129
131
|
sourceChannel: string,
|
|
130
|
-
metadata:
|
|
132
|
+
metadata: SourceMetadata | undefined,
|
|
131
133
|
): SlackActorTimezoneMetadata | undefined {
|
|
132
134
|
if (sourceChannel !== "slack") return undefined;
|
|
133
135
|
|
|
134
|
-
const timezone =
|
|
135
|
-
const timezoneLabel =
|
|
136
|
-
const rawOffset = metadata?.timezoneOffsetSeconds;
|
|
136
|
+
const timezone = metadata?.timezone?.trim() || undefined;
|
|
137
|
+
const timezoneLabel = metadata?.timezoneLabel?.trim() || undefined;
|
|
137
138
|
const timezoneOffsetSeconds =
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
metadata?.timezoneOffsetSeconds != null &&
|
|
140
|
+
Number.isFinite(metadata.timezoneOffsetSeconds)
|
|
141
|
+
? metadata.timezoneOffsetSeconds
|
|
140
142
|
: undefined;
|
|
141
143
|
|
|
142
144
|
if (
|
|
@@ -193,17 +195,16 @@ function resolveSlackTranscriptTimestampTimezone(
|
|
|
193
195
|
|
|
194
196
|
function resolveInboundClientTimezone(params: {
|
|
195
197
|
bodyClientTimezone?: unknown;
|
|
196
|
-
sourceMetadata?:
|
|
198
|
+
sourceMetadata?: SourceMetadata;
|
|
197
199
|
conversationId: string;
|
|
198
200
|
}): string | undefined {
|
|
199
201
|
const bodyClientTimezone =
|
|
200
202
|
typeof params.bodyClientTimezone === "string"
|
|
201
203
|
? canonicalizeTimeZone(params.bodyClientTimezone)
|
|
202
204
|
: undefined;
|
|
203
|
-
const metadataClientTimezone =
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
: undefined;
|
|
205
|
+
const metadataClientTimezone = params.sourceMetadata?.clientTimezone
|
|
206
|
+
? canonicalizeTimeZone(params.sourceMetadata.clientTimezone)
|
|
207
|
+
: undefined;
|
|
207
208
|
return (
|
|
208
209
|
bodyClientTimezone ??
|
|
209
210
|
metadataClientTimezone ??
|
|
@@ -248,7 +249,7 @@ export async function handleChannelInbound({
|
|
|
248
249
|
attachmentIds?: string[];
|
|
249
250
|
actorExternalId?: string;
|
|
250
251
|
actorUsername?: string;
|
|
251
|
-
sourceMetadata?:
|
|
252
|
+
sourceMetadata?: SourceMetadata;
|
|
252
253
|
replyCallbackUrl?: string;
|
|
253
254
|
callbackQueryId?: string;
|
|
254
255
|
callbackData?: string;
|