@vellumai/assistant 0.8.8 → 0.8.9-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/ARCHITECTURE.md +6 -6
- package/bun.lock +2 -2
- 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 +235 -6
- package/package.json +2 -2
- 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 +1 -1
- 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 +5 -4
- 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 +132 -0
- package/src/__tests__/compaction-events.test.ts +5 -5
- package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
- package/src/__tests__/context-overflow-reducer.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -4
- 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 +142 -218
- package/src/__tests__/conversation-agent-loop.test.ts +297 -586
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -4
- package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +14 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +70 -65
- package/src/__tests__/conversation-queue.test.ts +9 -9
- package/src/__tests__/conversation-runtime-assembly.test.ts +923 -231
- package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
- package/src/__tests__/conversation-slash-queue.test.ts +6 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -4
- package/src/__tests__/conversation-speed-override.test.ts +10 -9
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-workspace-cache-state.test.ts +23 -20
- package/src/__tests__/conversation-workspace-injection.test.ts +68 -6
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +14 -11
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- 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 +12 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -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 +1 -1
- 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__/memory-retrieval-hook.test.ts +131 -26
- package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
- package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
- package/src/__tests__/plugin-api-shim.test.ts +6 -9
- package/src/__tests__/plugin-bootstrap.test.ts +12 -23
- package/src/__tests__/plugin-registry.test.ts +3 -49
- package/src/__tests__/plugin-types.test.ts +0 -70
- package/src/__tests__/pre-model-call-sanitize.test.ts +109 -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 +33 -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 +1 -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/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- 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/feature-gate.test.ts +48 -0
- package/src/acp/feature-gate.ts +34 -0
- package/src/acp/prepare-agent-env.ts +80 -27
- package/src/acp/resolve-agent.test.ts +225 -9
- package/src/acp/resolve-agent.ts +122 -17
- 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 +414 -248
- package/src/api/responses/conversation-message.ts +14 -1
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
- package/src/cli/commands/plugins.ts +43 -37
- package/src/cli/lib/__tests__/install-from-github.test.ts +429 -111
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +372 -0
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +220 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +226 -32
- package/src/cli/lib/install-from-github.ts +464 -55
- package/src/cli/lib/plugin-catalog-cache.ts +84 -0
- package/src/cli/lib/plugin-details.ts +409 -0
- package/src/cli/lib/plugin-marketplace.ts +197 -0
- package/src/cli/lib/search-plugins.ts +195 -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 +6 -0
- package/src/config/bundled-skills/acp/SKILL.md +85 -33
- 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 -2
- package/src/config/feature-flag-registry.json +15 -6
- package/src/config/schemas/call-site-catalog.ts +0 -14
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +0 -2
- package/src/context/compactor.ts +22 -4
- package/src/context/strip-injections.ts +8 -2
- package/src/context/window-manager.ts +27 -13
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -35
- package/src/daemon/conversation-agent-loop.ts +175 -1055
- package/src/daemon/conversation-lifecycle.ts +11 -255
- package/src/daemon/conversation-process.ts +8 -136
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +293 -392
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +24 -8
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +404 -57
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/external-plugins-bootstrap.ts +14 -19
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-proxy-preactivation.ts +1 -3
- package/src/daemon/lifecycle.ts +21 -7
- package/src/daemon/server.ts +2 -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__/jobs-worker-v2-schedule.test.ts +87 -0
- package/src/memory/conversation-crud.ts +29 -19
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/db-init.ts +2 -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/index.ts +1 -0
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +3 -3
- package/src/memory/v2/consolidation-job.ts +13 -4
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +6 -5
- package/src/plugin-api/types.ts +75 -0
- package/src/plugins/defaults/compaction/compact.ts +59 -0
- package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +7 -7
- package/src/plugins/defaults/compaction/manager-store.ts +57 -0
- package/src/plugins/defaults/compaction/package.json +1 -2
- 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 +135 -26
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +184 -74
- 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/unified-turn-context.ts +223 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +9 -6
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +8 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +10 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +16 -17
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +9 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +5 -2
- 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 +75 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +15 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/provider-blocks.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +7 -3
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +7 -7
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +32 -94
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +1 -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/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/templates/BOOTSTRAP-ACTIVATION-RAIL.md +35 -3
- 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 +315 -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__/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 +89 -25
- package/src/runtime/routes/acp-routes.ts +81 -29
- 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/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 +28 -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/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 +16 -6
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +337 -35
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/signals/cancel.ts +2 -4
- package/src/subagent/manager.ts +21 -5
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +8 -2
- package/src/tools/acp/spawn.test.ts +176 -195
- 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/filesystem/write.ts +34 -0
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/ui-surface/definitions.ts +25 -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/__tests__/plugin-external-api.test.ts +0 -68
- package/src/daemon/wake-target-adapter.ts +0 -253
- 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/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/plugins/external-api.ts +0 -104
- 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/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
- /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__/health.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/provider-blocks.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +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}/core.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}/health.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.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" },
|
|
@@ -42,7 +41,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
42
41
|
},
|
|
43
42
|
|
|
44
43
|
filingAgent: { profile: "cost-optimized" },
|
|
45
|
-
proactiveArtifactDecision: { profile: "cost-optimized" },
|
|
46
44
|
memoryExtraction: { profile: "cost-optimized" },
|
|
47
45
|
memoryRetrieval: { profile: "cost-optimized" },
|
|
48
46
|
memoryRetrospective: { profile: "cost-optimized" },
|
|
@@ -26,12 +26,13 @@
|
|
|
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",
|
|
@@ -139,7 +140,7 @@
|
|
|
139
140
|
},
|
|
140
141
|
{
|
|
141
142
|
"id": "multi-platform-assistant",
|
|
142
|
-
"scope": "
|
|
143
|
+
"scope": "client",
|
|
143
144
|
"key": "multi-platform-assistant",
|
|
144
145
|
"label": "Multi-Platform Assistant Switcher",
|
|
145
146
|
"description": "Enable the menu-bar assistant switcher for managing multiple platform-hosted assistants (new/switch/retire)",
|
|
@@ -488,6 +489,14 @@
|
|
|
488
489
|
"label": "Provider-First Profile Creation",
|
|
489
490
|
"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
491
|
"defaultEnabled": false
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"id": "acp",
|
|
495
|
+
"scope": "assistant",
|
|
496
|
+
"key": "acp",
|
|
497
|
+
"label": "ACP Coding Agents",
|
|
498
|
+
"description": "Enable spawning and steering external coding agents (Claude Code, Codex, Gemini) via the Agent Client Protocol. Alternative gate to the acp.enabled workspace config field; either enables the subsystem.",
|
|
499
|
+
"defaultEnabled": false
|
|
491
500
|
}
|
|
492
501
|
]
|
|
493
502
|
}
|
|
@@ -300,20 +300,6 @@ const CATALOG_RECORD: CatalogRecord = {
|
|
|
300
300
|
description: "General-purpose LLM inference call site for skill use.",
|
|
301
301
|
domain: "skills",
|
|
302
302
|
},
|
|
303
|
-
proactiveArtifactDecision: {
|
|
304
|
-
id: "proactiveArtifactDecision",
|
|
305
|
-
displayName: "Proactive Artifact Decision",
|
|
306
|
-
description:
|
|
307
|
-
"Decides what personalized artifact to build for new users based on conversation context.",
|
|
308
|
-
domain: "agentLoop",
|
|
309
|
-
},
|
|
310
|
-
proactiveArtifactBuild: {
|
|
311
|
-
id: "proactiveArtifactBuild",
|
|
312
|
-
displayName: "Proactive Artifact Build",
|
|
313
|
-
description:
|
|
314
|
-
"Builds the personalized artifact in a background conversation with tool access.",
|
|
315
|
-
domain: "agentLoop",
|
|
316
|
-
},
|
|
317
303
|
homeGreeting: {
|
|
318
304
|
id: "homeGreeting",
|
|
319
305
|
displayName: "Home Greeting",
|
|
@@ -56,6 +56,15 @@ export const HeartbeatConfigSchema = z
|
|
|
56
56
|
.describe(
|
|
57
57
|
"Maximum heartbeats that can run consecutively without a guardian message. Counter resets when the guardian sends a message. Set to null for unlimited.",
|
|
58
58
|
),
|
|
59
|
+
maxDailyRuns: z
|
|
60
|
+
.number({ error: "heartbeat.maxDailyRuns must be a number" })
|
|
61
|
+
.int("heartbeat.maxDailyRuns must be an integer")
|
|
62
|
+
.positive("heartbeat.maxDailyRuns must be a positive integer")
|
|
63
|
+
.nullable()
|
|
64
|
+
.default(2)
|
|
65
|
+
.describe(
|
|
66
|
+
"Maximum heartbeats that can run per calendar day. Resets at midnight local time. Set to null for unlimited.",
|
|
67
|
+
),
|
|
59
68
|
disposition: z
|
|
60
69
|
.string({ error: "heartbeat.disposition must be a string" })
|
|
61
70
|
.default(
|
package/src/context/compactor.ts
CHANGED
|
@@ -22,6 +22,7 @@ import { optimizeImageForTransport } from "../agent/image-optimize.js";
|
|
|
22
22
|
import type { CompactionConfig } from "../config/schemas/compaction.js";
|
|
23
23
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
24
24
|
import { filterMessagesForUntrustedActor } from "../daemon/message-provenance.js";
|
|
25
|
+
import { stripHistoricalWebSearchResults } from "../daemon/web-search-history.js";
|
|
25
26
|
import {
|
|
26
27
|
getAttachmentContent,
|
|
27
28
|
getAttachmentMetadataForMessage,
|
|
@@ -685,6 +686,25 @@ function extractTextFromResponse(content: ContentBlock[]): string {
|
|
|
685
686
|
.join("\n");
|
|
686
687
|
}
|
|
687
688
|
|
|
689
|
+
// Build the outbound message list for a compaction provider call: convert
|
|
690
|
+
// historical web_search_tool_result blocks to text, then append the
|
|
691
|
+
// summarization instruction at the tail.
|
|
692
|
+
//
|
|
693
|
+
// Anthropic's opaque `encrypted_content` tokens are route-scoped and expire, so
|
|
694
|
+
// replaying a stale one is rejected with `Invalid encrypted_content in
|
|
695
|
+
// search_result block`. Sanitizing here — the single seam every compaction
|
|
696
|
+
// provider call funnels through — keeps that error away from both the
|
|
697
|
+
// assistant-driven and emergency summarization calls. Only this outbound copy
|
|
698
|
+
// is sanitized; tail resolution and the persisted compaction result read the
|
|
699
|
+
// caller's original messages, so durable history keeps the rich blocks. The
|
|
700
|
+
// instruction stays at the tail so the prefix cache stays warm.
|
|
701
|
+
function buildCompactionRequest(
|
|
702
|
+
history: Message[],
|
|
703
|
+
instruction: Message,
|
|
704
|
+
): Message[] {
|
|
705
|
+
return [...stripHistoricalWebSearchResults(history).messages, instruction];
|
|
706
|
+
}
|
|
707
|
+
|
|
688
708
|
export async function runAssistantDrivenCompaction(
|
|
689
709
|
args: CompactionRunArgs,
|
|
690
710
|
): Promise<CompactionRunResult> {
|
|
@@ -718,9 +738,7 @@ export async function runAssistantDrivenCompaction(
|
|
|
718
738
|
manifestText,
|
|
719
739
|
);
|
|
720
740
|
|
|
721
|
-
|
|
722
|
-
// stays warm.
|
|
723
|
-
const requestMessages = [...args.messages, instruction];
|
|
741
|
+
const requestMessages = buildCompactionRequest(args.messages, instruction);
|
|
724
742
|
|
|
725
743
|
let response: ProviderResponse;
|
|
726
744
|
try {
|
|
@@ -1090,7 +1108,7 @@ export async function runEmergencyCompaction(
|
|
|
1090
1108
|
role: "user",
|
|
1091
1109
|
content: [{ type: "text", text: EMERGENCY_COMPACTION_PROMPT }],
|
|
1092
1110
|
};
|
|
1093
|
-
const requestMessages =
|
|
1111
|
+
const requestMessages = buildCompactionRequest(prefix, instruction);
|
|
1094
1112
|
|
|
1095
1113
|
let response: ProviderResponse;
|
|
1096
1114
|
try {
|
|
@@ -87,8 +87,14 @@ const RUNTIME_INJECTION_PREFIXES: InjectionMatcher[] = [
|
|
|
87
87
|
{ prefix: "<info>\n", suffix: "\n</info>" },
|
|
88
88
|
"<voice_call_control>",
|
|
89
89
|
"<workspace_top_level>", // backward-compat: strip legacy workspace blocks
|
|
90
|
-
//
|
|
91
|
-
//
|
|
90
|
+
// The `<workspace>` top-level block is stripped so each compaction re-injects
|
|
91
|
+
// a fresh directory snapshot rather than carrying a stale listing into the
|
|
92
|
+
// summary — matching the `<knowledge_base>`/`<NOW.md>` cadence and keeping the
|
|
93
|
+
// `workspace-context` injector's presence detection in lockstep (the block is
|
|
94
|
+
// present exactly when compaction would strip it). The full `{ prefix, suffix }`
|
|
95
|
+
// wrapper shape ensures user-authored text merely starting with `<workspace>\n`
|
|
96
|
+
// is never mistaken for an injected block.
|
|
97
|
+
{ prefix: "<workspace>\n", suffix: "\n</workspace>" },
|
|
92
98
|
"<temporal_context>\nToday:", // backward-compat: strip legacy temporal blocks
|
|
93
99
|
"<active_subagents>",
|
|
94
100
|
"<active_workspace>",
|