@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +6 -6
- package/bun.lock +2 -2
- package/docs/activation-funnel-telemetry.md +310 -0
- package/examples/plugins/echo/README.md +61 -60
- package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
- package/examples/plugins/echo/hooks/stop.ts +16 -0
- package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
- package/examples/plugins/echo/package.json +1 -2
- package/examples/plugins/echo/src/emit.ts +19 -0
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
- package/openapi.yaml +263 -121
- package/package.json +2 -2
- package/src/__tests__/activation-early-marking.test.ts +120 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
- package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
- package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
- package/src/__tests__/agent-loop-thinking.test.ts +36 -20
- package/src/__tests__/agent-loop.test.ts +441 -96
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
- package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
- package/src/__tests__/anthropic-provider.test.ts +23 -8
- package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +132 -0
- package/src/__tests__/approval-cascade.test.ts +6 -5
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +146 -0
- package/src/__tests__/compaction-events.test.ts +7 -7
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
- package/src/__tests__/context-overflow-reducer.test.ts +265 -125
- package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
- package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
- package/src/__tests__/conversation-agent-loop.test.ts +342 -623
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
- package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-media-retry.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
- package/src/__tests__/conversation-process-callsite.test.ts +15 -15
- package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
- package/src/__tests__/conversation-queue.test.ts +10 -10
- package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
- package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
- package/src/__tests__/conversation-slash-queue.test.ts +7 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
- package/src/__tests__/conversation-speed-override.test.ts +11 -10
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
- package/src/__tests__/conversation-undo.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
- package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +36 -0
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/empty-response-hook.test.ts +1 -1
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +17 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/history-repair-hook.test.ts +5 -1
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-app-control-routes.test.ts +1 -1
- package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
- package/src/__tests__/inference-profile-reaper.test.ts +62 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
- package/src/__tests__/injector-background-turn.test.ts +13 -23
- package/src/__tests__/injector-chain.test.ts +268 -44
- package/src/__tests__/injector-disk-pressure.test.ts +210 -52
- package/src/__tests__/injector-document-comments.test.ts +97 -114
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-v3-suppression.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
- package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
- package/src/__tests__/llm-resolver.test.ts +73 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
- package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
- package/src/__tests__/persist-unsendable-image.test.ts +97 -1
- package/src/__tests__/plugin-api-shim.test.ts +6 -9
- package/src/__tests__/plugin-bootstrap.test.ts +91 -81
- package/src/__tests__/plugin-registry.test.ts +3 -49
- package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -70
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
- package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
- package/src/__tests__/published-app-updater.test.ts +138 -0
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
- package/src/__tests__/steer-tool-repair.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-detail.test.ts +25 -7
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +1 -3
- package/src/__tests__/subagent-notify-parent.test.ts +1 -3
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +5 -1
- package/src/__tests__/tool-error-hook.test.ts +1 -1
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +54 -286
- package/src/__tests__/web-fetch.test.ts +45 -0
- package/src/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +280 -0
- package/src/acp/auto-install.ts +232 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/prepare-agent-env.ts +80 -27
- package/src/acp/resolve-agent.test.ts +188 -28
- package/src/acp/resolve-agent.ts +119 -42
- package/src/acp/resume-hint.ts +23 -0
- package/src/acp/session-manager.ts +507 -73
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +403 -251
- package/src/api/responses/conversation-message.ts +22 -2
- package/src/api/responses/memory-v3-selection-log.ts +19 -10
- package/src/approvals/guardian-request-resolvers.ts +27 -1
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
- package/src/cli/commands/memory-v3.ts +57 -199
- package/src/cli/commands/plugins.ts +43 -37
- package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
- package/src/cli/lib/install-from-github.ts +797 -60
- package/src/cli/lib/plugin-catalog-cache.ts +84 -0
- package/src/cli/lib/plugin-details.ts +416 -0
- package/src/cli/lib/plugin-marketplace.ts +215 -0
- package/src/cli/lib/search-plugins.ts +201 -29
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +10 -0
- package/src/config/acp-defaults.ts +9 -3
- package/src/config/acp-schema.ts +1 -7
- package/src/config/bundled-skills/acp/SKILL.md +80 -41
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
- package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-tool-registry.ts +4 -0
- package/src/config/call-site-defaults.ts +0 -3
- package/src/config/feature-flag-registry.json +10 -16
- package/src/config/llm-resolver.ts +39 -7
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
- package/src/config/schemas/call-site-catalog.ts +0 -21
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +17 -3
- package/src/config/schemas/memory-v3.ts +58 -8
- package/src/config/seed-inference-profiles.ts +18 -0
- package/src/context/compactor.ts +22 -4
- package/src/context/post-turn-tool-result-truncation.ts +39 -1
- package/src/context/strip-injections.ts +8 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
- package/src/daemon/conversation-agent-loop.ts +308 -1297
- package/src/daemon/conversation-error.ts +31 -4
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +11 -255
- package/src/daemon/conversation-media-retry.ts +19 -6
- package/src/daemon/conversation-messaging.ts +17 -0
- package/src/daemon/conversation-process.ts +22 -141
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +361 -393
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +165 -11
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +444 -62
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/external-plugins-bootstrap.ts +36 -46
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-proxy-preactivation.ts +1 -3
- package/src/daemon/lifecycle.ts +21 -7
- package/src/daemon/persist-unsendable-image.ts +62 -25
- package/src/daemon/process-message.ts +1 -1
- package/src/daemon/server.ts +2 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/wake-conversation-ops.ts +269 -0
- package/src/embedded/plugin-api.ts +2 -2
- package/src/export/__tests__/transcript-formatter.test.ts +5 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
- package/src/heartbeat/heartbeat-run-store.ts +23 -1
- package/src/heartbeat/heartbeat-service.ts +26 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
- package/src/ipc/skill-routes/memory.ts +4 -2
- package/src/memory/__tests__/activation-session-store.test.ts +41 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
- package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
- package/src/memory/activation-session-store.ts +43 -0
- package/src/memory/conversation-crud.ts +29 -19
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/db-init.ts +6 -0
- package/src/memory/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
- package/src/memory/jobs-worker.ts +25 -1
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
- package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/onboarding-events-store.ts +66 -18
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
- package/src/memory/v2/__tests__/page-store.test.ts +22 -0
- package/src/memory/v2/consolidation-job.ts +2 -63
- package/src/memory/v2/types.ts +5 -0
- package/src/messaging/providers/telegram-bot/api.ts +14 -5
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +9 -2
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +40 -11
- package/src/plugin-api/types.ts +108 -0
- package/src/plugins/defaults/compaction/compact.ts +106 -0
- package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/plugins/defaults/compaction/manager-store.ts +57 -0
- package/src/plugins/defaults/compaction/package.json +1 -2
- package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
- package/src/plugins/defaults/empty-response/package.json +0 -1
- package/src/plugins/defaults/history-repair/package.json +0 -1
- package/src/plugins/defaults/index.ts +156 -26
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
- package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
- package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
- package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
- package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
- package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
- package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
- package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
- package/src/plugins/defaults/title-generate/package.json +0 -1
- package/src/plugins/defaults/tool-error/package.json +0 -1
- package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
- package/src/plugins/external-api.ts +12 -2
- package/src/plugins/pipeline.ts +6 -293
- package/src/plugins/registry.ts +9 -37
- package/src/plugins/types.ts +76 -381
- package/src/plugins/user-loader.ts +30 -127
- package/src/prompts/__tests__/system-prompt.test.ts +6 -0
- package/src/prompts/system-prompt.ts +61 -10
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
- package/src/providers/anthropic/client.ts +9 -10
- package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
- package/src/providers/inference/logit-bias.ts +55 -0
- package/src/providers/model-catalog.ts +34 -0
- package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -1
- package/src/providers/retry.ts +22 -0
- package/src/providers/types.ts +6 -0
- package/src/runtime/__tests__/agent-wake.test.ts +555 -691
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +108 -209
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
- package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
- package/src/runtime/routes/acp-routes.test.ts +185 -32
- package/src/runtime/routes/acp-routes.ts +328 -30
- package/src/runtime/routes/app-management-routes.ts +3 -0
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +30 -2
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-cu-routes.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +18 -3
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
- package/src/runtime/routes/memory-v3-routes.ts +65 -305
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +337 -35
- package/src/runtime/routes/stt-routes.ts +45 -12
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/routes/workspace-routes.ts +50 -15
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/services/published-app-updater.ts +30 -8
- package/src/signals/cancel.ts +2 -4
- package/src/subagent/manager.ts +21 -5
- package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
- package/src/telemetry/activation-funnel.ts +167 -0
- package/src/telemetry/types.ts +13 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
- package/src/telemetry/usage-telemetry-reporter.ts +26 -1
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +9 -19
- package/src/tools/acp/list-agents.ts +3 -15
- package/src/tools/acp/spawn.test.ts +173 -202
- package/src/tools/acp/spawn.ts +37 -172
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +166 -50
- package/src/tools/browser/browser-execution.ts +12 -2
- package/src/tools/filesystem/write.ts +34 -0
- package/src/tools/network/web-fetch.ts +65 -24
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/ui-surface/definitions.ts +32 -5
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
- package/docs/plugins.md +0 -832
- package/examples/plugins/echo/register.ts +0 -143
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
- package/src/__tests__/compaction-pipeline.test.ts +0 -210
- package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
- package/src/__tests__/pipeline-runner.test.ts +0 -554
- package/src/daemon/wake-target-adapter.ts +0 -253
- package/src/memory/v3/__tests__/assign.test.ts +0 -242
- package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
- package/src/memory/v3/__tests__/core.test.ts +0 -39
- package/src/memory/v3/__tests__/health.test.ts +0 -219
- package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
- package/src/memory/v3/__tests__/needle.test.ts +0 -107
- package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
- package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
- package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
- package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
- package/src/memory/v3/__tests__/router.test.ts +0 -332
- package/src/memory/v3/__tests__/selector.test.ts +0 -470
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
- package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
- package/src/memory/v3/__tests__/tree.test.ts +0 -192
- package/src/memory/v3/assign.ts +0 -268
- package/src/memory/v3/capabilities.ts +0 -124
- package/src/memory/v3/core.ts +0 -26
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +0 -314
- package/src/memory/v3/needle.ts +0 -115
- package/src/memory/v3/orchestrate.ts +0 -126
- package/src/memory/v3/page-content.ts +0 -34
- package/src/memory/v3/provider-blocks.ts +0 -26
- package/src/memory/v3/reconcile.ts +0 -523
- package/src/memory/v3/router.ts +0 -190
- package/src/memory/v3/selection-log-store.ts +0 -84
- package/src/memory/v3/selector.ts +0 -226
- package/src/memory/v3/shadow-plugin.ts +0 -411
- package/src/memory/v3/snapshot.ts +0 -209
- package/src/memory/v3/tree.ts +0 -174
- package/src/memory/v3/types.ts +0 -59
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
- package/src/plugins/defaults/circuit-breaker/package.json +0 -15
- package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
- package/src/plugins/defaults/compaction/register.ts +0 -35
- package/src/plugins/defaults/compaction/terminal.ts +0 -73
- package/src/plugins/defaults/empty-response/register.ts +0 -23
- package/src/plugins/defaults/history-repair/register.ts +0 -24
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
- package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
- package/src/plugins/defaults/overflow-reduce/package.json +0 -15
- package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
- package/src/plugins/defaults/title-generate/register.ts +0 -35
- package/src/plugins/defaults/tool-error/register.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
- package/src/proactive-artifact/aux-message-injector.ts +0 -97
- package/src/proactive-artifact/decision.test.ts +0 -226
- package/src/proactive-artifact/decision.ts +0 -165
- package/src/proactive-artifact/index.ts +0 -7
- package/src/proactive-artifact/job.test.ts +0 -962
- package/src/proactive-artifact/job.ts +0 -372
- package/src/proactive-artifact/message-copy.ts +0 -58
- package/src/proactive-artifact/trigger-state.test.ts +0 -286
- package/src/proactive-artifact/trigger-state.ts +0 -123
- package/src/util/map-limit.ts +0 -27
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"properties": {
|
|
12
12
|
"name": {
|
|
13
13
|
"type": "string",
|
|
14
|
-
"description": "
|
|
14
|
+
"description": "Optional name of the app. When omitted, defaults to the preview card title (or \"New App\" if there is none); rename later via app_update."
|
|
15
15
|
},
|
|
16
16
|
"description": {
|
|
17
17
|
"type": "string",
|
|
@@ -74,13 +74,65 @@
|
|
|
74
74
|
"change_summary": {
|
|
75
75
|
"type": "string",
|
|
76
76
|
"description": "Short summary of what changed, using git conventional commit format (e.g. 'feat: add coin flip app', 'fix: correct button alignment'). Used as the version history entry."
|
|
77
|
+
},
|
|
78
|
+
"icon": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "Lenient alias. Prefer preview.icon. An emoji or image URL passed here is folded into preview.icon automatically."
|
|
81
|
+
},
|
|
82
|
+
"html": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": "Lenient alias. Prefer source_files. Raw HTML passed here is folded into source_files['src/index.html'] automatically."
|
|
85
|
+
},
|
|
86
|
+
"pages": {
|
|
87
|
+
"description": "Retired. Multi-page apps route inside the Preact app under src/components/. Passing this returns a guidance error."
|
|
77
88
|
}
|
|
78
89
|
},
|
|
79
|
-
"required": [
|
|
90
|
+
"required": []
|
|
80
91
|
},
|
|
81
92
|
"executor": "tools/app-create.ts",
|
|
82
93
|
"execution_target": "host"
|
|
83
94
|
},
|
|
95
|
+
{
|
|
96
|
+
"name": "app_update",
|
|
97
|
+
"description": "Update an existing app: change its name, description, or schema, and/or rewrite source files, then recompile. Use this to iterate on an app you already created instead of calling app_create again (which would make a duplicate). Resolve the app_id with app_list first if you don't have it.",
|
|
98
|
+
"category": "apps",
|
|
99
|
+
"risk": "low",
|
|
100
|
+
"input_schema": {
|
|
101
|
+
"type": "object",
|
|
102
|
+
"properties": {
|
|
103
|
+
"app_id": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"description": "The ID of the app to update"
|
|
106
|
+
},
|
|
107
|
+
"name": {
|
|
108
|
+
"type": "string",
|
|
109
|
+
"description": "New name for the app. Omit to leave the name unchanged."
|
|
110
|
+
},
|
|
111
|
+
"description": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "New description for the app. Omit to leave the description unchanged."
|
|
114
|
+
},
|
|
115
|
+
"schema_json": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "New JSON schema for the app data structure. Omit to leave the schema unchanged."
|
|
118
|
+
},
|
|
119
|
+
"source_files": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"description": "Map of relative file paths to file contents to write under the app directory (e.g. 'src/main.tsx', 'src/components/App.tsx', 'src/styles.css'). Supply changed source here instead of separate file_write calls. The app is recompiled after writing.",
|
|
122
|
+
"additionalProperties": {
|
|
123
|
+
"type": "string"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"change_summary": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Short summary of what changed, using git conventional commit format (e.g. 'fix: correct totals', 'feat: add dark mode'). Used as the version history entry."
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"required": ["app_id"]
|
|
132
|
+
},
|
|
133
|
+
"executor": "tools/app-update.ts",
|
|
134
|
+
"execution_target": "host"
|
|
135
|
+
},
|
|
84
136
|
{
|
|
85
137
|
"name": "app_delete",
|
|
86
138
|
"description": "Delete a persistent app and all its records.",
|
|
@@ -150,6 +202,24 @@
|
|
|
150
202
|
},
|
|
151
203
|
"executor": "tools/app-generate-icon.ts",
|
|
152
204
|
"execution_target": "host"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"name": "app_list",
|
|
208
|
+
"description": "List the persistent apps the user has built, returning each app's app_id, name, description, and timestamps (most recently updated first). Pass `query` to resolve an app the user mentions by name to its app_id before calling app_open. Use this whenever the user refers to an existing app and you don't already have its app_id in context.",
|
|
209
|
+
"category": "apps",
|
|
210
|
+
"risk": "low",
|
|
211
|
+
"input_schema": {
|
|
212
|
+
"type": "object",
|
|
213
|
+
"properties": {
|
|
214
|
+
"query": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"description": "Optional name (or partial name) the user mentioned. When provided, only matching apps are returned: an exact case-insensitive name match if one exists, otherwise substring matches in either direction (e.g. 'habit tracker' resolves 'Habit Tracker'). Omit to list all apps."
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"required": []
|
|
220
|
+
},
|
|
221
|
+
"executor": "tools/app-list.ts",
|
|
222
|
+
"execution_target": "host"
|
|
153
223
|
}
|
|
154
224
|
]
|
|
155
225
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Design System
|
|
2
|
+
|
|
3
|
+
A design system CSS is auto-injected inside a `@layer`, so your styles always take priority. It provides element defaults and automatic light/dark mode switching via `prefers-color-scheme`.
|
|
4
|
+
|
|
5
|
+
**Use `--v-*` variables and `.v-*` classes** — they handle light/dark mode automatically. No manual dark mode CSS needed.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Design tokens
|
|
10
|
+
|
|
11
|
+
| Category | Tokens |
|
|
12
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| **Backgrounds** | `--v-bg`, `--v-surface`, `--v-surface-border` |
|
|
14
|
+
| **Text** | `--v-text`, `--v-text-secondary`, `--v-text-muted` |
|
|
15
|
+
| **Accent** | `--v-accent`, `--v-accent-hover` |
|
|
16
|
+
| **Status** | `--v-success`, `--v-danger`, `--v-warning` |
|
|
17
|
+
| **Spacing** | `--v-spacing-xxs` (2px) / `-xs` (4px) / `-sm` (8px) / `-md` (12px) / `-lg` (16px) / `-xl` (24px) / `-xxl` (32px) / `-xxxl` (48px) |
|
|
18
|
+
| **Radius** | `--v-radius-xs` (2px) / `-sm` (4px) / `-md` (8px) / `-lg` (12px) / `-xl` (16px) / `-pill` (999px) |
|
|
19
|
+
| **Shadows** | `--v-shadow-sm`, `--v-shadow-md`, `--v-shadow-lg` |
|
|
20
|
+
| **Typography** | `--v-font-family`, `--v-font-mono`, `--v-font-size-xs` (10px) / `-sm` (11px) / `-base` (14px) / `-lg` (17px) / `-xl` (22px) / `-2xl` (26px), `--v-line-height` |
|
|
21
|
+
| **Animation** | `--v-duration-fast` (0.15s) / `-standard` (0.25s) / `-slow` (0.4s) |
|
|
22
|
+
| **Palettes** | `--v-slate-{950..50}`, `--v-emerald-*`, `--v-violet-*`, `--v-indigo-*`, `--v-rose-*`, `--v-amber-*` |
|
|
23
|
+
| **Constant** | `--v-aux-white` (always `#FFFFFF` in both modes — use for text on filled/accent backgrounds) |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Utility classes
|
|
28
|
+
|
|
29
|
+
`.v-button` (`.secondary` / `.danger` / `.ghost`), `.v-card`, `.v-list` / `.v-list-item`, `.v-badge` (`.success` / `.warning` / `.danger`), `.v-input-row`, `.v-empty-state`, `.v-toggle`.
|
|
30
|
+
|
|
31
|
+
⚠️ **Never hardcode `color: white` or `color: #fff`.** Use `var(--v-aux-white)` for text on filled/accent backgrounds, or `var(--v-text)` / `var(--v-text-secondary)` for text on surface backgrounds. Hardcoded white causes invisible text on light surfaces.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Custom themes
|
|
36
|
+
|
|
37
|
+
When the user wants a specific branded look, write complete CSS with hardcoded colors and `@media (prefers-color-scheme: dark)` for dark variants. Don't mix `--v-*` auto-switching variables with hardcoded colors in the same element.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Theme detection in JavaScript
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
console.log(window.vellum.theme.mode); // 'light' or 'dark'
|
|
45
|
+
window.addEventListener("vellum-theme-change", (e) => {
|
|
46
|
+
console.log("Theme:", e.detail.mode);
|
|
47
|
+
});
|
|
48
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Responsive Baseline & Mobile-First Mode
|
|
2
|
+
|
|
3
|
+
Every app must work across phone (~360px) to desktop (~1400px+).
|
|
4
|
+
|
|
5
|
+
## Mode selection
|
|
6
|
+
|
|
7
|
+
The conversation context's `<turn_context>` block carries an `interface:` field.
|
|
8
|
+
|
|
9
|
+
**If `interface: ios`** (or any future mobile-web / android identifier):
|
|
10
|
+
→ Mobile-first build. Design the narrow viewport first, enhance upward.
|
|
11
|
+
|
|
12
|
+
**If `interface: macos` or `web`**:
|
|
13
|
+
→ Desktop-first build. Design larger composition first; narrow fallback still meets the universal baseline below.
|
|
14
|
+
|
|
15
|
+
**If field is absent or ambiguous**:
|
|
16
|
+
→ Default to desktop-first unless the request implies phone use ("for my iPhone", "a tap-tracker I'll use on the go").
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Universal baseline (every build, regardless of interface)
|
|
21
|
+
|
|
22
|
+
### Viewport & safe areas
|
|
23
|
+
|
|
24
|
+
- Set viewport meta: `<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">`. Never set `user-scalable=no` — it blocks accessibility zoom.
|
|
25
|
+
- Pad the root container with `env(safe-area-inset-*)` so content clears the notch: `padding-top: max(var(--v-spacing-lg), env(safe-area-inset-top))`, mirrored for `-bottom` / `-left` / `-right`.
|
|
26
|
+
- Use `100dvh` (dynamic viewport height), not `100vh`, for full-height containers.
|
|
27
|
+
|
|
28
|
+
### Form controls
|
|
29
|
+
|
|
30
|
+
- `<input>`, `<textarea>`, `<select>` must be `font-size: 16px` or larger, or iOS Safari will zoom on focus and break the layout. This applies to every build.
|
|
31
|
+
- Add `inputmode` to text fields with structured input: `numeric` for integers, `decimal` for amounts, `email`, `tel`, `url`.
|
|
32
|
+
|
|
33
|
+
### Touch & hover
|
|
34
|
+
|
|
35
|
+
- Interactive elements must be ≥44×44pt. `.v-button` already meets this; for custom controls, set `min-height: 44px` explicitly.
|
|
36
|
+
- Gate hover affordances behind `@media (hover: hover)` so they don't stick on touch devices.
|
|
37
|
+
- Disable text selection on app chrome with `user-select: none; -webkit-user-select: none`.
|
|
38
|
+
|
|
39
|
+
### Layout fluidity
|
|
40
|
+
|
|
41
|
+
- Use fluid widths only. No fixed-pixel layouts. Prefer `%`, `fr`, `minmax`, `clamp()` over `px` on container widths.
|
|
42
|
+
- At narrow widths, collapse tables into stacked cards with labels and values arranged vertically.
|
|
43
|
+
- Size `vellum.widgets.*` chart containers in `vw` / `%`, not fixed `px`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Mobile-first priorities (`interface: ios`)
|
|
48
|
+
|
|
49
|
+
- Default body text to `--v-font-size-lg` (17px), not `--v-font-size-base` (14px).
|
|
50
|
+
- Bump default vertical rhythm one step (e.g. `--v-spacing-md` → `--v-spacing-lg`).
|
|
51
|
+
- One column as the default, not a fallback. Opt into multi-column only above `@media (min-width: 720px)`.
|
|
52
|
+
- Bottom-anchor the primary action: `position: sticky; bottom: env(safe-area-inset-bottom)`.
|
|
53
|
+
- Replace side modals and popovers with bottom sheets.
|
|
54
|
+
|
|
55
|
+
## Desktop-first priorities (`interface: macos` / `web`)
|
|
56
|
+
|
|
57
|
+
Multi-column composition, hover-rich affordances, denser information, side modals, inline primary actions. The universal baseline above is still the floor — narrow view must still work.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Presentation Slide Design
|
|
2
|
+
|
|
3
|
+
Slides are a different domain from apps. Skip app-specific patterns (contextual headers, search/filter, toast notifications, form validation, custom routes). Slides are static content — build navigation and layouts with custom HTML/CSS.
|
|
4
|
+
|
|
5
|
+
## Key principles
|
|
6
|
+
|
|
7
|
+
- One idea per slide — understood in 3 seconds
|
|
8
|
+
- Layout variety — 3+ different types per deck, never consecutive same-type
|
|
9
|
+
- 8 layout types: Title, Stats, Bullets, Quote, Comparison, Timeline, Visual/Immersive, Closing/CTA
|
|
10
|
+
- Bold backgrounds — dark, gradient, or strongly tinted
|
|
11
|
+
- Max 6 bullets per slide, max 3 sentences body text
|
|
12
|
+
- Never go below 15px for any visible text
|
|
13
|
+
|
|
14
|
+
## Navigation
|
|
15
|
+
|
|
16
|
+
Build slide navigation as your own component. Common patterns:
|
|
17
|
+
- Keyboard: `ArrowLeft` / `ArrowRight` / `Space` / `Escape`
|
|
18
|
+
- Click affordances at left/right edges
|
|
19
|
+
- Slide counter pill in a corner (e.g. `3 / 12`)
|
|
20
|
+
- Optional progress bar at the top
|
|
21
|
+
|
|
22
|
+
## Layout templates
|
|
23
|
+
|
|
24
|
+
- **Title** — Centered headline, optional subtitle, no body. Full-bleed background or gradient.
|
|
25
|
+
- **Stats** — One huge number, label below, supporting paragraph optional.
|
|
26
|
+
- **Bullets** — Heading + 3–6 short bullets. Avoid wall-of-text.
|
|
27
|
+
- **Quote** — Pull quote in large italic type, attribution below, contrasting background.
|
|
28
|
+
- **Comparison** — Two columns (before/after, us/them, problem/solution). Visual symmetry matters.
|
|
29
|
+
- **Timeline** — Horizontal or vertical sequence with dates and milestones.
|
|
30
|
+
- **Visual/Immersive** — Full-bleed image, gradient, or generated graphic with minimal text overlay.
|
|
31
|
+
- **Closing/CTA** — Headline + single call to action. Mirror the title slide aesthetic.
|
|
32
|
+
|
|
33
|
+
## What to avoid
|
|
34
|
+
|
|
35
|
+
- Generic Keynote / PowerPoint aesthetic (default white background, sans-serif body, bullet lists everywhere)
|
|
36
|
+
- Tiny text below 15px — slides are read across rooms
|
|
37
|
+
- Same layout type used 3+ times in a row — vary the rhythm
|
|
38
|
+
- Body paragraphs longer than 3 sentences — split into multiple slides
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as appStore from "../../../../memory/app-store.js";
|
|
2
|
+
import type {
|
|
3
|
+
ToolContext,
|
|
4
|
+
ToolExecutionResult,
|
|
5
|
+
} from "../../../../tools/types.js";
|
|
6
|
+
|
|
7
|
+
interface AppListEntry {
|
|
8
|
+
app_id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
updated_at: number;
|
|
12
|
+
created_at: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function toEntry(app: appStore.AppDefinition): AppListEntry {
|
|
16
|
+
return {
|
|
17
|
+
app_id: app.id,
|
|
18
|
+
name: app.name,
|
|
19
|
+
...(app.description ? { description: app.description } : {}),
|
|
20
|
+
updated_at: app.updatedAt,
|
|
21
|
+
created_at: app.createdAt,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function run(
|
|
26
|
+
input: Record<string, unknown>,
|
|
27
|
+
_context: ToolContext,
|
|
28
|
+
): Promise<ToolExecutionResult> {
|
|
29
|
+
const apps = appStore.listApps();
|
|
30
|
+
const entries = apps.map(toEntry);
|
|
31
|
+
|
|
32
|
+
const query =
|
|
33
|
+
typeof input.query === "string" ? input.query.trim().toLowerCase() : "";
|
|
34
|
+
|
|
35
|
+
if (!query) {
|
|
36
|
+
return {
|
|
37
|
+
content: JSON.stringify({ count: entries.length, apps: entries }),
|
|
38
|
+
isError: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Resolve the app the user mentioned by name. Prefer an exact (case-insensitive)
|
|
43
|
+
// name match, then fall back to substring matches in either direction so
|
|
44
|
+
// "habit tracker" resolves "Habit Tracker" and "my budget" resolves "Budget".
|
|
45
|
+
const exact = entries.filter((e) => e.name.toLowerCase() === query);
|
|
46
|
+
const matches =
|
|
47
|
+
exact.length > 0
|
|
48
|
+
? exact
|
|
49
|
+
: entries.filter((e) => {
|
|
50
|
+
const name = e.name.toLowerCase();
|
|
51
|
+
return name.includes(query) || query.includes(name);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
content: JSON.stringify({
|
|
56
|
+
query: input.query,
|
|
57
|
+
match_count: matches.length,
|
|
58
|
+
matches,
|
|
59
|
+
}),
|
|
60
|
+
isError: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { setAppCommitMessage } from "../../../../memory/app-git-service.js";
|
|
2
|
+
import * as appStore from "../../../../memory/app-store.js";
|
|
3
|
+
import type { AppUpdateInput } from "../../../../tools/apps/executors.js";
|
|
4
|
+
import { executeAppUpdate } from "../../../../tools/apps/executors.js";
|
|
5
|
+
import type {
|
|
6
|
+
ToolContext,
|
|
7
|
+
ToolExecutionResult,
|
|
8
|
+
} from "../../../../tools/types.js";
|
|
9
|
+
|
|
10
|
+
export async function run(
|
|
11
|
+
input: Record<string, unknown>,
|
|
12
|
+
context: ToolContext,
|
|
13
|
+
): Promise<ToolExecutionResult> {
|
|
14
|
+
if (typeof input.change_summary === "string" && input.change_summary.trim()) {
|
|
15
|
+
setAppCommitMessage(context.conversationId, input.change_summary.trim());
|
|
16
|
+
}
|
|
17
|
+
return executeAppUpdate(input as unknown as AppUpdateInput, appStore);
|
|
18
|
+
}
|
|
@@ -1,44 +1,37 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: document-editor
|
|
3
|
-
description:
|
|
3
|
+
description: Use whenever the user wants to write or draft an article, blog post, essay, report, or any long-form content. Creates the content in a rich text editor instead of dumping it in chat, so it can be streamed, reviewed, edited, and exported.
|
|
4
4
|
compatibility: "Designed for Vellum personal assistants"
|
|
5
5
|
metadata:
|
|
6
|
-
emoji: "
|
|
6
|
+
emoji: "✍️"
|
|
7
7
|
vellum:
|
|
8
|
-
display-name: "Document
|
|
8
|
+
display-name: "Document Writer"
|
|
9
9
|
activation-hints:
|
|
10
|
-
- "User asks to write, draft, or
|
|
11
|
-
- "
|
|
12
|
-
- "
|
|
10
|
+
- "User asks to write, draft, or compose an article, blog post, essay, report, story, or any long-form content — always create it in the document editor, not as a chat reply"
|
|
11
|
+
- "User wants written content they will iterate on, review, or export — use the editor instead of inline markdown"
|
|
12
|
+
- "A file attachment contains a draft or document the user wants to revise — open it in the editor"
|
|
13
|
+
avoid-when:
|
|
14
|
+
- "The user wants an interactive app, dashboard, calculator, game, or anything with state or data — use app-builder instead"
|
|
15
|
+
- "A one or two sentence answer is enough — just reply in chat"
|
|
13
16
|
---
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Write and edit long-form documents using the built-in rich text editor. Documents open in workspace mode with chat docked to the side. When a request is about writing prose (an article, blog post, report, essay, story, or similar), create it here rather than writing it into the chat response.
|
|
16
19
|
|
|
17
20
|
## Tools
|
|
18
21
|
|
|
19
|
-
- **
|
|
20
|
-
- **document_create** - Opens a new document editor with an optional title and initial Markdown content. Returns a `surface_id` for subsequent updates.
|
|
22
|
+
- **document_create** - Opens a new document editor with an optional title and initial Markdown content. Returns a `surface_id` for subsequent updates. This is the entry point for any new piece of writing.
|
|
21
23
|
- **document_update** - Updates content in an open document editor by `surface_id`. Supports `replace` (overwrite) and `append` (add to end) modes.
|
|
22
24
|
- **document_read** - Reads the current content of a document by `surface_id` when it belongs to the current conversation, or when the current actor is the guardian/local user. Use to verify content before editing.
|
|
23
|
-
- **document_list** - Lists documents. Without `query`, lists the current conversation's documents. With `query`, searches by title; guardian/local users can search across conversations, while other actors are scoped to the current conversation.
|
|
24
25
|
- **document_find** - Searches a document for text or regex patterns. Returns matching lines with line numbers, match positions, and matched text.
|
|
25
26
|
- **document_replace_text** - Targeted find-and-replace within a document. Supports literal and regex patterns (with backreferences). Optionally limit the number of replacements.
|
|
27
|
+
- **document_list** - Lists documents. Without `query`, lists the current conversation's documents. With `query`, searches by title; guardian/local users can search across conversations, while other actors are scoped to the current conversation.
|
|
28
|
+
- **document_open** - Opens an existing document in the editor panel by `surface_id`. Use this when a document exists but isn't visible in the editor — for example after the user switches devices, refreshes the page, or when the editor panel was closed. Fetches the document from storage and sends it to the client.
|
|
26
29
|
- **document_delete** - Deletes a document by `surface_id`. Use to clean up unwanted documents.
|
|
27
30
|
|
|
28
|
-
## Retrieving existing documents
|
|
29
|
-
|
|
30
|
-
When the user asks to see, open, or pull up a document:
|
|
31
|
-
|
|
32
|
-
1. Check the `<active_documents>` block in your context — it lists all documents in this conversation with their `surface_id` and title.
|
|
33
|
-
2. If the document is NOT in `<active_documents>`, call `document_list` with a `query` matching the document title. For guardian/local users, this searches across previous conversations and sessions.
|
|
34
|
-
3. Once you have the `surface_id`, call `document_open` to open the editor panel. This surfaces the editor on the client and returns document metadata (`surface_id`, `title`, `word_count`) — not the full content. If you need the actual document text, follow up with `document_read`.
|
|
35
|
-
|
|
36
|
-
**Never** search the filesystem, conversation history, or archives to find a document. Always use `document_list` with a `query`.
|
|
37
|
-
|
|
38
|
-
**If the user says they can't see a document you know exists** (e.g. after switching from macOS to web, or after a page refresh), call `document_open` with the `surface_id` to re-surface the editor panel on their current client.
|
|
39
|
-
|
|
40
31
|
## Creating a new document
|
|
41
32
|
|
|
33
|
+
This is the default path when the user asks you to write something.
|
|
34
|
+
|
|
42
35
|
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
36
|
2. **Write content in Markdown**: Use proper structure (`#` for titles, `##` for sections), **bold**, _italic_, code blocks, tables, lists, blockquotes as appropriate.
|
|
44
37
|
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.
|
|
@@ -59,6 +52,18 @@ When the user requests changes to a document:
|
|
|
59
52
|
- `document_find` + `document_replace_text` — **for everything else**. Fixing typos, renaming terms, swapping sections, reordering content, adjusting formatting, or any edit that touches only part of the document. This is the default choice for edits. It avoids rewriting the entire document and eliminates the risk of accidentally dropping content.
|
|
60
53
|
4. **Do NOT use `document_update` with `mode: "replace"` for targeted edits.** Rewriting the entire document to change a few words or rearrange sections is wasteful and error-prone.
|
|
61
54
|
|
|
55
|
+
## Retrieving existing documents
|
|
56
|
+
|
|
57
|
+
When the user asks to see, open, or pull up a document:
|
|
58
|
+
|
|
59
|
+
1. Check the `<active_documents>` block in your context — it lists all documents in this conversation with their `surface_id` and title.
|
|
60
|
+
2. If the document is NOT in `<active_documents>`, call `document_list` with a `query` matching the document title. For guardian/local users, this searches across previous conversations and sessions.
|
|
61
|
+
3. Once you have the `surface_id`, call `document_open` to open the editor panel. This surfaces the editor on the client and returns document metadata (`surface_id`, `title`, `word_count`) — not the full content. If you need the actual document text, follow up with `document_read`.
|
|
62
|
+
|
|
63
|
+
**Never** search the filesystem, conversation history, or archives to find a document. Always use `document_list` with a `query`.
|
|
64
|
+
|
|
65
|
+
**If the user says they can't see a document you know exists** (e.g. after switching from macOS to web, or after a page refresh), call `document_open` with the `surface_id` to re-surface the editor panel on their current client.
|
|
66
|
+
|
|
62
67
|
## Find & Replace
|
|
63
68
|
|
|
64
69
|
Use `document_find` and `document_replace_text` for surgical edits that target specific text patterns without rewriting the entire document.
|
|
@@ -117,7 +122,7 @@ Users can leave inline comments on documents. Open comments are surfaced in a `<
|
|
|
117
122
|
## Anti-Patterns
|
|
118
123
|
|
|
119
124
|
- **Don't use `app_create` for blog posts, articles, or written content.** Use `document_create` — apps are for interactive content with state/data.
|
|
120
|
-
- **Don't
|
|
125
|
+
- **Don't write the article into the chat response.** Long-form prose goes in the document editor via `document_create`, not in chat and not into a `.md` file in the workspace. Acknowledge what you're doing and stream to the editor.
|
|
121
126
|
- **Don't wait to generate everything before sending.** Stream content in chunks via `document_update` with `mode: "append"` so users see progress in real time.
|
|
122
127
|
|
|
123
128
|
## Usage Notes
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"name": "document_update",
|
|
45
|
-
"description": "
|
|
45
|
+
"description": "Append to or fully replace a document's content. Takes the full Markdown in `content` plus a `mode`: \"append\" adds it to the end (use this to stream generated content in chunks), \"replace\" overwrites the entire document. This tool does NOT do targeted edits — for changing specific words, phrases, or sections, use document_replace_text instead. There is no old/new or find/replace parameter here.",
|
|
46
46
|
"category": "document-editor",
|
|
47
47
|
"risk": "low",
|
|
48
48
|
"input_schema": {
|
|
@@ -23,7 +23,9 @@ import * as acpSteer from "./bundled-skills/acp/tools/acp-steer.js";
|
|
|
23
23
|
import * as appCreate from "./bundled-skills/app-builder/tools/app-create.js";
|
|
24
24
|
import * as appDelete from "./bundled-skills/app-builder/tools/app-delete.js";
|
|
25
25
|
import * as appGenerateIcon from "./bundled-skills/app-builder/tools/app-generate-icon.js";
|
|
26
|
+
import * as appList from "./bundled-skills/app-builder/tools/app-list.js";
|
|
26
27
|
import * as appRefresh from "./bundled-skills/app-builder/tools/app-refresh.js";
|
|
28
|
+
import * as appUpdate from "./bundled-skills/app-builder/tools/app-update.js";
|
|
27
29
|
// ── app-control ────────────────────────────────────────────────────────────────
|
|
28
30
|
import * as appControlClick from "./bundled-skills/app-control/tools/app-control-click.js";
|
|
29
31
|
import * as appControlCombo from "./bundled-skills/app-control/tools/app-control-combo.js";
|
|
@@ -139,9 +141,11 @@ export const bundledToolRegistry = new Map<string, SkillToolScript>([
|
|
|
139
141
|
|
|
140
142
|
// app-builder
|
|
141
143
|
["app-builder:tools/app-create.ts", appCreate],
|
|
144
|
+
["app-builder:tools/app-update.ts", appUpdate],
|
|
142
145
|
["app-builder:tools/app-delete.ts", appDelete],
|
|
143
146
|
["app-builder:tools/app-refresh.ts", appRefresh],
|
|
144
147
|
["app-builder:tools/app-generate-icon.ts", appGenerateIcon],
|
|
148
|
+
["app-builder:tools/app-list.ts", appList],
|
|
145
149
|
|
|
146
150
|
// app-control
|
|
147
151
|
["app-control:tools/app-control-start.ts", appControlStart],
|
|
@@ -17,7 +17,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
17
17
|
patternScan: { profile: "balanced" },
|
|
18
18
|
narrativeRefinement: { profile: "balanced" },
|
|
19
19
|
callAgent: { profile: "balanced" },
|
|
20
|
-
proactiveArtifactBuild: { profile: "balanced" },
|
|
21
20
|
memoryConsolidation: { profile: "balanced" },
|
|
22
21
|
identityIntro: { profile: "balanced" },
|
|
23
22
|
emptyStateGreeting: { profile: "balanced" },
|
|
@@ -26,7 +25,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
26
25
|
profile: "cost-optimized",
|
|
27
26
|
contextWindow: { maxInputTokens: 1000000 },
|
|
28
27
|
},
|
|
29
|
-
memoryV3RouteL1: { profile: "balanced", temperature: 0 },
|
|
30
28
|
memoryV3SelectL2: { profile: "balanced", temperature: 0 },
|
|
31
29
|
recall: {
|
|
32
30
|
profile: "balanced",
|
|
@@ -42,7 +40,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
42
40
|
},
|
|
43
41
|
|
|
44
42
|
filingAgent: { profile: "cost-optimized" },
|
|
45
|
-
proactiveArtifactDecision: { profile: "cost-optimized" },
|
|
46
43
|
memoryExtraction: { profile: "cost-optimized" },
|
|
47
44
|
memoryRetrieval: { profile: "cost-optimized" },
|
|
48
45
|
memoryRetrospective: { profile: "cost-optimized" },
|
|
@@ -26,20 +26,22 @@
|
|
|
26
26
|
"defaultEnabled": false
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
"id": "
|
|
29
|
+
"id": "pre-chat-onboarding-experiment-2026-06-06",
|
|
30
30
|
"scope": "client",
|
|
31
|
-
"key": "
|
|
32
|
-
"label": "
|
|
33
|
-
"description": "
|
|
34
|
-
"defaultEnabled":
|
|
31
|
+
"key": "pre-chat-onboarding-experiment-2026-06-06",
|
|
32
|
+
"label": "Pre-chat Onboarding Experiment 2026-06-06",
|
|
33
|
+
"description": "Pre-chat onboarding experiment with control and variant-a arms. Control shows the full funnel; variant-a shows the condensed pared-down flow.",
|
|
34
|
+
"defaultEnabled": "control",
|
|
35
|
+
"values": ["control", "variant-a"]
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
38
|
"id": "experiment-activation-flow-2026-06-03",
|
|
38
39
|
"scope": "client",
|
|
39
40
|
"key": "experiment-activation-flow-2026-06-03",
|
|
40
41
|
"label": "Activation Flow Experiment 2026-06-03",
|
|
41
|
-
"description": "
|
|
42
|
-
"defaultEnabled":
|
|
42
|
+
"description": "Multivariate activation-flow experiment. control = standard flow; variant-a = activation rail. Targeted via LaunchDarkly.",
|
|
43
|
+
"defaultEnabled": "control",
|
|
44
|
+
"values": ["control", "variant-a"]
|
|
43
45
|
},
|
|
44
46
|
{
|
|
45
47
|
"id": "local-docker-enabled",
|
|
@@ -139,7 +141,7 @@
|
|
|
139
141
|
},
|
|
140
142
|
{
|
|
141
143
|
"id": "multi-platform-assistant",
|
|
142
|
-
"scope": "
|
|
144
|
+
"scope": "client",
|
|
143
145
|
"key": "multi-platform-assistant",
|
|
144
146
|
"label": "Multi-Platform Assistant Switcher",
|
|
145
147
|
"description": "Enable the menu-bar assistant switcher for managing multiple platform-hosted assistants (new/switch/retire)",
|
|
@@ -480,14 +482,6 @@
|
|
|
480
482
|
"label": "Self-intro first message",
|
|
481
483
|
"description": "On the first conversation, send a natural self-introduction (e.g. \"Hi Vela, I'm alex. Nice to meet you.\") on the user's behalf and route it through real LLM inference, instead of serving the canned first greeting. Names come from the onboarding context; falls back to the canned greeting when no name is known. Exposed to clients so pre-hatch onboarding can compute the source-of-truth initial message, and to the assistant so older clients can still be gated server-side. See assistant/src/daemon/first-greeting.ts (buildSelfIntroMessage).",
|
|
482
484
|
"defaultEnabled": false
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
"id": "provider-first-profile-creation",
|
|
486
|
-
"scope": "client",
|
|
487
|
-
"key": "provider-first-profile-creation",
|
|
488
|
-
"label": "Provider-First Profile Creation",
|
|
489
|
-
"description": "New profile creation flow: pick (or inline-create) a provider first, then a model, with pre-filled provider and profile name/key, plus a quick-add \"+\" in the chat composer's Model Profile menu. When off, profile creation uses the previous field order and there is no composer quick-add.",
|
|
490
|
-
"defaultEnabled": false
|
|
491
485
|
}
|
|
492
486
|
]
|
|
493
487
|
}
|
|
@@ -78,6 +78,15 @@ export function resolveCallSiteConfig(
|
|
|
78
78
|
): z.infer<typeof LLMConfigBase> {
|
|
79
79
|
const layers: Mergeable[] = [llm.default as Mergeable];
|
|
80
80
|
|
|
81
|
+
// Effective logit-bias preset, tracked outside the deep-merge so it ties to
|
|
82
|
+
// the single highest-precedence *profile* that wins resolution rather than
|
|
83
|
+
// inheriting from a lower one. Profile layers are appended low→high, and each
|
|
84
|
+
// one fully determines the preset (a profile that omits `logitBias` clears
|
|
85
|
+
// any value a lower-precedence profile set), so the last profile appended
|
|
86
|
+
// wins — matching the merge's own precedence and including the implicit
|
|
87
|
+
// call-site default selected by `effectiveDefault`.
|
|
88
|
+
const biasRef: LogitBiasRef = { preset: undefined };
|
|
89
|
+
|
|
81
90
|
const activeFragment = resolveProfileFragment(llm.activeProfile, llm, opts);
|
|
82
91
|
const overrideFragment = resolveProfileFragment(
|
|
83
92
|
opts.overrideProfile,
|
|
@@ -89,18 +98,32 @@ export function resolveCallSiteConfig(
|
|
|
89
98
|
effectiveDefault(callSite, llm, opts.overrideProfile != null);
|
|
90
99
|
|
|
91
100
|
if (callSite === "mainAgent") {
|
|
92
|
-
appendCallSiteLayers(layers, callSite, llm, site, opts);
|
|
93
|
-
appendProfileLayer(layers, activeFragment);
|
|
94
|
-
appendProfileLayer(layers, overrideFragment);
|
|
101
|
+
appendCallSiteLayers(layers, callSite, llm, site, opts, biasRef);
|
|
102
|
+
appendProfileLayer(layers, activeFragment, biasRef);
|
|
103
|
+
appendProfileLayer(layers, overrideFragment, biasRef);
|
|
95
104
|
} else {
|
|
96
|
-
appendProfileLayer(layers, activeFragment);
|
|
97
|
-
appendProfileLayer(layers, overrideFragment);
|
|
98
|
-
appendCallSiteLayers(layers, callSite, llm, site, opts);
|
|
105
|
+
appendProfileLayer(layers, activeFragment, biasRef);
|
|
106
|
+
appendProfileLayer(layers, overrideFragment, biasRef);
|
|
107
|
+
appendCallSiteLayers(layers, callSite, llm, site, opts, biasRef);
|
|
99
108
|
}
|
|
100
109
|
|
|
101
|
-
|
|
110
|
+
const resolved = finalize(
|
|
111
|
+
deepMerge(...layers.map(withImpliedProviderForKnownModel)),
|
|
112
|
+
);
|
|
113
|
+
// `logitBias` is profile-scoped: the winning profile is its only source.
|
|
114
|
+
// Overwrite — or clear — whatever the deep-merge may have copied from a
|
|
115
|
+
// non-profile layer (`llm.default` or a call-site fragment), so a preset set
|
|
116
|
+
// outside a profile can't apply to a profile that didn't opt in.
|
|
117
|
+
if (biasRef.preset !== undefined) {
|
|
118
|
+
resolved.logitBias = biasRef.preset;
|
|
119
|
+
} else {
|
|
120
|
+
delete (resolved as { logitBias?: unknown }).logitBias;
|
|
121
|
+
}
|
|
122
|
+
return resolved;
|
|
102
123
|
}
|
|
103
124
|
|
|
125
|
+
type LogitBiasRef = { preset: ProfileEntry["logitBias"] };
|
|
126
|
+
|
|
104
127
|
// ---------------------------------------------------------------------------
|
|
105
128
|
// Internal helpers
|
|
106
129
|
// ---------------------------------------------------------------------------
|
|
@@ -261,8 +284,10 @@ function withImpliedProviderForKnownModel(source: Mergeable): Mergeable {
|
|
|
261
284
|
function appendProfileLayer(
|
|
262
285
|
layers: Mergeable[],
|
|
263
286
|
profile: ProfileEntry | undefined,
|
|
287
|
+
biasRef: LogitBiasRef,
|
|
264
288
|
): void {
|
|
265
289
|
if (profile != null) {
|
|
290
|
+
biasRef.preset = profile.logitBias;
|
|
266
291
|
layers.push(profileConfigFragment(profile));
|
|
267
292
|
}
|
|
268
293
|
}
|
|
@@ -273,6 +298,7 @@ function appendCallSiteLayers(
|
|
|
273
298
|
llm: z.infer<typeof LLMSchema>,
|
|
274
299
|
site: z.infer<typeof LLMSchema>["callSites"][LLMCallSite] | undefined,
|
|
275
300
|
opts: ResolveCallSiteOpts,
|
|
301
|
+
biasRef: LogitBiasRef,
|
|
276
302
|
): void {
|
|
277
303
|
if (site != null) {
|
|
278
304
|
if (site.profile != null) {
|
|
@@ -286,6 +312,7 @@ function appendCallSiteLayers(
|
|
|
286
312
|
`LLM call site "${callSite}" references undefined profile "${site.profile}"`,
|
|
287
313
|
);
|
|
288
314
|
}
|
|
315
|
+
biasRef.preset = profileFragment.logitBias;
|
|
289
316
|
layers.push(profileConfigFragment(profileFragment));
|
|
290
317
|
}
|
|
291
318
|
// Strip the `profile` discriminator before merging — it isn't a
|
|
@@ -304,6 +331,11 @@ function profileConfigFragment(profile: ProfileEntry): Mergeable {
|
|
|
304
331
|
// profile before this point), but strip it defensively so it can never
|
|
305
332
|
// leak into the merged `LLMConfigBase`.
|
|
306
333
|
mix: _mix,
|
|
334
|
+
// `logitBias` is profile-identity metadata, not inheritable config: a
|
|
335
|
+
// preset must apply only to the profile that opted in, never bleed from a
|
|
336
|
+
// lower-precedence (e.g. active) profile into one that merely inherited it.
|
|
337
|
+
// `RetryProvider` resolves it from the applied profile, not the merge.
|
|
338
|
+
logitBias: _logitBias,
|
|
307
339
|
...config
|
|
308
340
|
} = profile;
|
|
309
341
|
return config as Mergeable;
|